12a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Copyright (c) 2012 The Chromium Authors. All rights reserved.
22a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
32a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// found in the LICENSE file.
42a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
52a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "net/spdy/spdy_test_utils.h"
62a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
72a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include <cstring>
8cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)#include <vector>
92a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1003b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)#include "base/base64.h"
112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/logging.h"
122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/memory/scoped_ptr.h"
13cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)#include "base/strings/string_number_conversions.h"
142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/sys_byteorder.h"
1503b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)#include "net/http/transport_security_state.h"
1603b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)#include "net/ssl/ssl_info.h"
172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "testing/gtest/include/gtest/gtest.h"
182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)namespace net {
202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)namespace test {
222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)std::string HexDumpWithMarks(const unsigned char* data, int length,
242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                             const bool* marks, int mark_length) {
252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  static const char kHexChars[] = "0123456789abcdef";
262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  static const int kColumns = 4;
272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  const int kSizeLimit = 1024;
292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (length > kSizeLimit || mark_length > kSizeLimit) {
302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    LOG(ERROR) << "Only dumping first " << kSizeLimit << " bytes.";
312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    length = std::min(length, kSizeLimit);
322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    mark_length = std::min(mark_length, kSizeLimit);
332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  std::string hex;
362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  for (const unsigned char* row = data; length > 0;
372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)       row += kColumns, length -= kColumns) {
382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    for (const unsigned char *p = row; p < row + 4; ++p) {
392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      if (p < row + length) {
402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        const bool mark =
412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)            (marks && (p - data) < mark_length && marks[p - data]);
422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        hex += mark ? '*' : ' ';
432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        hex += kHexChars[(*p & 0xf0) >> 4];
442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        hex += kHexChars[*p & 0x0f];
452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        hex += mark ? '*' : ' ';
462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      } else {
472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        hex += "    ";
482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      }
492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    }
502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    hex = hex + "  ";
512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    for (const unsigned char *p = row; p < row + 4 && p < row + length; ++p)
532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      hex += (*p >= 0x20 && *p <= 0x7f) ? (*p) : '.';
542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    hex = hex + '\n';
562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return hex;
582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void CompareCharArraysWithHexError(
612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const std::string& description,
622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const unsigned char* actual,
632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const int actual_len,
642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const unsigned char* expected,
652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const int expected_len) {
662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  const int min_len = std::min(actual_len, expected_len);
672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  const int max_len = std::max(actual_len, expected_len);
68c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  scoped_ptr<bool[]> marks(new bool[max_len]);
692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  bool identical = (actual_len == expected_len);
702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  for (int i = 0; i < min_len; ++i) {
712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    if (actual[i] != expected[i]) {
722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      marks[i] = true;
732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      identical = false;
742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    } else {
752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      marks[i] = false;
762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    }
772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  for (int i = min_len; i < max_len; ++i) {
792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    marks[i] = true;
802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (identical) return;
822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  ADD_FAILURE()
832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      << "Description:\n"
842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      << description
852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      << "\n\nExpected:\n"
862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      << HexDumpWithMarks(expected, expected_len, marks.get(), max_len)
872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      << "\nActual:\n"
882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      << HexDumpWithMarks(actual, actual_len, marks.get(), max_len);
892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
915c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liuvoid SetFrameFlags(SpdyFrame* frame,
925c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu                   uint8 flags,
935c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu                   SpdyMajorVersion spdy_version) {
942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  switch (spdy_version) {
955c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    case SPDY2:
965c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    case SPDY3:
975c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    case SPDY4:
985c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    case SPDY5:
9903b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)      frame->data()[4] = flags;
1002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      break;
1012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    default:
1022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      LOG(FATAL) << "Unsupported SPDY version.";
1032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
1042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
1052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1065c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liuvoid SetFrameLength(SpdyFrame* frame,
1075c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu                    size_t length,
1085c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu                    SpdyMajorVersion spdy_version) {
1092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  switch (spdy_version) {
1105c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    case SPDY2:
1115c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    case SPDY3:
1122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      CHECK_EQ(0u, length & ~kLengthMask);
1132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      {
1142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        int32 wire_length = base::HostToNet32(length);
1152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        // The length field in SPDY 2 and 3 is a 24-bit (3B) integer starting at
1162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        // offset 5.
1172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        memcpy(frame->data() + 5, reinterpret_cast<char*>(&wire_length) + 1, 3);
1182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      }
1192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      break;
1205c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    case SPDY4:
1215c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    case SPDY5:
1224ad1aa43a48567659193a298fad74f55e00b3dd9Ben Murdoch      CHECK_GT(1u<<14, length);
1232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      {
12403b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)        int32 wire_length = base::HostToNet32(length);
1252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        memcpy(frame->data(),
12603b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)               reinterpret_cast<char*>(&wire_length) + 1,
12703b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)               3);
1282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      }
1292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      break;
1302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    default:
1312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      LOG(FATAL) << "Unsupported SPDY version.";
1322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
1332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
1342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
135cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)std::string a2b_hex(const char* hex_data) {
136cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  std::vector<uint8> output;
137cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  std::string result;
138cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  if (base::HexStringToBytes(hex_data, &output))
139cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    result.assign(reinterpret_cast<const char*>(&output[0]), output.size());
140cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  return result;
141cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)}
1422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
14303b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)HashValue GetTestHashValue(uint8_t label) {
14403b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  HashValue hash_value(HASH_VALUE_SHA256);
14503b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  memset(hash_value.data(), label, hash_value.size());
14603b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  return hash_value;
14703b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)}
14803b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)
14903b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)std::string GetTestPin(uint8_t label) {
15003b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  HashValue hash_value = GetTestHashValue(label);
15103b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  std::string base64;
15203b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  base::Base64Encode(base::StringPiece(
15303b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)      reinterpret_cast<char*>(hash_value.data()), hash_value.size()), &base64);
15403b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)
15503b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  return std::string("pin-sha256=\"") + base64 + "\"";
15603b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)}
15703b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)
15803b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)void AddPin(TransportSecurityState* state,
15903b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)            const std::string& host,
16003b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)            uint8_t primary_label,
16103b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)            uint8_t backup_label) {
16203b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  std::string primary_pin = GetTestPin(primary_label);
16303b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  std::string backup_pin = GetTestPin(backup_label);
16403b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  std::string header = "max-age = 10000; " + primary_pin + "; " + backup_pin;
16503b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)
16603b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  // Construct a fake SSLInfo that will pass AddHPKPHeader's checks.
16703b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  SSLInfo ssl_info;
16803b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  ssl_info.is_issued_by_known_root = true;
16903b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  ssl_info.public_key_hashes.push_back(GetTestHashValue(primary_label));
17003b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  EXPECT_TRUE(state->AddHPKPHeader(host, header, ssl_info));
17103b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)}
17203b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)
1732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}  // namespace test
1742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}  // namespace net
176