blob: 38d7b2c4d387676bedeed50a9550de9bec0bff8d [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
rch16c74d1d2016-04-22 06:14:077#include <memory>
8
zhongyi23960342016-04-12 23:13:209#include "base/strings/string_util.h"
[email protected]38b3fd12013-06-18 08:19:0110#include "net/quic/crypto/channel_id.h"
[email protected]c244c5a12013-05-07 20:55:0411#include "net/quic/crypto/common_cert_set.h"
[email protected]ef95114d2013-04-17 17:57:0112#include "net/quic/crypto/crypto_handshake.h"
[email protected]8e01c062013-10-31 07:35:3113#include "net/quic/crypto/quic_crypto_server_config.h"
[email protected]14e8106c2013-03-14 16:25:3314#include "net/quic/crypto/quic_decrypter.h"
15#include "net/quic/crypto/quic_encrypter.h"
[email protected]ef95114d2013-04-17 17:57:0116#include "net/quic/crypto/quic_random.h"
17#include "net/quic/quic_clock.h"
[email protected]ed3fc15d2013-03-08 18:37:4418#include "net/quic/quic_crypto_client_stream.h"
19#include "net/quic/quic_crypto_server_stream.h"
20#include "net/quic/quic_crypto_stream.h"
[email protected]257f24f2014-04-01 09:15:3721#include "net/quic/quic_server_id.h"
rch28f6469d2016-03-13 21:13:0822#include "net/quic/quic_utils.h"
[email protected]2532de12013-05-09 12:29:3323#include "net/quic/test_tools/quic_connection_peer.h"
rch1e543ec2015-03-29 07:04:4024#include "net/quic/test_tools/quic_framer_peer.h"
[email protected]ed3fc15d2013-03-08 18:37:4425#include "net/quic/test_tools/quic_test_utils.h"
26#include "net/quic/test_tools/simple_quic_framer.h"
[email protected]ed3fc15d2013-03-08 18:37:4427
[email protected]14e8106c2013-03-14 16:25:3328using base::StringPiece;
[email protected]691f45a982013-11-19 10:52:0429using std::make_pair;
30using std::pair;
[email protected]ccc66e8a2013-03-26 08:26:1431using std::string;
[email protected]fe053f92013-04-23 20:18:5532using std::vector;
[email protected]14e8106c2013-03-14 16:25:3333
[email protected]ed3fc15d2013-03-08 18:37:4434namespace net {
35namespace test {
36
37namespace {
38
[email protected]fe053f92013-04-23 20:18:5539// CryptoFramerVisitor is a framer visitor that records handshake messages.
40class CryptoFramerVisitor : public CryptoFramerVisitorInterface {
41 public:
rjshaded5ced072015-12-18 19:26:0242 CryptoFramerVisitor() : error_(false) {}
[email protected]ed3fc15d2013-03-08 18:37:4443
dchengb03027d2014-10-21 12:00:2044 void OnError(CryptoFramer* framer) override { error_ = true; }
[email protected]ed3fc15d2013-03-08 18:37:4445
dchengb03027d2014-10-21 12:00:2046 void OnHandshakeMessage(const CryptoHandshakeMessage& message) override {
[email protected]fe053f92013-04-23 20:18:5547 messages_.push_back(message);
48 }
[email protected]ed3fc15d2013-03-08 18:37:4449
rjshaded5ced072015-12-18 19:26:0250 bool error() const { return error_; }
[email protected]ed3fc15d2013-03-08 18:37:4451
rjshaded5ced072015-12-18 19:26:0252 const vector<CryptoHandshakeMessage>& messages() const { return messages_; }
[email protected]ed3fc15d2013-03-08 18:37:4453
[email protected]fe053f92013-04-23 20:18:5554 private:
55 bool error_;
56 vector<CryptoHandshakeMessage> messages_;
57};
58
[email protected]0bbeb6972013-05-23 04:10:2159// HexChar parses |c| as a hex character. If valid, it sets |*value| to the
60// value of the hex character and returns true. Otherwise it returns false.
Avi Drissman13fc8932015-12-20 04:40:4661bool HexChar(char c, uint8_t* value) {
zhongyif74ee622016-04-13 17:59:2262 if (c >= '0' && c <= '9') {
[email protected]0bbeb6972013-05-23 04:10:2163 *value = c - '0';
64 return true;
65 }
66 if (c >= 'a' && c <= 'f') {
[email protected]b064310782013-05-30 21:12:1767 *value = c - 'a' + 10;
[email protected]0bbeb6972013-05-23 04:10:2168 return true;
69 }
70 if (c >= 'A' && c <= 'F') {
[email protected]b064310782013-05-30 21:12:1771 *value = c - 'A' + 10;
[email protected]0bbeb6972013-05-23 04:10:2172 return true;
73 }
74 return false;
75}
76
[email protected]6fc79ea2014-07-10 04:30:2377// A ChannelIDSource that works in asynchronous mode unless the |callback|
rtennetibe635732014-10-02 22:51:4278// argument to GetChannelIDKey is nullptr.
[email protected]6fc79ea2014-07-10 04:30:2379class AsyncTestChannelIDSource : public ChannelIDSource,
[email protected]dc6094a2014-07-23 01:50:0480 public CryptoTestUtils::CallbackSource {
[email protected]6fc79ea2014-07-10 04:30:2381 public:
82 // Takes ownership of |sync_source|, a synchronous ChannelIDSource.
83 explicit AsyncTestChannelIDSource(ChannelIDSource* sync_source)
84 : sync_source_(sync_source) {}
dchengb03027d2014-10-21 12:00:2085 ~AsyncTestChannelIDSource() override {}
[email protected]6fc79ea2014-07-10 04:30:2386
87 // ChannelIDSource implementation.
dchengb03027d2014-10-21 12:00:2088 QuicAsyncStatus GetChannelIDKey(const string& hostname,
danakjad1777e2016-04-16 00:56:4289 std::unique_ptr<ChannelIDKey>* channel_id_key,
dchengb03027d2014-10-21 12:00:2090 ChannelIDSourceCallback* callback) override {
[email protected]6fc79ea2014-07-10 04:30:2391 // Synchronous mode.
92 if (!callback) {
rtennetibe635732014-10-02 22:51:4293 return sync_source_->GetChannelIDKey(hostname, channel_id_key, nullptr);
[email protected]6fc79ea2014-07-10 04:30:2394 }
95
96 // Asynchronous mode.
97 QuicAsyncStatus status =
rtennetibe635732014-10-02 22:51:4298 sync_source_->GetChannelIDKey(hostname, &channel_id_key_, nullptr);
[email protected]6fc79ea2014-07-10 04:30:2399 if (status != QUIC_SUCCESS) {
100 return QUIC_FAILURE;
101 }
102 callback_.reset(callback);
103 return QUIC_PENDING;
104 }
105
[email protected]dc6094a2014-07-23 01:50:04106 // CallbackSource implementation.
dchengb03027d2014-10-21 12:00:20107 void RunPendingCallbacks() override {
[email protected]6fc79ea2014-07-10 04:30:23108 if (callback_.get()) {
109 callback_->Run(&channel_id_key_);
110 callback_.reset();
111 }
112 }
113
114 private:
danakjad1777e2016-04-16 00:56:42115 std::unique_ptr<ChannelIDSource> sync_source_;
116 std::unique_ptr<ChannelIDSourceCallback> callback_;
117 std::unique_ptr<ChannelIDKey> channel_id_key_;
[email protected]6fc79ea2014-07-10 04:30:23118};
119
[email protected]ed3fc15d2013-03-08 18:37:44120} // anonymous namespace
121
rjshadec86dbfa2015-11-12 20:16:25122CryptoTestUtils::FakeServerOptions::FakeServerOptions()
123 : token_binding_enabled(false) {}
124
[email protected]899951652013-05-16 12:52:39125CryptoTestUtils::FakeClientOptions::FakeClientOptions()
rjshadec86dbfa2015-11-12 20:16:25126 : channel_id_enabled(false),
127 channel_id_source_async(false),
128 token_binding_enabled(false) {}
[email protected]899951652013-05-16 12:52:39129
[email protected]ed3fc15d2013-03-08 18:37:44130// static
[email protected]fe053f92013-04-23 20:18:55131int CryptoTestUtils::HandshakeWithFakeServer(
rch99b644c2015-11-04 05:25:28132 MockConnectionHelper* helper,
rch16c74d1d2016-04-22 06:14:07133 MockAlarmFactory* alarm_factory,
[email protected]ed3fc15d2013-03-08 18:37:44134 PacketSavingConnection* client_conn,
rjshadec86dbfa2015-11-12 20:16:25135 QuicCryptoClientStream* client,
136 const FakeServerOptions& options) {
rch16c74d1d2016-04-22 06:14:07137 PacketSavingConnection* server_conn =
138 new PacketSavingConnection(helper, alarm_factory, Perspective::IS_SERVER,
139 client_conn->supported_versions());
rtennetid39bd762015-06-12 01:05:52140
141 QuicConfig config = DefaultQuicConfig();
[email protected]b064310782013-05-30 21:12:17142 QuicCryptoServerConfig crypto_config(QuicCryptoServerConfig::TESTING,
rch1fe2eeb2015-10-26 14:45:57143 QuicRandom::GetInstance(),
144 ProofSourceForTesting());
rjshaded069aaee2016-03-11 20:42:17145 QuicCompressedCertsCache compressed_certs_cache(
146 QuicCompressedCertsCache::kQuicCompressedCertsCacheSize);
rtennetid39bd762015-06-12 01:05:52147 SetupCryptoServerConfigForTest(server_conn->clock(),
148 server_conn->random_generator(), &config,
rjshadec86dbfa2015-11-12 20:16:25149 &crypto_config, options);
[email protected]ccb34212014-07-18 09:27:50150
rjshaded069aaee2016-03-11 20:42:17151 TestQuicSpdyServerSession server_session(server_conn, config, &crypto_config,
152 &compressed_certs_cache);
[email protected]ed3fc15d2013-03-08 18:37:44153
154 // The client's handshake must have been started already.
rtennetib6ac61a52015-02-11 20:20:52155 CHECK_NE(0u, client_conn->encrypted_packets_.size());
[email protected]ed3fc15d2013-03-08 18:37:44156
rtennetid39bd762015-06-12 01:05:52157 CommunicateHandshakeMessages(client_conn, client, server_conn,
158 server_session.GetCryptoStream());
rtennetid39bd762015-06-12 01:05:52159 CompareClientAndServerKeys(client, server_session.GetCryptoStream());
[email protected]fe053f92013-04-23 20:18:55160
161 return client->num_sent_client_hellos();
[email protected]ed3fc15d2013-03-08 18:37:44162}
163
164// static
[email protected]fe053f92013-04-23 20:18:55165int CryptoTestUtils::HandshakeWithFakeClient(
rch99b644c2015-11-04 05:25:28166 MockConnectionHelper* helper,
rch16c74d1d2016-04-22 06:14:07167 MockAlarmFactory* alarm_factory,
[email protected]ed3fc15d2013-03-08 18:37:44168 PacketSavingConnection* server_conn,
[email protected]899951652013-05-16 12:52:39169 QuicCryptoServerStream* server,
zhongyic92bc492015-09-22 19:14:36170 const QuicServerId& server_id,
[email protected]899951652013-05-16 12:52:39171 const FakeClientOptions& options) {
rtenneti6f48aa92015-03-16 02:18:48172 PacketSavingConnection* client_conn =
rch16c74d1d2016-04-22 06:14:07173 new PacketSavingConnection(helper, alarm_factory, Perspective::IS_CLIENT);
rtenneti85d89712014-11-20 03:32:24174 // Advance the time, because timers do not like uninitialized times.
175 client_conn->AdvanceTime(QuicTime::Delta::FromSeconds(1));
[email protected]ef95114d2013-04-17 17:57:01176
rch1fe2eeb2015-10-26 14:45:57177 QuicCryptoClientConfig crypto_config(ProofVerifierForTesting());
rtennetibe635732014-10-02 22:51:42178 AsyncTestChannelIDSource* async_channel_id_source = nullptr;
[email protected]b064310782013-05-30 21:12:17179 if (options.channel_id_enabled) {
[email protected]6fc79ea2014-07-10 04:30:23180 ChannelIDSource* source = ChannelIDSourceForTesting();
181 if (options.channel_id_source_async) {
182 async_channel_id_source = new AsyncTestChannelIDSource(source);
183 source = async_channel_id_source;
184 }
185 crypto_config.SetChannelIDSource(source);
[email protected]b064310782013-05-30 21:12:17186 }
rjshadec86dbfa2015-11-12 20:16:25187 if (options.token_binding_enabled) {
188 crypto_config.tb_key_params.push_back(kP256);
189 }
rtennetib865eb82015-06-17 20:21:46190 TestQuicSpdyClientSession client_session(client_conn, DefaultQuicConfig(),
191 server_id, &crypto_config);
[email protected]ed3fc15d2013-03-08 18:37:44192
rch28f6469d2016-03-13 21:13:08193 EXPECT_CALL(client_session, OnProofValid(testing::_))
194 .Times(testing::AnyNumber());
rtennetid39bd762015-06-12 01:05:52195 client_session.GetCryptoStream()->CryptoConnect();
rtennetib6ac61a52015-02-11 20:20:52196 CHECK_EQ(1u, client_conn->encrypted_packets_.size());
[email protected]ed3fc15d2013-03-08 18:37:44197
[email protected]dc6094a2014-07-23 01:50:04198 CommunicateHandshakeMessagesAndRunCallbacks(
rtennetid39bd762015-06-12 01:05:52199 client_conn, client_session.GetCryptoStream(), server_conn, server,
200 async_channel_id_source);
[email protected]14e8106c2013-03-14 16:25:33201
rtennetid39bd762015-06-12 01:05:52202 CompareClientAndServerKeys(client_session.GetCryptoStream(), server);
[email protected]fe053f92013-04-23 20:18:55203
[email protected]38b3fd12013-06-18 08:19:01204 if (options.channel_id_enabled) {
danakjad1777e2016-04-16 00:56:42205 std::unique_ptr<ChannelIDKey> channel_id_key;
rtennetibe635732014-10-02 22:51:42206 QuicAsyncStatus status = crypto_config.channel_id_source()->GetChannelIDKey(
zhongyic92bc492015-09-22 19:14:36207 server_id.host(), &channel_id_key, nullptr);
[email protected]05bfc260f2014-06-07 06:31:25208 EXPECT_EQ(QUIC_SUCCESS, status);
[email protected]03dd32532014-05-30 07:11:25209 EXPECT_EQ(channel_id_key->SerializeKey(),
210 server->crypto_negotiated_params().channel_id);
rtennetid39bd762015-06-12 01:05:52211 EXPECT_EQ(
212 options.channel_id_source_async,
213 client_session.GetCryptoStream()->WasChannelIDSourceCallbackRun());
[email protected]38b3fd12013-06-18 08:19:01214 }
215
rtennetid39bd762015-06-12 01:05:52216 return client_session.GetCryptoStream()->num_sent_client_hellos();
[email protected]14e8106c2013-03-14 16:25:33217}
218
219// static
[email protected]ef95114d2013-04-17 17:57:01220void CryptoTestUtils::SetupCryptoServerConfigForTest(
221 const QuicClock* clock,
222 QuicRandom* rand,
223 QuicConfig* config,
rjshadec86dbfa2015-11-12 20:16:25224 QuicCryptoServerConfig* crypto_config,
225 const FakeServerOptions& fake_options) {
[email protected]b064310782013-05-30 21:12:17226 QuicCryptoServerConfig::ConfigOptions options;
227 options.channel_id_enabled = true;
rjshadec86dbfa2015-11-12 20:16:25228 options.token_binding_enabled = fake_options.token_binding_enabled;
danakjad1777e2016-04-16 00:56:42229 std::unique_ptr<CryptoHandshakeMessage> scfg(
[email protected]b064310782013-05-30 21:12:17230 crypto_config->AddDefaultConfig(rand, clock, options));
[email protected]ef95114d2013-04-17 17:57:01231}
232
233// static
[email protected]0bbeb6972013-05-23 04:10:21234void CryptoTestUtils::CommunicateHandshakeMessages(
235 PacketSavingConnection* a_conn,
236 QuicCryptoStream* a,
237 PacketSavingConnection* b_conn,
238 QuicCryptoStream* b) {
rtennetibe635732014-10-02 22:51:42239 CommunicateHandshakeMessagesAndRunCallbacks(a_conn, a, b_conn, b, nullptr);
[email protected]6fc79ea2014-07-10 04:30:23240}
241
242// static
[email protected]dc6094a2014-07-23 01:50:04243void CryptoTestUtils::CommunicateHandshakeMessagesAndRunCallbacks(
[email protected]6fc79ea2014-07-10 04:30:23244 PacketSavingConnection* a_conn,
245 QuicCryptoStream* a,
246 PacketSavingConnection* b_conn,
247 QuicCryptoStream* b,
[email protected]dc6094a2014-07-23 01:50:04248 CallbackSource* callback_source) {
[email protected]0bbeb6972013-05-23 04:10:21249 size_t a_i = 0, b_i = 0;
250 while (!a->handshake_confirmed()) {
rtennetib6ac61a52015-02-11 20:20:52251 ASSERT_GT(a_conn->encrypted_packets_.size(), a_i);
252 VLOG(1) << "Processing " << a_conn->encrypted_packets_.size() - a_i
253 << " packets a->b";
[email protected]0bbeb6972013-05-23 04:10:21254 MovePackets(a_conn, &a_i, b, b_conn);
[email protected]dc6094a2014-07-23 01:50:04255 if (callback_source) {
256 callback_source->RunPendingCallbacks();
[email protected]6fc79ea2014-07-10 04:30:23257 }
[email protected]0bbeb6972013-05-23 04:10:21258
rtennetib6ac61a52015-02-11 20:20:52259 ASSERT_GT(b_conn->encrypted_packets_.size(), b_i);
260 VLOG(1) << "Processing " << b_conn->encrypted_packets_.size() - b_i
261 << " packets b->a";
[email protected]0bbeb6972013-05-23 04:10:21262 MovePackets(b_conn, &b_i, a, a_conn);
[email protected]dc6094a2014-07-23 01:50:04263 if (callback_source) {
264 callback_source->RunPendingCallbacks();
[email protected]6fc79ea2014-07-10 04:30:23265 }
[email protected]0bbeb6972013-05-23 04:10:21266 }
267}
268
[email protected]b694e48c2014-03-18 17:10:13269// static
[email protected]691f45a982013-11-19 10:52:04270pair<size_t, size_t> CryptoTestUtils::AdvanceHandshake(
271 PacketSavingConnection* a_conn,
272 QuicCryptoStream* a,
273 size_t a_i,
274 PacketSavingConnection* b_conn,
275 QuicCryptoStream* b,
276 size_t b_i) {
rtennetib6ac61a52015-02-11 20:20:52277 VLOG(1) << "Processing " << a_conn->encrypted_packets_.size() - a_i
278 << " packets a->b";
[email protected]691f45a982013-11-19 10:52:04279 MovePackets(a_conn, &a_i, b, b_conn);
280
rtennetib6ac61a52015-02-11 20:20:52281 VLOG(1) << "Processing " << b_conn->encrypted_packets_.size() - b_i
282 << " packets b->a";
283 if (b_conn->encrypted_packets_.size() - b_i == 2) {
284 VLOG(1) << "here";
[email protected]691f45a982013-11-19 10:52:04285 }
286 MovePackets(b_conn, &b_i, a, a_conn);
287
rtenneti16a20772015-02-17 18:58:48288 return std::make_pair(a_i, b_i);
[email protected]691f45a982013-11-19 10:52:04289}
290
[email protected]0bbeb6972013-05-23 04:10:21291// static
[email protected]ccc66e8a2013-03-26 08:26:14292string CryptoTestUtils::GetValueForTag(const CryptoHandshakeMessage& message,
[email protected]2532de12013-05-09 12:29:33293 QuicTag tag) {
294 QuicTagValueMap::const_iterator it = message.tag_value_map().find(tag);
[email protected]ccc66e8a2013-03-26 08:26:14295 if (it == message.tag_value_map().end()) {
296 return string();
297 }
298 return it->second;
299}
300
[email protected]2532de12013-05-09 12:29:33301class MockCommonCertSets : public CommonCertSets {
[email protected]c244c5a12013-05-07 20:55:04302 public:
Avi Drissman13fc8932015-12-20 04:40:46303 MockCommonCertSets(StringPiece cert, uint64_t hash, uint32_t index)
rjshaded5ced072015-12-18 19:26:02304 : cert_(cert.as_string()), hash_(hash), index_(index) {}
[email protected]c244c5a12013-05-07 20:55:04305
dchengb03027d2014-10-21 12:00:20306 StringPiece GetCommonHashes() const override {
[email protected]c244c5a12013-05-07 20:55:04307 CHECK(false) << "not implemented";
308 return StringPiece();
309 }
310
Avi Drissman13fc8932015-12-20 04:40:46311 StringPiece GetCert(uint64_t hash, uint32_t index) const override {
[email protected]c244c5a12013-05-07 20:55:04312 if (hash == hash_ && index == index_) {
313 return cert_;
314 }
315 return StringPiece();
316 }
317
dchengb03027d2014-10-21 12:00:20318 bool MatchCert(StringPiece cert,
319 StringPiece common_set_hashes,
Avi Drissman13fc8932015-12-20 04:40:46320 uint64_t* out_hash,
321 uint32_t* out_index) const override {
[email protected]c244c5a12013-05-07 20:55:04322 if (cert != cert_) {
323 return false;
324 }
325
Avi Drissman13fc8932015-12-20 04:40:46326 if (common_set_hashes.size() % sizeof(uint64_t) != 0) {
[email protected]c244c5a12013-05-07 20:55:04327 return false;
328 }
329 bool client_has_set = false;
Avi Drissman13fc8932015-12-20 04:40:46330 for (size_t i = 0; i < common_set_hashes.size(); i += sizeof(uint64_t)) {
331 uint64_t hash;
[email protected]c244c5a12013-05-07 20:55:04332 memcpy(&hash, common_set_hashes.data() + i, sizeof(hash));
333 if (hash == hash_) {
334 client_has_set = true;
335 break;
336 }
337 }
338
339 if (!client_has_set) {
340 return false;
341 }
342
343 *out_hash = hash_;
344 *out_index = index_;
345 return true;
346 }
347
348 private:
349 const string cert_;
Avi Drissman13fc8932015-12-20 04:40:46350 const uint64_t hash_;
351 const uint32_t index_;
[email protected]c244c5a12013-05-07 20:55:04352};
353
[email protected]2532de12013-05-09 12:29:33354CommonCertSets* CryptoTestUtils::MockCommonCertSets(StringPiece cert,
Avi Drissman13fc8932015-12-20 04:40:46355 uint64_t hash,
356 uint32_t index) {
[email protected]2532de12013-05-09 12:29:33357 return new class MockCommonCertSets(cert, hash, index);
[email protected]c244c5a12013-05-07 20:55:04358}
359
rch94e52bc2015-12-06 04:28:26360// static
361void CryptoTestUtils::FillInDummyReject(CryptoHandshakeMessage* rej,
362 bool reject_is_stateless) {
363 if (reject_is_stateless) {
364 rej->set_tag(kSREJ);
365 } else {
366 rej->set_tag(kREJ);
367 }
368
369 // Minimum SCFG that passes config validation checks.
370 // clang-format off
371 unsigned char scfg[] = {
372 // SCFG
373 0x53, 0x43, 0x46, 0x47,
374 // num entries
375 0x01, 0x00,
376 // padding
377 0x00, 0x00,
378 // EXPY
379 0x45, 0x58, 0x50, 0x59,
380 // EXPY end offset
381 0x08, 0x00, 0x00, 0x00,
382 // Value
383 '1', '2', '3', '4',
384 '5', '6', '7', '8'
385 };
386 // clang-format on
387 rej->SetValue(kSCFG, scfg);
388 rej->SetStringPiece(kServerNonceTag, "SERVER_NONCE");
389 vector<QuicTag> reject_reasons;
390 reject_reasons.push_back(CLIENT_NONCE_INVALID_FAILURE);
391 rej->SetVector(kRREJ, reject_reasons);
392}
393
[email protected]14e8106c2013-03-14 16:25:33394void CryptoTestUtils::CompareClientAndServerKeys(
395 QuicCryptoClientStream* client,
396 QuicCryptoServerStream* server) {
rch1e543ec2015-03-29 07:04:40397 QuicFramer* client_framer =
398 QuicConnectionPeer::GetFramer(client->session()->connection());
399 QuicFramer* server_framer =
400 QuicConnectionPeer::GetFramer(server->session()->connection());
[email protected]8ba81212013-05-03 13:11:48401 const QuicEncrypter* client_encrypter(
rch1e543ec2015-03-29 07:04:40402 QuicFramerPeer::GetEncrypter(client_framer, ENCRYPTION_INITIAL));
[email protected]8ba81212013-05-03 13:11:48403 const QuicDecrypter* client_decrypter(
[email protected]2532de12013-05-09 12:29:33404 client->session()->connection()->decrypter());
405 const QuicEncrypter* client_forward_secure_encrypter(
rch1e543ec2015-03-29 07:04:40406 QuicFramerPeer::GetEncrypter(client_framer, ENCRYPTION_FORWARD_SECURE));
[email protected]2532de12013-05-09 12:29:33407 const QuicDecrypter* client_forward_secure_decrypter(
[email protected]8ba81212013-05-03 13:11:48408 client->session()->connection()->alternative_decrypter());
409 const QuicEncrypter* server_encrypter(
rch1e543ec2015-03-29 07:04:40410 QuicFramerPeer::GetEncrypter(server_framer, ENCRYPTION_INITIAL));
[email protected]8ba81212013-05-03 13:11:48411 const QuicDecrypter* server_decrypter(
412 server->session()->connection()->decrypter());
[email protected]2532de12013-05-09 12:29:33413 const QuicEncrypter* server_forward_secure_encrypter(
rch1e543ec2015-03-29 07:04:40414 QuicFramerPeer::GetEncrypter(server_framer, ENCRYPTION_FORWARD_SECURE));
[email protected]2532de12013-05-09 12:29:33415 const QuicDecrypter* server_forward_secure_decrypter(
416 server->session()->connection()->alternative_decrypter());
[email protected]8ba81212013-05-03 13:11:48417
418 StringPiece client_encrypter_key = client_encrypter->GetKey();
419 StringPiece client_encrypter_iv = client_encrypter->GetNoncePrefix();
420 StringPiece client_decrypter_key = client_decrypter->GetKey();
421 StringPiece client_decrypter_iv = client_decrypter->GetNoncePrefix();
[email protected]2532de12013-05-09 12:29:33422 StringPiece client_forward_secure_encrypter_key =
423 client_forward_secure_encrypter->GetKey();
424 StringPiece client_forward_secure_encrypter_iv =
425 client_forward_secure_encrypter->GetNoncePrefix();
426 StringPiece client_forward_secure_decrypter_key =
427 client_forward_secure_decrypter->GetKey();
428 StringPiece client_forward_secure_decrypter_iv =
429 client_forward_secure_decrypter->GetNoncePrefix();
[email protected]8ba81212013-05-03 13:11:48430 StringPiece server_encrypter_key = server_encrypter->GetKey();
431 StringPiece server_encrypter_iv = server_encrypter->GetNoncePrefix();
432 StringPiece server_decrypter_key = server_decrypter->GetKey();
433 StringPiece server_decrypter_iv = server_decrypter->GetNoncePrefix();
[email protected]2532de12013-05-09 12:29:33434 StringPiece server_forward_secure_encrypter_key =
435 server_forward_secure_encrypter->GetKey();
436 StringPiece server_forward_secure_encrypter_iv =
437 server_forward_secure_encrypter->GetNoncePrefix();
438 StringPiece server_forward_secure_decrypter_key =
439 server_forward_secure_decrypter->GetKey();
440 StringPiece server_forward_secure_decrypter_iv =
441 server_forward_secure_decrypter->GetNoncePrefix();
[email protected]8ba81212013-05-03 13:11:48442
[email protected]2fe8b632014-07-31 11:36:37443 StringPiece client_subkey_secret =
444 client->crypto_negotiated_params().subkey_secret;
445 StringPiece server_subkey_secret =
446 server->crypto_negotiated_params().subkey_secret;
447
[email protected]2fe8b632014-07-31 11:36:37448 const char kSampleLabel[] = "label";
449 const char kSampleContext[] = "context";
450 const size_t kSampleOutputLength = 32;
451 string client_key_extraction;
452 string server_key_extraction;
fayanga64c1a92016-02-13 01:55:58453 string client_tb_ekm;
454 string server_tb_ekm;
rjshaded5ced072015-12-18 19:26:02455 EXPECT_TRUE(client->ExportKeyingMaterial(kSampleLabel, kSampleContext,
[email protected]2fe8b632014-07-31 11:36:37456 kSampleOutputLength,
457 &client_key_extraction));
rjshaded5ced072015-12-18 19:26:02458 EXPECT_TRUE(server->ExportKeyingMaterial(kSampleLabel, kSampleContext,
[email protected]2fe8b632014-07-31 11:36:37459 kSampleOutputLength,
460 &server_key_extraction));
jri78ec06a2016-03-31 18:19:40461 EXPECT_TRUE(client->ExportTokenBindingKeyingMaterial(&client_tb_ekm));
462 EXPECT_TRUE(server->ExportTokenBindingKeyingMaterial(&server_tb_ekm));
[email protected]2fe8b632014-07-31 11:36:37463
rjshaded5ced072015-12-18 19:26:02464 CompareCharArraysWithHexError("client write key", client_encrypter_key.data(),
[email protected]14e8106c2013-03-14 16:25:33465 client_encrypter_key.length(),
466 server_decrypter_key.data(),
467 server_decrypter_key.length());
rjshaded5ced072015-12-18 19:26:02468 CompareCharArraysWithHexError("client write IV", client_encrypter_iv.data(),
[email protected]14e8106c2013-03-14 16:25:33469 client_encrypter_iv.length(),
470 server_decrypter_iv.data(),
471 server_decrypter_iv.length());
rjshaded5ced072015-12-18 19:26:02472 CompareCharArraysWithHexError("server write key", server_encrypter_key.data(),
[email protected]14e8106c2013-03-14 16:25:33473 server_encrypter_key.length(),
474 client_decrypter_key.data(),
475 client_decrypter_key.length());
rjshaded5ced072015-12-18 19:26:02476 CompareCharArraysWithHexError("server write IV", server_encrypter_iv.data(),
[email protected]14e8106c2013-03-14 16:25:33477 server_encrypter_iv.length(),
478 client_decrypter_iv.data(),
479 client_decrypter_iv.length());
[email protected]2532de12013-05-09 12:29:33480 CompareCharArraysWithHexError("client forward secure write key",
481 client_forward_secure_encrypter_key.data(),
482 client_forward_secure_encrypter_key.length(),
483 server_forward_secure_decrypter_key.data(),
484 server_forward_secure_decrypter_key.length());
485 CompareCharArraysWithHexError("client forward secure write IV",
486 client_forward_secure_encrypter_iv.data(),
487 client_forward_secure_encrypter_iv.length(),
488 server_forward_secure_decrypter_iv.data(),
489 server_forward_secure_decrypter_iv.length());
490 CompareCharArraysWithHexError("server forward secure write key",
491 server_forward_secure_encrypter_key.data(),
492 server_forward_secure_encrypter_key.length(),
493 client_forward_secure_decrypter_key.data(),
494 client_forward_secure_decrypter_key.length());
495 CompareCharArraysWithHexError("server forward secure write IV",
496 server_forward_secure_encrypter_iv.data(),
497 server_forward_secure_encrypter_iv.length(),
498 client_forward_secure_decrypter_iv.data(),
499 client_forward_secure_decrypter_iv.length());
rjshaded5ced072015-12-18 19:26:02500 CompareCharArraysWithHexError("subkey secret", client_subkey_secret.data(),
[email protected]2fe8b632014-07-31 11:36:37501 client_subkey_secret.length(),
502 server_subkey_secret.data(),
503 server_subkey_secret.length());
rjshaded5ced072015-12-18 19:26:02504 CompareCharArraysWithHexError(
505 "sample key extraction", client_key_extraction.data(),
506 client_key_extraction.length(), server_key_extraction.data(),
507 server_key_extraction.length());
fayanga64c1a92016-02-13 01:55:58508
jri78ec06a2016-03-31 18:19:40509 CompareCharArraysWithHexError("token binding key extraction",
510 client_tb_ekm.data(), client_tb_ekm.length(),
511 server_tb_ekm.data(), server_tb_ekm.length());
[email protected]ed3fc15d2013-03-08 18:37:44512}
[email protected]0bbeb6972013-05-23 04:10:21513
514// static
515QuicTag CryptoTestUtils::ParseTag(const char* tagstr) {
516 const size_t len = strlen(tagstr);
517 CHECK_NE(0u, len);
518
519 QuicTag tag = 0;
520
521 if (tagstr[0] == '#') {
rjshaded5ced072015-12-18 19:26:02522 CHECK_EQ(static_cast<size_t>(1 + 2 * 4), len);
[email protected]0bbeb6972013-05-23 04:10:21523 tagstr++;
524
525 for (size_t i = 0; i < 8; i++) {
526 tag <<= 4;
527
Avi Drissman13fc8932015-12-20 04:40:46528 uint8_t v = 0;
[email protected]0bbeb6972013-05-23 04:10:21529 CHECK(HexChar(tagstr[i], &v));
530 tag |= v;
531 }
532
533 return tag;
534 }
535
536 CHECK_LE(len, 4u);
537 for (size_t i = 0; i < 4; i++) {
538 tag >>= 8;
539 if (i < len) {
Avi Drissman13fc8932015-12-20 04:40:46540 tag |= static_cast<uint32_t>(tagstr[i]) << 24;
[email protected]0bbeb6972013-05-23 04:10:21541 }
542 }
543
544 return tag;
545}
546
547// static
548CryptoHandshakeMessage CryptoTestUtils::Message(const char* message_tag, ...) {
549 va_list ap;
550 va_start(ap, message_tag);
551
[email protected]0bbeb6972013-05-23 04:10:21552 CryptoHandshakeMessage msg;
553 msg.set_tag(ParseTag(message_tag));
554
555 for (;;) {
556 const char* tagstr = va_arg(ap, const char*);
rtennetibe635732014-10-02 22:51:42557 if (tagstr == nullptr) {
[email protected]0bbeb6972013-05-23 04:10:21558 break;
559 }
560
[email protected]4e49b6a2013-06-18 16:39:28561 if (tagstr[0] == '$') {
562 // Special value.
563 const char* const special = tagstr + 1;
564 if (strcmp(special, "padding") == 0) {
565 const int min_bytes = va_arg(ap, int);
566 msg.set_minimum_size(min_bytes);
567 } else {
568 CHECK(false) << "Unknown special value: " << special;
569 }
570
571 continue;
572 }
573
[email protected]0bbeb6972013-05-23 04:10:21574 const QuicTag tag = ParseTag(tagstr);
575 const char* valuestr = va_arg(ap, const char*);
576
577 size_t len = strlen(valuestr);
578 if (len > 0 && valuestr[0] == '#') {
579 valuestr++;
580 len--;
581
[email protected]257f24f2014-04-01 09:15:37582 CHECK_EQ(0u, len % 2);
danakjad1777e2016-04-16 00:56:42583 std::unique_ptr<uint8_t[]> buf(new uint8_t[len / 2]);
[email protected]0bbeb6972013-05-23 04:10:21584
rjshaded5ced072015-12-18 19:26:02585 for (size_t i = 0; i < len / 2; i++) {
Avi Drissman13fc8932015-12-20 04:40:46586 uint8_t v = 0;
rjshaded5ced072015-12-18 19:26:02587 CHECK(HexChar(valuestr[i * 2], &v));
[email protected]0bbeb6972013-05-23 04:10:21588 buf[i] = v << 4;
rjshaded5ced072015-12-18 19:26:02589 CHECK(HexChar(valuestr[i * 2 + 1], &v));
[email protected]0bbeb6972013-05-23 04:10:21590 buf[i] |= v;
591 }
592
593 msg.SetStringPiece(
rjshaded5ced072015-12-18 19:26:02594 tag, StringPiece(reinterpret_cast<char*>(buf.get()), len / 2));
[email protected]0bbeb6972013-05-23 04:10:21595 continue;
596 }
597
598 msg.SetStringPiece(tag, valuestr);
599 }
600
[email protected]4e49b6a2013-06-18 16:39:28601 // The CryptoHandshakeMessage needs to be serialized and parsed to ensure
602 // that any padding is included.
danakjad1777e2016-04-16 00:56:42603 std::unique_ptr<QuicData> bytes(CryptoFramer::ConstructHandshakeMessage(msg));
604 std::unique_ptr<CryptoHandshakeMessage> parsed(
[email protected]4e49b6a2013-06-18 16:39:28605 CryptoFramer::ParseMessage(bytes->AsStringPiece()));
606 CHECK(parsed.get());
607
rtenneti48f371c682015-08-27 05:34:26608 va_end(ap);
[email protected]4e49b6a2013-06-18 16:39:28609 return *parsed;
[email protected]0bbeb6972013-05-23 04:10:21610}
611
rjshadec86dbfa2015-11-12 20:16:25612// static
613void CryptoTestUtils::MovePackets(PacketSavingConnection* source_conn,
614 size_t* inout_packet_index,
615 QuicCryptoStream* dest_stream,
616 PacketSavingConnection* dest_conn) {
617 SimpleQuicFramer framer(source_conn->supported_versions());
618 CryptoFramer crypto_framer;
619 CryptoFramerVisitor crypto_visitor;
620
621 // In order to properly test the code we need to perform encryption and
622 // decryption so that the crypters latch when expected. The crypters are in
623 // |dest_conn|, but we don't want to try and use them there. Instead we swap
624 // them into |framer|, perform the decryption with them, and then swap ther
625 // back.
626 QuicConnectionPeer::SwapCrypters(dest_conn, framer.framer());
627
628 crypto_framer.set_visitor(&crypto_visitor);
629
630 size_t index = *inout_packet_index;
631 for (; index < source_conn->encrypted_packets_.size(); index++) {
632 if (!framer.ProcessPacket(*source_conn->encrypted_packets_[index])) {
633 // The framer will be unable to decrypt forward-secure packets sent after
634 // the handshake is complete. Don't treat them as handshake packets.
635 break;
636 }
637
zhongyi36727b82015-12-03 00:42:23638 for (const QuicStreamFrame* stream_frame : framer.stream_frames()) {
jokulik2324d282015-12-08 21:42:57639 ASSERT_TRUE(crypto_framer.ProcessInput(
640 StringPiece(stream_frame->frame_buffer, stream_frame->frame_length)));
rjshadec86dbfa2015-11-12 20:16:25641 ASSERT_FALSE(crypto_visitor.error());
642 }
643 }
644 *inout_packet_index = index;
645
646 QuicConnectionPeer::SwapCrypters(dest_conn, framer.framer());
647
648 ASSERT_EQ(0u, crypto_framer.InputBytesRemaining());
649
650 for (const CryptoHandshakeMessage& message : crypto_visitor.messages()) {
651 dest_stream->OnHandshakeMessage(message);
652 }
653}
654
[email protected]ed3fc15d2013-03-08 18:37:44655} // namespace test
656} // namespace net