blob: 4d18cca20c940ea5cb93d00796d859204d236d49 [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:
rjshaded5ced072015-12-18 19:26:0238 CryptoFramerVisitor() : error_(false) {}
[email protected]ed3fc15d2013-03-08 18:37:4439
dchengb03027d2014-10-21 12:00:2040 void OnError(CryptoFramer* framer) override { error_ = true; }
[email protected]ed3fc15d2013-03-08 18:37:4441
dchengb03027d2014-10-21 12:00:2042 void OnHandshakeMessage(const CryptoHandshakeMessage& message) override {
[email protected]fe053f92013-04-23 20:18:5543 messages_.push_back(message);
44 }
[email protected]ed3fc15d2013-03-08 18:37:4445
rjshaded5ced072015-12-18 19:26:0246 bool error() const { return error_; }
[email protected]ed3fc15d2013-03-08 18:37:4447
rjshaded5ced072015-12-18 19:26:0248 const vector<CryptoHandshakeMessage>& messages() const { return messages_; }
[email protected]ed3fc15d2013-03-08 18:37:4449
[email protected]fe053f92013-04-23 20:18:5550 private:
51 bool error_;
52 vector<CryptoHandshakeMessage> messages_;
53};
54
[email protected]0bbeb6972013-05-23 04:10:2155// HexChar parses |c| as a hex character. If valid, it sets |*value| to the
56// value of the hex character and returns true. Otherwise it returns false.
Avi Drissman13fc8932015-12-20 04:40:4657bool HexChar(char c, uint8_t* value) {
[email protected]0bbeb6972013-05-23 04:10:2158 if (c >= '0' && c <= '9') {
59 *value = c - '0';
60 return true;
61 }
62 if (c >= 'a' && c <= 'f') {
[email protected]b064310782013-05-30 21:12:1763 *value = c - 'a' + 10;
[email protected]0bbeb6972013-05-23 04:10:2164 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 return false;
71}
72
[email protected]6fc79ea2014-07-10 04:30:2373// A ChannelIDSource that works in asynchronous mode unless the |callback|
rtennetibe635732014-10-02 22:51:4274// argument to GetChannelIDKey is nullptr.
[email protected]6fc79ea2014-07-10 04:30:2375class AsyncTestChannelIDSource : public ChannelIDSource,
[email protected]dc6094a2014-07-23 01:50:0476 public CryptoTestUtils::CallbackSource {
[email protected]6fc79ea2014-07-10 04:30:2377 public:
78 // Takes ownership of |sync_source|, a synchronous ChannelIDSource.
79 explicit AsyncTestChannelIDSource(ChannelIDSource* sync_source)
80 : sync_source_(sync_source) {}
dchengb03027d2014-10-21 12:00:2081 ~AsyncTestChannelIDSource() override {}
[email protected]6fc79ea2014-07-10 04:30:2382
83 // ChannelIDSource implementation.
dchengb03027d2014-10-21 12:00:2084 QuicAsyncStatus GetChannelIDKey(const string& hostname,
85 scoped_ptr<ChannelIDKey>* channel_id_key,
86 ChannelIDSourceCallback* callback) override {
[email protected]6fc79ea2014-07-10 04:30:2387 // Synchronous mode.
88 if (!callback) {
rtennetibe635732014-10-02 22:51:4289 return sync_source_->GetChannelIDKey(hostname, channel_id_key, nullptr);
[email protected]6fc79ea2014-07-10 04:30:2390 }
91
92 // Asynchronous mode.
93 QuicAsyncStatus status =
rtennetibe635732014-10-02 22:51:4294 sync_source_->GetChannelIDKey(hostname, &channel_id_key_, nullptr);
[email protected]6fc79ea2014-07-10 04:30:2395 if (status != QUIC_SUCCESS) {
96 return QUIC_FAILURE;
97 }
98 callback_.reset(callback);
99 return QUIC_PENDING;
100 }
101
[email protected]dc6094a2014-07-23 01:50:04102 // CallbackSource implementation.
dchengb03027d2014-10-21 12:00:20103 void RunPendingCallbacks() override {
[email protected]6fc79ea2014-07-10 04:30:23104 if (callback_.get()) {
105 callback_->Run(&channel_id_key_);
106 callback_.reset();
107 }
108 }
109
110 private:
111 scoped_ptr<ChannelIDSource> sync_source_;
112 scoped_ptr<ChannelIDSourceCallback> callback_;
113 scoped_ptr<ChannelIDKey> channel_id_key_;
114};
115
[email protected]ed3fc15d2013-03-08 18:37:44116} // anonymous namespace
117
rjshadec86dbfa2015-11-12 20:16:25118CryptoTestUtils::FakeServerOptions::FakeServerOptions()
119 : token_binding_enabled(false) {}
120
[email protected]899951652013-05-16 12:52:39121CryptoTestUtils::FakeClientOptions::FakeClientOptions()
rjshadec86dbfa2015-11-12 20:16:25122 : channel_id_enabled(false),
123 channel_id_source_async(false),
124 token_binding_enabled(false) {}
[email protected]899951652013-05-16 12:52:39125
[email protected]ed3fc15d2013-03-08 18:37:44126// static
[email protected]fe053f92013-04-23 20:18:55127int CryptoTestUtils::HandshakeWithFakeServer(
rch99b644c2015-11-04 05:25:28128 MockConnectionHelper* helper,
[email protected]ed3fc15d2013-03-08 18:37:44129 PacketSavingConnection* client_conn,
rjshadec86dbfa2015-11-12 20:16:25130 QuicCryptoClientStream* client,
131 const FakeServerOptions& options) {
rtenneti6f48aa92015-03-16 02:18:48132 PacketSavingConnection* server_conn = new PacketSavingConnection(
rtenneti8a4a0732015-10-18 00:45:51133 helper, Perspective::IS_SERVER, client_conn->supported_versions());
rtennetid39bd762015-06-12 01:05:52134
135 QuicConfig config = DefaultQuicConfig();
[email protected]b064310782013-05-30 21:12:17136 QuicCryptoServerConfig crypto_config(QuicCryptoServerConfig::TESTING,
rch1fe2eeb2015-10-26 14:45:57137 QuicRandom::GetInstance(),
138 ProofSourceForTesting());
rtennetid39bd762015-06-12 01:05:52139 SetupCryptoServerConfigForTest(server_conn->clock(),
140 server_conn->random_generator(), &config,
rjshadec86dbfa2015-11-12 20:16:25141 &crypto_config, options);
[email protected]ccb34212014-07-18 09:27:50142
rtennetib865eb82015-06-17 20:21:46143 TestQuicSpdyServerSession server_session(server_conn, config, &crypto_config);
[email protected]ed3fc15d2013-03-08 18:37:44144
145 // The client's handshake must have been started already.
rtennetib6ac61a52015-02-11 20:20:52146 CHECK_NE(0u, client_conn->encrypted_packets_.size());
[email protected]ed3fc15d2013-03-08 18:37:44147
rtennetid39bd762015-06-12 01:05:52148 CommunicateHandshakeMessages(client_conn, client, server_conn,
149 server_session.GetCryptoStream());
rtennetid39bd762015-06-12 01:05:52150 CompareClientAndServerKeys(client, server_session.GetCryptoStream());
[email protected]fe053f92013-04-23 20:18:55151
152 return client->num_sent_client_hellos();
[email protected]ed3fc15d2013-03-08 18:37:44153}
154
155// static
[email protected]fe053f92013-04-23 20:18:55156int CryptoTestUtils::HandshakeWithFakeClient(
rch99b644c2015-11-04 05:25:28157 MockConnectionHelper* helper,
[email protected]ed3fc15d2013-03-08 18:37:44158 PacketSavingConnection* server_conn,
[email protected]899951652013-05-16 12:52:39159 QuicCryptoServerStream* server,
zhongyic92bc492015-09-22 19:14:36160 const QuicServerId& server_id,
[email protected]899951652013-05-16 12:52:39161 const FakeClientOptions& options) {
rtenneti6f48aa92015-03-16 02:18:48162 PacketSavingConnection* client_conn =
rtenneti8a4a0732015-10-18 00:45:51163 new PacketSavingConnection(helper, Perspective::IS_CLIENT);
rtenneti85d89712014-11-20 03:32:24164 // Advance the time, because timers do not like uninitialized times.
165 client_conn->AdvanceTime(QuicTime::Delta::FromSeconds(1));
[email protected]ef95114d2013-04-17 17:57:01166
rch1fe2eeb2015-10-26 14:45:57167 QuicCryptoClientConfig crypto_config(ProofVerifierForTesting());
rtennetibe635732014-10-02 22:51:42168 AsyncTestChannelIDSource* async_channel_id_source = nullptr;
[email protected]b064310782013-05-30 21:12:17169 if (options.channel_id_enabled) {
[email protected]6fc79ea2014-07-10 04:30:23170 ChannelIDSource* source = ChannelIDSourceForTesting();
171 if (options.channel_id_source_async) {
172 async_channel_id_source = new AsyncTestChannelIDSource(source);
173 source = async_channel_id_source;
174 }
175 crypto_config.SetChannelIDSource(source);
[email protected]b064310782013-05-30 21:12:17176 }
rjshadec86dbfa2015-11-12 20:16:25177 if (options.token_binding_enabled) {
178 crypto_config.tb_key_params.push_back(kP256);
179 }
rtennetib865eb82015-06-17 20:21:46180 TestQuicSpdyClientSession client_session(client_conn, DefaultQuicConfig(),
181 server_id, &crypto_config);
[email protected]ed3fc15d2013-03-08 18:37:44182
rtennetid39bd762015-06-12 01:05:52183 client_session.GetCryptoStream()->CryptoConnect();
rtennetib6ac61a52015-02-11 20:20:52184 CHECK_EQ(1u, client_conn->encrypted_packets_.size());
[email protected]ed3fc15d2013-03-08 18:37:44185
[email protected]dc6094a2014-07-23 01:50:04186 CommunicateHandshakeMessagesAndRunCallbacks(
rtennetid39bd762015-06-12 01:05:52187 client_conn, client_session.GetCryptoStream(), server_conn, server,
188 async_channel_id_source);
[email protected]14e8106c2013-03-14 16:25:33189
rtennetid39bd762015-06-12 01:05:52190 CompareClientAndServerKeys(client_session.GetCryptoStream(), server);
[email protected]fe053f92013-04-23 20:18:55191
[email protected]38b3fd12013-06-18 08:19:01192 if (options.channel_id_enabled) {
[email protected]03dd32532014-05-30 07:11:25193 scoped_ptr<ChannelIDKey> channel_id_key;
rtennetibe635732014-10-02 22:51:42194 QuicAsyncStatus status = crypto_config.channel_id_source()->GetChannelIDKey(
zhongyic92bc492015-09-22 19:14:36195 server_id.host(), &channel_id_key, nullptr);
[email protected]05bfc260f2014-06-07 06:31:25196 EXPECT_EQ(QUIC_SUCCESS, status);
[email protected]03dd32532014-05-30 07:11:25197 EXPECT_EQ(channel_id_key->SerializeKey(),
198 server->crypto_negotiated_params().channel_id);
rtennetid39bd762015-06-12 01:05:52199 EXPECT_EQ(
200 options.channel_id_source_async,
201 client_session.GetCryptoStream()->WasChannelIDSourceCallbackRun());
[email protected]38b3fd12013-06-18 08:19:01202 }
203
rtennetid39bd762015-06-12 01:05:52204 return client_session.GetCryptoStream()->num_sent_client_hellos();
[email protected]14e8106c2013-03-14 16:25:33205}
206
207// static
[email protected]ef95114d2013-04-17 17:57:01208void CryptoTestUtils::SetupCryptoServerConfigForTest(
209 const QuicClock* clock,
210 QuicRandom* rand,
211 QuicConfig* config,
rjshadec86dbfa2015-11-12 20:16:25212 QuicCryptoServerConfig* crypto_config,
213 const FakeServerOptions& fake_options) {
[email protected]b064310782013-05-30 21:12:17214 QuicCryptoServerConfig::ConfigOptions options;
215 options.channel_id_enabled = true;
rjshadec86dbfa2015-11-12 20:16:25216 options.token_binding_enabled = fake_options.token_binding_enabled;
[email protected]ef95114d2013-04-17 17:57:01217 scoped_ptr<CryptoHandshakeMessage> scfg(
[email protected]b064310782013-05-30 21:12:17218 crypto_config->AddDefaultConfig(rand, clock, options));
[email protected]ef95114d2013-04-17 17:57:01219}
220
221// static
[email protected]0bbeb6972013-05-23 04:10:21222void CryptoTestUtils::CommunicateHandshakeMessages(
223 PacketSavingConnection* a_conn,
224 QuicCryptoStream* a,
225 PacketSavingConnection* b_conn,
226 QuicCryptoStream* b) {
rtennetibe635732014-10-02 22:51:42227 CommunicateHandshakeMessagesAndRunCallbacks(a_conn, a, b_conn, b, nullptr);
[email protected]6fc79ea2014-07-10 04:30:23228}
229
230// static
[email protected]dc6094a2014-07-23 01:50:04231void CryptoTestUtils::CommunicateHandshakeMessagesAndRunCallbacks(
[email protected]6fc79ea2014-07-10 04:30:23232 PacketSavingConnection* a_conn,
233 QuicCryptoStream* a,
234 PacketSavingConnection* b_conn,
235 QuicCryptoStream* b,
[email protected]dc6094a2014-07-23 01:50:04236 CallbackSource* callback_source) {
[email protected]0bbeb6972013-05-23 04:10:21237 size_t a_i = 0, b_i = 0;
238 while (!a->handshake_confirmed()) {
rtennetib6ac61a52015-02-11 20:20:52239 ASSERT_GT(a_conn->encrypted_packets_.size(), a_i);
240 VLOG(1) << "Processing " << a_conn->encrypted_packets_.size() - a_i
241 << " packets a->b";
[email protected]0bbeb6972013-05-23 04:10:21242 MovePackets(a_conn, &a_i, b, b_conn);
[email protected]dc6094a2014-07-23 01:50:04243 if (callback_source) {
244 callback_source->RunPendingCallbacks();
[email protected]6fc79ea2014-07-10 04:30:23245 }
[email protected]0bbeb6972013-05-23 04:10:21246
rtennetib6ac61a52015-02-11 20:20:52247 ASSERT_GT(b_conn->encrypted_packets_.size(), b_i);
248 VLOG(1) << "Processing " << b_conn->encrypted_packets_.size() - b_i
249 << " packets b->a";
[email protected]0bbeb6972013-05-23 04:10:21250 MovePackets(b_conn, &b_i, a, a_conn);
[email protected]dc6094a2014-07-23 01:50:04251 if (callback_source) {
252 callback_source->RunPendingCallbacks();
[email protected]6fc79ea2014-07-10 04:30:23253 }
[email protected]0bbeb6972013-05-23 04:10:21254 }
255}
256
[email protected]b694e48c2014-03-18 17:10:13257// static
[email protected]691f45a982013-11-19 10:52:04258pair<size_t, size_t> CryptoTestUtils::AdvanceHandshake(
259 PacketSavingConnection* a_conn,
260 QuicCryptoStream* a,
261 size_t a_i,
262 PacketSavingConnection* b_conn,
263 QuicCryptoStream* b,
264 size_t b_i) {
rtennetib6ac61a52015-02-11 20:20:52265 VLOG(1) << "Processing " << a_conn->encrypted_packets_.size() - a_i
266 << " packets a->b";
[email protected]691f45a982013-11-19 10:52:04267 MovePackets(a_conn, &a_i, b, b_conn);
268
rtennetib6ac61a52015-02-11 20:20:52269 VLOG(1) << "Processing " << b_conn->encrypted_packets_.size() - b_i
270 << " packets b->a";
271 if (b_conn->encrypted_packets_.size() - b_i == 2) {
272 VLOG(1) << "here";
[email protected]691f45a982013-11-19 10:52:04273 }
274 MovePackets(b_conn, &b_i, a, a_conn);
275
rtenneti16a20772015-02-17 18:58:48276 return std::make_pair(a_i, b_i);
[email protected]691f45a982013-11-19 10:52:04277}
278
[email protected]0bbeb6972013-05-23 04:10:21279// static
[email protected]ccc66e8a2013-03-26 08:26:14280string CryptoTestUtils::GetValueForTag(const CryptoHandshakeMessage& message,
[email protected]2532de12013-05-09 12:29:33281 QuicTag tag) {
282 QuicTagValueMap::const_iterator it = message.tag_value_map().find(tag);
[email protected]ccc66e8a2013-03-26 08:26:14283 if (it == message.tag_value_map().end()) {
284 return string();
285 }
286 return it->second;
287}
288
[email protected]2532de12013-05-09 12:29:33289class MockCommonCertSets : public CommonCertSets {
[email protected]c244c5a12013-05-07 20:55:04290 public:
Avi Drissman13fc8932015-12-20 04:40:46291 MockCommonCertSets(StringPiece cert, uint64_t hash, uint32_t index)
rjshaded5ced072015-12-18 19:26:02292 : cert_(cert.as_string()), hash_(hash), index_(index) {}
[email protected]c244c5a12013-05-07 20:55:04293
dchengb03027d2014-10-21 12:00:20294 StringPiece GetCommonHashes() const override {
[email protected]c244c5a12013-05-07 20:55:04295 CHECK(false) << "not implemented";
296 return StringPiece();
297 }
298
Avi Drissman13fc8932015-12-20 04:40:46299 StringPiece GetCert(uint64_t hash, uint32_t index) const override {
[email protected]c244c5a12013-05-07 20:55:04300 if (hash == hash_ && index == index_) {
301 return cert_;
302 }
303 return StringPiece();
304 }
305
dchengb03027d2014-10-21 12:00:20306 bool MatchCert(StringPiece cert,
307 StringPiece common_set_hashes,
Avi Drissman13fc8932015-12-20 04:40:46308 uint64_t* out_hash,
309 uint32_t* out_index) const override {
[email protected]c244c5a12013-05-07 20:55:04310 if (cert != cert_) {
311 return false;
312 }
313
Avi Drissman13fc8932015-12-20 04:40:46314 if (common_set_hashes.size() % sizeof(uint64_t) != 0) {
[email protected]c244c5a12013-05-07 20:55:04315 return false;
316 }
317 bool client_has_set = false;
Avi Drissman13fc8932015-12-20 04:40:46318 for (size_t i = 0; i < common_set_hashes.size(); i += sizeof(uint64_t)) {
319 uint64_t hash;
[email protected]c244c5a12013-05-07 20:55:04320 memcpy(&hash, common_set_hashes.data() + i, sizeof(hash));
321 if (hash == hash_) {
322 client_has_set = true;
323 break;
324 }
325 }
326
327 if (!client_has_set) {
328 return false;
329 }
330
331 *out_hash = hash_;
332 *out_index = index_;
333 return true;
334 }
335
336 private:
337 const string cert_;
Avi Drissman13fc8932015-12-20 04:40:46338 const uint64_t hash_;
339 const uint32_t index_;
[email protected]c244c5a12013-05-07 20:55:04340};
341
[email protected]2532de12013-05-09 12:29:33342CommonCertSets* CryptoTestUtils::MockCommonCertSets(StringPiece cert,
Avi Drissman13fc8932015-12-20 04:40:46343 uint64_t hash,
344 uint32_t index) {
[email protected]2532de12013-05-09 12:29:33345 return new class MockCommonCertSets(cert, hash, index);
[email protected]c244c5a12013-05-07 20:55:04346}
347
rch94e52bc2015-12-06 04:28:26348// static
349void CryptoTestUtils::FillInDummyReject(CryptoHandshakeMessage* rej,
350 bool reject_is_stateless) {
351 if (reject_is_stateless) {
352 rej->set_tag(kSREJ);
353 } else {
354 rej->set_tag(kREJ);
355 }
356
357 // Minimum SCFG that passes config validation checks.
358 // clang-format off
359 unsigned char scfg[] = {
360 // SCFG
361 0x53, 0x43, 0x46, 0x47,
362 // num entries
363 0x01, 0x00,
364 // padding
365 0x00, 0x00,
366 // EXPY
367 0x45, 0x58, 0x50, 0x59,
368 // EXPY end offset
369 0x08, 0x00, 0x00, 0x00,
370 // Value
371 '1', '2', '3', '4',
372 '5', '6', '7', '8'
373 };
374 // clang-format on
375 rej->SetValue(kSCFG, scfg);
376 rej->SetStringPiece(kServerNonceTag, "SERVER_NONCE");
377 vector<QuicTag> reject_reasons;
378 reject_reasons.push_back(CLIENT_NONCE_INVALID_FAILURE);
379 rej->SetVector(kRREJ, reject_reasons);
380}
381
[email protected]14e8106c2013-03-14 16:25:33382void CryptoTestUtils::CompareClientAndServerKeys(
383 QuicCryptoClientStream* client,
384 QuicCryptoServerStream* server) {
rch1e543ec2015-03-29 07:04:40385 QuicFramer* client_framer =
386 QuicConnectionPeer::GetFramer(client->session()->connection());
387 QuicFramer* server_framer =
388 QuicConnectionPeer::GetFramer(server->session()->connection());
[email protected]8ba81212013-05-03 13:11:48389 const QuicEncrypter* client_encrypter(
rch1e543ec2015-03-29 07:04:40390 QuicFramerPeer::GetEncrypter(client_framer, ENCRYPTION_INITIAL));
[email protected]8ba81212013-05-03 13:11:48391 const QuicDecrypter* client_decrypter(
[email protected]2532de12013-05-09 12:29:33392 client->session()->connection()->decrypter());
393 const QuicEncrypter* client_forward_secure_encrypter(
rch1e543ec2015-03-29 07:04:40394 QuicFramerPeer::GetEncrypter(client_framer, ENCRYPTION_FORWARD_SECURE));
[email protected]2532de12013-05-09 12:29:33395 const QuicDecrypter* client_forward_secure_decrypter(
[email protected]8ba81212013-05-03 13:11:48396 client->session()->connection()->alternative_decrypter());
397 const QuicEncrypter* server_encrypter(
rch1e543ec2015-03-29 07:04:40398 QuicFramerPeer::GetEncrypter(server_framer, ENCRYPTION_INITIAL));
[email protected]8ba81212013-05-03 13:11:48399 const QuicDecrypter* server_decrypter(
400 server->session()->connection()->decrypter());
[email protected]2532de12013-05-09 12:29:33401 const QuicEncrypter* server_forward_secure_encrypter(
rch1e543ec2015-03-29 07:04:40402 QuicFramerPeer::GetEncrypter(server_framer, ENCRYPTION_FORWARD_SECURE));
[email protected]2532de12013-05-09 12:29:33403 const QuicDecrypter* server_forward_secure_decrypter(
404 server->session()->connection()->alternative_decrypter());
[email protected]8ba81212013-05-03 13:11:48405
406 StringPiece client_encrypter_key = client_encrypter->GetKey();
407 StringPiece client_encrypter_iv = client_encrypter->GetNoncePrefix();
408 StringPiece client_decrypter_key = client_decrypter->GetKey();
409 StringPiece client_decrypter_iv = client_decrypter->GetNoncePrefix();
[email protected]2532de12013-05-09 12:29:33410 StringPiece client_forward_secure_encrypter_key =
411 client_forward_secure_encrypter->GetKey();
412 StringPiece client_forward_secure_encrypter_iv =
413 client_forward_secure_encrypter->GetNoncePrefix();
414 StringPiece client_forward_secure_decrypter_key =
415 client_forward_secure_decrypter->GetKey();
416 StringPiece client_forward_secure_decrypter_iv =
417 client_forward_secure_decrypter->GetNoncePrefix();
[email protected]8ba81212013-05-03 13:11:48418 StringPiece server_encrypter_key = server_encrypter->GetKey();
419 StringPiece server_encrypter_iv = server_encrypter->GetNoncePrefix();
420 StringPiece server_decrypter_key = server_decrypter->GetKey();
421 StringPiece server_decrypter_iv = server_decrypter->GetNoncePrefix();
[email protected]2532de12013-05-09 12:29:33422 StringPiece server_forward_secure_encrypter_key =
423 server_forward_secure_encrypter->GetKey();
424 StringPiece server_forward_secure_encrypter_iv =
425 server_forward_secure_encrypter->GetNoncePrefix();
426 StringPiece server_forward_secure_decrypter_key =
427 server_forward_secure_decrypter->GetKey();
428 StringPiece server_forward_secure_decrypter_iv =
429 server_forward_secure_decrypter->GetNoncePrefix();
[email protected]8ba81212013-05-03 13:11:48430
[email protected]2fe8b632014-07-31 11:36:37431 StringPiece client_subkey_secret =
432 client->crypto_negotiated_params().subkey_secret;
433 StringPiece server_subkey_secret =
434 server->crypto_negotiated_params().subkey_secret;
435
[email protected]2fe8b632014-07-31 11:36:37436 const char kSampleLabel[] = "label";
437 const char kSampleContext[] = "context";
438 const size_t kSampleOutputLength = 32;
439 string client_key_extraction;
440 string server_key_extraction;
fayanga64c1a92016-02-13 01:55:58441 string client_tb_ekm;
442 string server_tb_ekm;
rjshaded5ced072015-12-18 19:26:02443 EXPECT_TRUE(client->ExportKeyingMaterial(kSampleLabel, kSampleContext,
[email protected]2fe8b632014-07-31 11:36:37444 kSampleOutputLength,
445 &client_key_extraction));
rjshaded5ced072015-12-18 19:26:02446 EXPECT_TRUE(server->ExportKeyingMaterial(kSampleLabel, kSampleContext,
[email protected]2fe8b632014-07-31 11:36:37447 kSampleOutputLength,
448 &server_key_extraction));
fayanga64c1a92016-02-13 01:55:58449 if (FLAGS_quic_save_initial_subkey_secret) {
450 EXPECT_TRUE(client->ExportTokenBindingKeyingMaterial(&client_tb_ekm));
451 EXPECT_TRUE(server->ExportTokenBindingKeyingMaterial(&server_tb_ekm));
452 }
[email protected]2fe8b632014-07-31 11:36:37453
rjshaded5ced072015-12-18 19:26:02454 CompareCharArraysWithHexError("client write key", client_encrypter_key.data(),
[email protected]14e8106c2013-03-14 16:25:33455 client_encrypter_key.length(),
456 server_decrypter_key.data(),
457 server_decrypter_key.length());
rjshaded5ced072015-12-18 19:26:02458 CompareCharArraysWithHexError("client write IV", client_encrypter_iv.data(),
[email protected]14e8106c2013-03-14 16:25:33459 client_encrypter_iv.length(),
460 server_decrypter_iv.data(),
461 server_decrypter_iv.length());
rjshaded5ced072015-12-18 19:26:02462 CompareCharArraysWithHexError("server write key", server_encrypter_key.data(),
[email protected]14e8106c2013-03-14 16:25:33463 server_encrypter_key.length(),
464 client_decrypter_key.data(),
465 client_decrypter_key.length());
rjshaded5ced072015-12-18 19:26:02466 CompareCharArraysWithHexError("server write IV", server_encrypter_iv.data(),
[email protected]14e8106c2013-03-14 16:25:33467 server_encrypter_iv.length(),
468 client_decrypter_iv.data(),
469 client_decrypter_iv.length());
[email protected]2532de12013-05-09 12:29:33470 CompareCharArraysWithHexError("client forward secure write key",
471 client_forward_secure_encrypter_key.data(),
472 client_forward_secure_encrypter_key.length(),
473 server_forward_secure_decrypter_key.data(),
474 server_forward_secure_decrypter_key.length());
475 CompareCharArraysWithHexError("client forward secure write IV",
476 client_forward_secure_encrypter_iv.data(),
477 client_forward_secure_encrypter_iv.length(),
478 server_forward_secure_decrypter_iv.data(),
479 server_forward_secure_decrypter_iv.length());
480 CompareCharArraysWithHexError("server forward secure write key",
481 server_forward_secure_encrypter_key.data(),
482 server_forward_secure_encrypter_key.length(),
483 client_forward_secure_decrypter_key.data(),
484 client_forward_secure_decrypter_key.length());
485 CompareCharArraysWithHexError("server forward secure write IV",
486 server_forward_secure_encrypter_iv.data(),
487 server_forward_secure_encrypter_iv.length(),
488 client_forward_secure_decrypter_iv.data(),
489 client_forward_secure_decrypter_iv.length());
rjshaded5ced072015-12-18 19:26:02490 CompareCharArraysWithHexError("subkey secret", client_subkey_secret.data(),
[email protected]2fe8b632014-07-31 11:36:37491 client_subkey_secret.length(),
492 server_subkey_secret.data(),
493 server_subkey_secret.length());
rjshaded5ced072015-12-18 19:26:02494 CompareCharArraysWithHexError(
495 "sample key extraction", client_key_extraction.data(),
496 client_key_extraction.length(), server_key_extraction.data(),
497 server_key_extraction.length());
fayanga64c1a92016-02-13 01:55:58498
499 if (FLAGS_quic_save_initial_subkey_secret) {
500 CompareCharArraysWithHexError("token binding key extraction",
501 client_tb_ekm.data(), client_tb_ekm.length(),
502 server_tb_ekm.data(), server_tb_ekm.length());
503 }
[email protected]ed3fc15d2013-03-08 18:37:44504}
[email protected]0bbeb6972013-05-23 04:10:21505
506// static
507QuicTag CryptoTestUtils::ParseTag(const char* tagstr) {
508 const size_t len = strlen(tagstr);
509 CHECK_NE(0u, len);
510
511 QuicTag tag = 0;
512
513 if (tagstr[0] == '#') {
rjshaded5ced072015-12-18 19:26:02514 CHECK_EQ(static_cast<size_t>(1 + 2 * 4), len);
[email protected]0bbeb6972013-05-23 04:10:21515 tagstr++;
516
517 for (size_t i = 0; i < 8; i++) {
518 tag <<= 4;
519
Avi Drissman13fc8932015-12-20 04:40:46520 uint8_t v = 0;
[email protected]0bbeb6972013-05-23 04:10:21521 CHECK(HexChar(tagstr[i], &v));
522 tag |= v;
523 }
524
525 return tag;
526 }
527
528 CHECK_LE(len, 4u);
529 for (size_t i = 0; i < 4; i++) {
530 tag >>= 8;
531 if (i < len) {
Avi Drissman13fc8932015-12-20 04:40:46532 tag |= static_cast<uint32_t>(tagstr[i]) << 24;
[email protected]0bbeb6972013-05-23 04:10:21533 }
534 }
535
536 return tag;
537}
538
539// static
540CryptoHandshakeMessage CryptoTestUtils::Message(const char* message_tag, ...) {
541 va_list ap;
542 va_start(ap, message_tag);
543
[email protected]0bbeb6972013-05-23 04:10:21544 CryptoHandshakeMessage msg;
545 msg.set_tag(ParseTag(message_tag));
546
547 for (;;) {
548 const char* tagstr = va_arg(ap, const char*);
rtennetibe635732014-10-02 22:51:42549 if (tagstr == nullptr) {
[email protected]0bbeb6972013-05-23 04:10:21550 break;
551 }
552
[email protected]4e49b6a2013-06-18 16:39:28553 if (tagstr[0] == '$') {
554 // Special value.
555 const char* const special = tagstr + 1;
556 if (strcmp(special, "padding") == 0) {
557 const int min_bytes = va_arg(ap, int);
558 msg.set_minimum_size(min_bytes);
559 } else {
560 CHECK(false) << "Unknown special value: " << special;
561 }
562
563 continue;
564 }
565
[email protected]0bbeb6972013-05-23 04:10:21566 const QuicTag tag = ParseTag(tagstr);
567 const char* valuestr = va_arg(ap, const char*);
568
569 size_t len = strlen(valuestr);
570 if (len > 0 && valuestr[0] == '#') {
571 valuestr++;
572 len--;
573
[email protected]257f24f2014-04-01 09:15:37574 CHECK_EQ(0u, len % 2);
Avi Drissman13fc8932015-12-20 04:40:46575 scoped_ptr<uint8_t[]> buf(new uint8_t[len / 2]);
[email protected]0bbeb6972013-05-23 04:10:21576
rjshaded5ced072015-12-18 19:26:02577 for (size_t i = 0; i < len / 2; i++) {
Avi Drissman13fc8932015-12-20 04:40:46578 uint8_t v = 0;
rjshaded5ced072015-12-18 19:26:02579 CHECK(HexChar(valuestr[i * 2], &v));
[email protected]0bbeb6972013-05-23 04:10:21580 buf[i] = v << 4;
rjshaded5ced072015-12-18 19:26:02581 CHECK(HexChar(valuestr[i * 2 + 1], &v));
[email protected]0bbeb6972013-05-23 04:10:21582 buf[i] |= v;
583 }
584
585 msg.SetStringPiece(
rjshaded5ced072015-12-18 19:26:02586 tag, StringPiece(reinterpret_cast<char*>(buf.get()), len / 2));
[email protected]0bbeb6972013-05-23 04:10:21587 continue;
588 }
589
590 msg.SetStringPiece(tag, valuestr);
591 }
592
[email protected]4e49b6a2013-06-18 16:39:28593 // The CryptoHandshakeMessage needs to be serialized and parsed to ensure
594 // that any padding is included.
595 scoped_ptr<QuicData> bytes(CryptoFramer::ConstructHandshakeMessage(msg));
596 scoped_ptr<CryptoHandshakeMessage> parsed(
597 CryptoFramer::ParseMessage(bytes->AsStringPiece()));
598 CHECK(parsed.get());
599
rtenneti48f371c682015-08-27 05:34:26600 va_end(ap);
[email protected]4e49b6a2013-06-18 16:39:28601 return *parsed;
[email protected]0bbeb6972013-05-23 04:10:21602}
603
rjshadec86dbfa2015-11-12 20:16:25604// static
605void CryptoTestUtils::MovePackets(PacketSavingConnection* source_conn,
606 size_t* inout_packet_index,
607 QuicCryptoStream* dest_stream,
608 PacketSavingConnection* dest_conn) {
609 SimpleQuicFramer framer(source_conn->supported_versions());
610 CryptoFramer crypto_framer;
611 CryptoFramerVisitor crypto_visitor;
612
613 // In order to properly test the code we need to perform encryption and
614 // decryption so that the crypters latch when expected. The crypters are in
615 // |dest_conn|, but we don't want to try and use them there. Instead we swap
616 // them into |framer|, perform the decryption with them, and then swap ther
617 // back.
618 QuicConnectionPeer::SwapCrypters(dest_conn, framer.framer());
619
620 crypto_framer.set_visitor(&crypto_visitor);
621
622 size_t index = *inout_packet_index;
623 for (; index < source_conn->encrypted_packets_.size(); index++) {
624 if (!framer.ProcessPacket(*source_conn->encrypted_packets_[index])) {
625 // The framer will be unable to decrypt forward-secure packets sent after
626 // the handshake is complete. Don't treat them as handshake packets.
627 break;
628 }
629
zhongyi36727b82015-12-03 00:42:23630 for (const QuicStreamFrame* stream_frame : framer.stream_frames()) {
jokulik2324d282015-12-08 21:42:57631 ASSERT_TRUE(crypto_framer.ProcessInput(
632 StringPiece(stream_frame->frame_buffer, stream_frame->frame_length)));
rjshadec86dbfa2015-11-12 20:16:25633 ASSERT_FALSE(crypto_visitor.error());
634 }
635 }
636 *inout_packet_index = index;
637
638 QuicConnectionPeer::SwapCrypters(dest_conn, framer.framer());
639
640 ASSERT_EQ(0u, crypto_framer.InputBytesRemaining());
641
642 for (const CryptoHandshakeMessage& message : crypto_visitor.messages()) {
643 dest_stream->OnHandshakeMessage(message);
644 }
645}
646
[email protected]ed3fc15d2013-03-08 18:37:44647} // namespace test
648} // namespace net