blob: 40a6a66228aff57360e000b23aa6490aa040efc9 [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]2532de12013-05-09 12:29:3318#include "net/quic/test_tools/quic_connection_peer.h"
[email protected]ed3fc15d2013-03-08 18:37:4419#include "net/quic/test_tools/quic_test_utils.h"
20#include "net/quic/test_tools/simple_quic_framer.h"
[email protected]ed3fc15d2013-03-08 18:37:4421
[email protected]14e8106c2013-03-14 16:25:3322using base::StringPiece;
[email protected]ccc66e8a2013-03-26 08:26:1423using std::string;
[email protected]fe053f92013-04-23 20:18:5524using std::vector;
[email protected]14e8106c2013-03-14 16:25:3325
[email protected]ed3fc15d2013-03-08 18:37:4426namespace net {
27namespace test {
28
29namespace {
30
[email protected]fe053f92013-04-23 20:18:5531// CryptoFramerVisitor is a framer visitor that records handshake messages.
32class CryptoFramerVisitor : public CryptoFramerVisitorInterface {
33 public:
34 CryptoFramerVisitor()
35 : error_(false) {
36 }
[email protected]ed3fc15d2013-03-08 18:37:4437
[email protected]42091902013-05-02 02:24:1238 virtual void OnError(CryptoFramer* framer) OVERRIDE {
[email protected]fe053f92013-04-23 20:18:5539 error_ = true;
40 }
[email protected]ed3fc15d2013-03-08 18:37:4441
[email protected]42091902013-05-02 02:24:1242 virtual void OnHandshakeMessage(
43 const CryptoHandshakeMessage& message) OVERRIDE {
[email protected]fe053f92013-04-23 20:18:5544 messages_.push_back(message);
45 }
[email protected]ed3fc15d2013-03-08 18:37:4446
[email protected]fe053f92013-04-23 20:18:5547 bool error() const {
48 return error_;
49 }
[email protected]ed3fc15d2013-03-08 18:37:4450
[email protected]fe053f92013-04-23 20:18:5551 const vector<CryptoHandshakeMessage>& messages() const {
52 return messages_;
53 }
[email protected]ed3fc15d2013-03-08 18:37:4454
[email protected]fe053f92013-04-23 20:18:5555 private:
56 bool error_;
57 vector<CryptoHandshakeMessage> messages_;
58};
59
60// MovePackets parses crypto handshake messages from packet number
61// |*inout_packet_index| through to the last packet and has |dest_stream|
62// process them. |*inout_packet_index| is updated with an index one greater
63// than the last packet processed.
64void MovePackets(PacketSavingConnection* source_conn,
65 size_t *inout_packet_index,
[email protected]2532de12013-05-09 12:29:3366 QuicCryptoStream* dest_stream,
67 PacketSavingConnection* dest_conn) {
[email protected]fe053f92013-04-23 20:18:5568 SimpleQuicFramer framer;
69 CryptoFramer crypto_framer;
70 CryptoFramerVisitor crypto_visitor;
71
[email protected]2532de12013-05-09 12:29:3372 // In order to properly test the code we need to perform encryption and
73 // decryption so that the crypters latch when expected. The crypters are in
74 // |dest_conn|, but we don't want to try and use them there. Instead we swap
75 // them into |framer|, perform the decryption with them, and then swap them
76 // back.
77 QuicConnectionPeer::SwapCrypters(dest_conn, framer.framer());
78
[email protected]fe053f92013-04-23 20:18:5579 crypto_framer.set_visitor(&crypto_visitor);
80
81 size_t index = *inout_packet_index;
[email protected]2532de12013-05-09 12:29:3382 for (; index < source_conn->encrypted_packets_.size(); index++) {
83 ASSERT_TRUE(framer.ProcessPacket(*source_conn->encrypted_packets_[index]));
[email protected]fe053f92013-04-23 20:18:5584 for (vector<QuicStreamFrame>::const_iterator
85 i = framer.stream_frames().begin();
86 i != framer.stream_frames().end(); ++i) {
[email protected]5dafdb62013-11-14 01:24:2687 scoped_ptr<string> frame_data(i->GetDataAsString());
88 ASSERT_TRUE(crypto_framer.ProcessInput(*frame_data));
[email protected]fe053f92013-04-23 20:18:5589 ASSERT_FALSE(crypto_visitor.error());
90 }
91 }
92 *inout_packet_index = index;
93
[email protected]2532de12013-05-09 12:29:3394 QuicConnectionPeer::SwapCrypters(dest_conn, framer.framer());
95
[email protected]fe053f92013-04-23 20:18:5596 ASSERT_EQ(0u, crypto_framer.InputBytesRemaining());
97
98 for (vector<CryptoHandshakeMessage>::const_iterator
99 i = crypto_visitor.messages().begin();
100 i != crypto_visitor.messages().end(); ++i) {
101 dest_stream->OnHandshakeMessage(*i);
[email protected]ed3fc15d2013-03-08 18:37:44102 }
103}
104
[email protected]0bbeb6972013-05-23 04:10:21105// HexChar parses |c| as a hex character. If valid, it sets |*value| to the
106// value of the hex character and returns true. Otherwise it returns false.
107bool HexChar(char c, uint8* value) {
108 if (c >= '0' && c <= '9') {
109 *value = c - '0';
110 return true;
111 }
112 if (c >= 'a' && c <= 'f') {
[email protected]b064310782013-05-30 21:12:17113 *value = c - 'a' + 10;
[email protected]0bbeb6972013-05-23 04:10:21114 return true;
115 }
116 if (c >= 'A' && c <= 'F') {
[email protected]b064310782013-05-30 21:12:17117 *value = c - 'A' + 10;
[email protected]0bbeb6972013-05-23 04:10:21118 return true;
119 }
120 return false;
121}
122
[email protected]ed3fc15d2013-03-08 18:37:44123} // anonymous namespace
124
[email protected]899951652013-05-16 12:52:39125CryptoTestUtils::FakeClientOptions::FakeClientOptions()
[email protected]b064310782013-05-30 21:12:17126 : dont_verify_certs(false),
127 channel_id_enabled(false) {
[email protected]899951652013-05-16 12:52:39128}
129
[email protected]ed3fc15d2013-03-08 18:37:44130// static
[email protected]fe053f92013-04-23 20:18:55131int CryptoTestUtils::HandshakeWithFakeServer(
[email protected]ed3fc15d2013-03-08 18:37:44132 PacketSavingConnection* client_conn,
[email protected]14e8106c2013-03-14 16:25:33133 QuicCryptoClientStream* client) {
[email protected]ed3fc15d2013-03-08 18:37:44134 QuicGuid guid(1);
[email protected]72818ea2013-03-13 03:23:57135 IPAddressNumber ip;
136 CHECK(ParseIPLiteralToNumber("192.0.2.33", &ip));
137 IPEndPoint addr = IPEndPoint(ip, 1);
[email protected]ed3fc15d2013-03-08 18:37:44138 PacketSavingConnection* server_conn =
[email protected]14e8106c2013-03-14 16:25:33139 new PacketSavingConnection(guid, addr, true);
[email protected]b007e632013-10-28 08:39:25140 TestSession server_session(server_conn, DefaultQuicConfig(), true);
[email protected]ef95114d2013-04-17 17:57:01141
[email protected]b064310782013-05-30 21:12:17142 QuicCryptoServerConfig crypto_config(QuicCryptoServerConfig::TESTING,
143 QuicRandom::GetInstance());
[email protected]ef95114d2013-04-17 17:57:01144 SetupCryptoServerConfigForTest(
145 server_session.connection()->clock(),
146 server_session.connection()->random_generator(),
[email protected]899951652013-05-16 12:52:39147 server_session.config(), &crypto_config);
[email protected]ef95114d2013-04-17 17:57:01148
[email protected]899951652013-05-16 12:52:39149 QuicCryptoServerStream server(crypto_config, &server_session);
[email protected]2532de12013-05-09 12:29:33150 server_session.SetCryptoStream(&server);
[email protected]ed3fc15d2013-03-08 18:37:44151
152 // The client's handshake must have been started already.
153 CHECK_NE(0u, client_conn->packets_.size());
154
155 CommunicateHandshakeMessages(client_conn, client, server_conn, &server);
[email protected]14e8106c2013-03-14 16:25:33156
157 CompareClientAndServerKeys(client, &server);
[email protected]fe053f92013-04-23 20:18:55158
159 return client->num_sent_client_hellos();
[email protected]ed3fc15d2013-03-08 18:37:44160}
161
162// static
[email protected]fe053f92013-04-23 20:18:55163int CryptoTestUtils::HandshakeWithFakeClient(
[email protected]ed3fc15d2013-03-08 18:37:44164 PacketSavingConnection* server_conn,
[email protected]899951652013-05-16 12:52:39165 QuicCryptoServerStream* server,
166 const FakeClientOptions& options) {
[email protected]ed3fc15d2013-03-08 18:37:44167 QuicGuid guid(1);
[email protected]72818ea2013-03-13 03:23:57168 IPAddressNumber ip;
169 CHECK(ParseIPLiteralToNumber("192.0.2.33", &ip));
170 IPEndPoint addr = IPEndPoint(ip, 1);
[email protected]ed3fc15d2013-03-08 18:37:44171 PacketSavingConnection* client_conn =
[email protected]14e8106c2013-03-14 16:25:33172 new PacketSavingConnection(guid, addr, false);
[email protected]b007e632013-10-28 08:39:25173 TestSession client_session(client_conn, DefaultQuicConfig(), false);
[email protected]ef95114d2013-04-17 17:57:01174 QuicCryptoClientConfig crypto_config;
175
[email protected]899951652013-05-16 12:52:39176 client_session.config()->SetDefaults();
[email protected]ef95114d2013-04-17 17:57:01177 crypto_config.SetDefaults();
[email protected]a57e0272013-04-26 07:31:47178 // TODO(rtenneti): Enable testing of ProofVerifier.
[email protected]899951652013-05-16 12:52:39179 // if (!options.dont_verify_certs) {
[email protected]b064310782013-05-30 21:12:17180 // crypto_config.SetProofVerifier(ProofVerifierForTesting());
[email protected]899951652013-05-16 12:52:39181 // }
[email protected]b064310782013-05-30 21:12:17182 if (options.channel_id_enabled) {
183 crypto_config.SetChannelIDSigner(ChannelIDSignerForTesting());
184 }
[email protected]899951652013-05-16 12:52:39185 QuicCryptoClientStream client("test.example.com", &client_session,
[email protected]ef95114d2013-04-17 17:57:01186 &crypto_config);
[email protected]2532de12013-05-09 12:29:33187 client_session.SetCryptoStream(&client);
[email protected]ed3fc15d2013-03-08 18:37:44188
189 CHECK(client.CryptoConnect());
190 CHECK_EQ(1u, client_conn->packets_.size());
191
192 CommunicateHandshakeMessages(client_conn, &client, server_conn, server);
[email protected]14e8106c2013-03-14 16:25:33193
194 CompareClientAndServerKeys(&client, server);
[email protected]fe053f92013-04-23 20:18:55195
[email protected]38b3fd12013-06-18 08:19:01196 if (options.channel_id_enabled) {
197 EXPECT_EQ(crypto_config.channel_id_signer()->GetKeyForHostname(
198 "test.example.com"),
199 server->crypto_negotiated_params().channel_id);
200 }
201
[email protected]fe053f92013-04-23 20:18:55202 return client.num_sent_client_hellos();
[email protected]14e8106c2013-03-14 16:25:33203}
204
205// static
[email protected]ef95114d2013-04-17 17:57:01206void CryptoTestUtils::SetupCryptoServerConfigForTest(
207 const QuicClock* clock,
208 QuicRandom* rand,
209 QuicConfig* config,
210 QuicCryptoServerConfig* crypto_config) {
211 config->SetDefaults();
[email protected]b064310782013-05-30 21:12:17212 QuicCryptoServerConfig::ConfigOptions options;
213 options.channel_id_enabled = true;
[email protected]ef95114d2013-04-17 17:57:01214 scoped_ptr<CryptoHandshakeMessage> scfg(
[email protected]b064310782013-05-30 21:12:17215 crypto_config->AddDefaultConfig(rand, clock, options));
[email protected]ef95114d2013-04-17 17:57:01216}
217
218// static
[email protected]0bbeb6972013-05-23 04:10:21219void CryptoTestUtils::CommunicateHandshakeMessages(
220 PacketSavingConnection* a_conn,
221 QuicCryptoStream* a,
222 PacketSavingConnection* b_conn,
223 QuicCryptoStream* b) {
224 size_t a_i = 0, b_i = 0;
225 while (!a->handshake_confirmed()) {
226 ASSERT_GT(a_conn->packets_.size(), a_i);
227 LOG(INFO) << "Processing " << a_conn->packets_.size() - a_i
228 << " packets a->b";
229 MovePackets(a_conn, &a_i, b, b_conn);
230
231 ASSERT_GT(b_conn->packets_.size(), b_i);
232 LOG(INFO) << "Processing " << b_conn->packets_.size() - b_i
233 << " packets b->a";
234 if (b_conn->packets_.size() - b_i == 2) {
235 LOG(INFO) << "here";
236 }
237 MovePackets(b_conn, &b_i, a, a_conn);
238 }
239}
240
241// static
[email protected]ccc66e8a2013-03-26 08:26:14242string CryptoTestUtils::GetValueForTag(const CryptoHandshakeMessage& message,
[email protected]2532de12013-05-09 12:29:33243 QuicTag tag) {
244 QuicTagValueMap::const_iterator it = message.tag_value_map().find(tag);
[email protected]ccc66e8a2013-03-26 08:26:14245 if (it == message.tag_value_map().end()) {
246 return string();
247 }
248 return it->second;
249}
250
[email protected]2532de12013-05-09 12:29:33251class MockCommonCertSets : public CommonCertSets {
[email protected]c244c5a12013-05-07 20:55:04252 public:
[email protected]2532de12013-05-09 12:29:33253 MockCommonCertSets(StringPiece cert, uint64 hash, uint32 index)
[email protected]c244c5a12013-05-07 20:55:04254 : cert_(cert.as_string()),
255 hash_(hash),
256 index_(index) {
257 }
258
[email protected]2532de12013-05-09 12:29:33259 virtual StringPiece GetCommonHashes() const OVERRIDE {
[email protected]c244c5a12013-05-07 20:55:04260 CHECK(false) << "not implemented";
261 return StringPiece();
262 }
263
[email protected]2532de12013-05-09 12:29:33264 virtual StringPiece GetCert(uint64 hash, uint32 index) const OVERRIDE {
[email protected]c244c5a12013-05-07 20:55:04265 if (hash == hash_ && index == index_) {
266 return cert_;
267 }
268 return StringPiece();
269 }
270
271 virtual bool MatchCert(StringPiece cert,
272 StringPiece common_set_hashes,
273 uint64* out_hash,
[email protected]2532de12013-05-09 12:29:33274 uint32* out_index) const OVERRIDE {
[email protected]c244c5a12013-05-07 20:55:04275 if (cert != cert_) {
276 return false;
277 }
278
279 if (common_set_hashes.size() % sizeof(uint64) != 0) {
280 return false;
281 }
282 bool client_has_set = false;
283 for (size_t i = 0; i < common_set_hashes.size(); i += sizeof(uint64)) {
284 uint64 hash;
285 memcpy(&hash, common_set_hashes.data() + i, sizeof(hash));
286 if (hash == hash_) {
287 client_has_set = true;
288 break;
289 }
290 }
291
292 if (!client_has_set) {
293 return false;
294 }
295
296 *out_hash = hash_;
297 *out_index = index_;
298 return true;
299 }
300
301 private:
302 const string cert_;
303 const uint64 hash_;
304 const uint32 index_;
305};
306
[email protected]2532de12013-05-09 12:29:33307CommonCertSets* CryptoTestUtils::MockCommonCertSets(StringPiece cert,
[email protected]899951652013-05-16 12:52:39308 uint64 hash,
309 uint32 index) {
[email protected]2532de12013-05-09 12:29:33310 return new class MockCommonCertSets(cert, hash, index);
[email protected]c244c5a12013-05-07 20:55:04311}
312
[email protected]14e8106c2013-03-14 16:25:33313void CryptoTestUtils::CompareClientAndServerKeys(
314 QuicCryptoClientStream* client,
315 QuicCryptoServerStream* server) {
[email protected]8ba81212013-05-03 13:11:48316 const QuicEncrypter* client_encrypter(
317 client->session()->connection()->encrypter(ENCRYPTION_INITIAL));
[email protected]8ba81212013-05-03 13:11:48318 const QuicDecrypter* client_decrypter(
[email protected]2532de12013-05-09 12:29:33319 client->session()->connection()->decrypter());
320 const QuicEncrypter* client_forward_secure_encrypter(
321 client->session()->connection()->encrypter(ENCRYPTION_FORWARD_SECURE));
322 const QuicDecrypter* client_forward_secure_decrypter(
[email protected]8ba81212013-05-03 13:11:48323 client->session()->connection()->alternative_decrypter());
324 const QuicEncrypter* server_encrypter(
325 server->session()->connection()->encrypter(ENCRYPTION_INITIAL));
326 const QuicDecrypter* server_decrypter(
327 server->session()->connection()->decrypter());
[email protected]2532de12013-05-09 12:29:33328 const QuicEncrypter* server_forward_secure_encrypter(
329 server->session()->connection()->encrypter(ENCRYPTION_FORWARD_SECURE));
330 const QuicDecrypter* server_forward_secure_decrypter(
331 server->session()->connection()->alternative_decrypter());
[email protected]8ba81212013-05-03 13:11:48332
333 StringPiece client_encrypter_key = client_encrypter->GetKey();
334 StringPiece client_encrypter_iv = client_encrypter->GetNoncePrefix();
335 StringPiece client_decrypter_key = client_decrypter->GetKey();
336 StringPiece client_decrypter_iv = client_decrypter->GetNoncePrefix();
[email protected]2532de12013-05-09 12:29:33337 StringPiece client_forward_secure_encrypter_key =
338 client_forward_secure_encrypter->GetKey();
339 StringPiece client_forward_secure_encrypter_iv =
340 client_forward_secure_encrypter->GetNoncePrefix();
341 StringPiece client_forward_secure_decrypter_key =
342 client_forward_secure_decrypter->GetKey();
343 StringPiece client_forward_secure_decrypter_iv =
344 client_forward_secure_decrypter->GetNoncePrefix();
[email protected]8ba81212013-05-03 13:11:48345 StringPiece server_encrypter_key = server_encrypter->GetKey();
346 StringPiece server_encrypter_iv = server_encrypter->GetNoncePrefix();
347 StringPiece server_decrypter_key = server_decrypter->GetKey();
348 StringPiece server_decrypter_iv = server_decrypter->GetNoncePrefix();
[email protected]2532de12013-05-09 12:29:33349 StringPiece server_forward_secure_encrypter_key =
350 server_forward_secure_encrypter->GetKey();
351 StringPiece server_forward_secure_encrypter_iv =
352 server_forward_secure_encrypter->GetNoncePrefix();
353 StringPiece server_forward_secure_decrypter_key =
354 server_forward_secure_decrypter->GetKey();
355 StringPiece server_forward_secure_decrypter_iv =
356 server_forward_secure_decrypter->GetNoncePrefix();
[email protected]8ba81212013-05-03 13:11:48357
[email protected]14e8106c2013-03-14 16:25:33358 CompareCharArraysWithHexError("client write key",
359 client_encrypter_key.data(),
360 client_encrypter_key.length(),
361 server_decrypter_key.data(),
362 server_decrypter_key.length());
363 CompareCharArraysWithHexError("client write IV",
364 client_encrypter_iv.data(),
365 client_encrypter_iv.length(),
366 server_decrypter_iv.data(),
367 server_decrypter_iv.length());
368 CompareCharArraysWithHexError("server write key",
369 server_encrypter_key.data(),
370 server_encrypter_key.length(),
371 client_decrypter_key.data(),
372 client_decrypter_key.length());
373 CompareCharArraysWithHexError("server write IV",
374 server_encrypter_iv.data(),
375 server_encrypter_iv.length(),
376 client_decrypter_iv.data(),
377 client_decrypter_iv.length());
[email protected]2532de12013-05-09 12:29:33378 CompareCharArraysWithHexError("client forward secure write key",
379 client_forward_secure_encrypter_key.data(),
380 client_forward_secure_encrypter_key.length(),
381 server_forward_secure_decrypter_key.data(),
382 server_forward_secure_decrypter_key.length());
383 CompareCharArraysWithHexError("client forward secure write IV",
384 client_forward_secure_encrypter_iv.data(),
385 client_forward_secure_encrypter_iv.length(),
386 server_forward_secure_decrypter_iv.data(),
387 server_forward_secure_decrypter_iv.length());
388 CompareCharArraysWithHexError("server forward secure write key",
389 server_forward_secure_encrypter_key.data(),
390 server_forward_secure_encrypter_key.length(),
391 client_forward_secure_decrypter_key.data(),
392 client_forward_secure_decrypter_key.length());
393 CompareCharArraysWithHexError("server forward secure write IV",
394 server_forward_secure_encrypter_iv.data(),
395 server_forward_secure_encrypter_iv.length(),
396 client_forward_secure_decrypter_iv.data(),
397 client_forward_secure_decrypter_iv.length());
[email protected]ed3fc15d2013-03-08 18:37:44398}
[email protected]0bbeb6972013-05-23 04:10:21399
400// static
401QuicTag CryptoTestUtils::ParseTag(const char* tagstr) {
402 const size_t len = strlen(tagstr);
403 CHECK_NE(0u, len);
404
405 QuicTag tag = 0;
406
407 if (tagstr[0] == '#') {
408 CHECK_EQ(static_cast<size_t>(1 + 2*4), len);
409 tagstr++;
410
411 for (size_t i = 0; i < 8; i++) {
412 tag <<= 4;
413
414 uint8 v = 0;
415 CHECK(HexChar(tagstr[i], &v));
416 tag |= v;
417 }
418
419 return tag;
420 }
421
422 CHECK_LE(len, 4u);
423 for (size_t i = 0; i < 4; i++) {
424 tag >>= 8;
425 if (i < len) {
426 tag |= static_cast<uint32>(tagstr[i]) << 24;
427 }
428 }
429
430 return tag;
431}
432
433// static
434CryptoHandshakeMessage CryptoTestUtils::Message(const char* message_tag, ...) {
435 va_list ap;
436 va_start(ap, message_tag);
437
438 CryptoHandshakeMessage message = BuildMessage(message_tag, ap);
439 va_end(ap);
440 return message;
441}
442
443// static
444CryptoHandshakeMessage CryptoTestUtils::BuildMessage(const char* message_tag,
445 va_list ap) {
446 CryptoHandshakeMessage msg;
447 msg.set_tag(ParseTag(message_tag));
448
449 for (;;) {
450 const char* tagstr = va_arg(ap, const char*);
451 if (tagstr == NULL) {
452 break;
453 }
454
[email protected]4e49b6a2013-06-18 16:39:28455 if (tagstr[0] == '$') {
456 // Special value.
457 const char* const special = tagstr + 1;
458 if (strcmp(special, "padding") == 0) {
459 const int min_bytes = va_arg(ap, int);
460 msg.set_minimum_size(min_bytes);
461 } else {
462 CHECK(false) << "Unknown special value: " << special;
463 }
464
465 continue;
466 }
467
[email protected]0bbeb6972013-05-23 04:10:21468 const QuicTag tag = ParseTag(tagstr);
469 const char* valuestr = va_arg(ap, const char*);
470
471 size_t len = strlen(valuestr);
472 if (len > 0 && valuestr[0] == '#') {
473 valuestr++;
474 len--;
475
476 CHECK(len % 2 == 0);
477 scoped_ptr<uint8[]> buf(new uint8[len/2]);
478
479 for (size_t i = 0; i < len/2; i++) {
480 uint8 v = 0;
481 CHECK(HexChar(valuestr[i*2], &v));
482 buf[i] = v << 4;
483 CHECK(HexChar(valuestr[i*2 + 1], &v));
484 buf[i] |= v;
485 }
486
487 msg.SetStringPiece(
488 tag, StringPiece(reinterpret_cast<char*>(buf.get()), len/2));
489 continue;
490 }
491
492 msg.SetStringPiece(tag, valuestr);
493 }
494
[email protected]4e49b6a2013-06-18 16:39:28495 // The CryptoHandshakeMessage needs to be serialized and parsed to ensure
496 // that any padding is included.
497 scoped_ptr<QuicData> bytes(CryptoFramer::ConstructHandshakeMessage(msg));
498 scoped_ptr<CryptoHandshakeMessage> parsed(
499 CryptoFramer::ParseMessage(bytes->AsStringPiece()));
500 CHECK(parsed.get());
501
502 return *parsed;
[email protected]0bbeb6972013-05-23 04:10:21503}
504
[email protected]ed3fc15d2013-03-08 18:37:44505} // namespace test
506} // namespace net