1 // 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/spdy/spdy_test_utils.h" 6 7 #include <cstring> 8 #include <vector> 9 10 #include "base/base64.h" 11 #include "base/logging.h" 12 #include "base/memory/scoped_ptr.h" 13 #include "base/strings/string_number_conversions.h" 14 #include "base/sys_byteorder.h" 15 #include "net/http/transport_security_state.h" 16 #include "net/ssl/ssl_info.h" 17 #include "testing/gtest/include/gtest/gtest.h" 18 19 namespace net { 20 21 namespace test { 22 23 std::string HexDumpWithMarks(const unsigned char* data, int length, 24 const bool* marks, int mark_length) { 25 static const char kHexChars[] = "0123456789abcdef"; 26 static const int kColumns = 4; 27 28 const int kSizeLimit = 1024; 29 if (length > kSizeLimit || mark_length > kSizeLimit) { 30 LOG(ERROR) << "Only dumping first " << kSizeLimit << " bytes."; 31 length = std::min(length, kSizeLimit); 32 mark_length = std::min(mark_length, kSizeLimit); 33 } 34 35 std::string hex; 36 for (const unsigned char* row = data; length > 0; 37 row += kColumns, length -= kColumns) { 38 for (const unsigned char *p = row; p < row + 4; ++p) { 39 if (p < row + length) { 40 const bool mark = 41 (marks && (p - data) < mark_length && marks[p - data]); 42 hex += mark ? '*' : ' '; 43 hex += kHexChars[(*p & 0xf0) >> 4]; 44 hex += kHexChars[*p & 0x0f]; 45 hex += mark ? '*' : ' '; 46 } else { 47 hex += " "; 48 } 49 } 50 hex = hex + " "; 51 52 for (const unsigned char *p = row; p < row + 4 && p < row + length; ++p) 53 hex += (*p >= 0x20 && *p <= 0x7f) ? (*p) : '.'; 54 55 hex = hex + '\n'; 56 } 57 return hex; 58 } 59 60 void CompareCharArraysWithHexError( 61 const std::string& description, 62 const unsigned char* actual, 63 const int actual_len, 64 const unsigned char* expected, 65 const int expected_len) { 66 const int min_len = std::min(actual_len, expected_len); 67 const int max_len = std::max(actual_len, expected_len); 68 scoped_ptr<bool[]> marks(new bool[max_len]); 69 bool identical = (actual_len == expected_len); 70 for (int i = 0; i < min_len; ++i) { 71 if (actual[i] != expected[i]) { 72 marks[i] = true; 73 identical = false; 74 } else { 75 marks[i] = false; 76 } 77 } 78 for (int i = min_len; i < max_len; ++i) { 79 marks[i] = true; 80 } 81 if (identical) return; 82 ADD_FAILURE() 83 << "Description:\n" 84 << description 85 << "\n\nExpected:\n" 86 << HexDumpWithMarks(expected, expected_len, marks.get(), max_len) 87 << "\nActual:\n" 88 << HexDumpWithMarks(actual, actual_len, marks.get(), max_len); 89 } 90 91 void SetFrameFlags(SpdyFrame* frame, 92 uint8 flags, 93 SpdyMajorVersion spdy_version) { 94 switch (spdy_version) { 95 case SPDY2: 96 case SPDY3: 97 case SPDY4: 98 case SPDY5: 99 frame->data()[4] = flags; 100 break; 101 default: 102 LOG(FATAL) << "Unsupported SPDY version."; 103 } 104 } 105 106 void SetFrameLength(SpdyFrame* frame, 107 size_t length, 108 SpdyMajorVersion spdy_version) { 109 switch (spdy_version) { 110 case SPDY2: 111 case SPDY3: 112 CHECK_EQ(0u, length & ~kLengthMask); 113 { 114 int32 wire_length = base::HostToNet32(length); 115 // The length field in SPDY 2 and 3 is a 24-bit (3B) integer starting at 116 // offset 5. 117 memcpy(frame->data() + 5, reinterpret_cast<char*>(&wire_length) + 1, 3); 118 } 119 break; 120 case SPDY4: 121 case SPDY5: 122 CHECK_GT(1u<<14, length); 123 { 124 int32 wire_length = base::HostToNet32(length); 125 memcpy(frame->data(), 126 reinterpret_cast<char*>(&wire_length) + 1, 127 3); 128 } 129 break; 130 default: 131 LOG(FATAL) << "Unsupported SPDY version."; 132 } 133 } 134 135 std::string a2b_hex(const char* hex_data) { 136 std::vector<uint8> output; 137 std::string result; 138 if (base::HexStringToBytes(hex_data, &output)) 139 result.assign(reinterpret_cast<const char*>(&output[0]), output.size()); 140 return result; 141 } 142 143 HashValue GetTestHashValue(uint8_t label) { 144 HashValue hash_value(HASH_VALUE_SHA256); 145 memset(hash_value.data(), label, hash_value.size()); 146 return hash_value; 147 } 148 149 std::string GetTestPin(uint8_t label) { 150 HashValue hash_value = GetTestHashValue(label); 151 std::string base64; 152 base::Base64Encode(base::StringPiece( 153 reinterpret_cast<char*>(hash_value.data()), hash_value.size()), &base64); 154 155 return std::string("pin-sha256=\"") + base64 + "\""; 156 } 157 158 void AddPin(TransportSecurityState* state, 159 const std::string& host, 160 uint8_t primary_label, 161 uint8_t backup_label) { 162 std::string primary_pin = GetTestPin(primary_label); 163 std::string backup_pin = GetTestPin(backup_label); 164 std::string header = "max-age = 10000; " + primary_pin + "; " + backup_pin; 165 166 // Construct a fake SSLInfo that will pass AddHPKPHeader's checks. 167 SSLInfo ssl_info; 168 ssl_info.is_issued_by_known_root = true; 169 ssl_info.public_key_hashes.push_back(GetTestHashValue(primary_label)); 170 EXPECT_TRUE(state->AddHPKPHeader(host, header, ssl_info)); 171 } 172 173 } // namespace test 174 175 } // namespace net 176