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.
8 #include "base/base64.h"
9 #include "base/strings/string_piece.h"
10 #include "crypto/sha2.h"
11 #include "net/base/host_port_pair.h"
12 #include "net/base/test_completion_callback.h"
13 #include "net/http/http_security_headers.h"
14 #include "net/http/http_util.h"
15 #include "net/http/transport_security_state.h"
16 #include "net/log/net_log.h"
17 #include "net/ssl/ssl_info.h"
18 #include "testing/gtest/include/gtest/gtest.h"
24 HashValue
GetTestHashValue(uint8 label
, HashValueTag tag
) {
25 HashValue
hash_value(tag
);
26 memset(hash_value
.data(), label
, hash_value
.size());
30 std::string
GetTestPinImpl(uint8 label
, HashValueTag tag
, bool quoted
) {
31 HashValue hash_value
= GetTestHashValue(label
, tag
);
33 base::Base64Encode(base::StringPiece(
34 reinterpret_cast<char*>(hash_value
.data()), hash_value
.size()), &base64
);
37 switch (hash_value
.tag
) {
38 case HASH_VALUE_SHA256
:
42 NOTREACHED() << "Unknown HashValueTag " << hash_value
.tag
;
43 return std::string("ERROR");
53 std::string
GetTestPin(uint8 label
, HashValueTag tag
) {
54 return GetTestPinImpl(label
, tag
, true);
57 std::string
GetTestPinUnquoted(uint8 label
, HashValueTag tag
) {
58 return GetTestPinImpl(label
, tag
, false);
63 // Parses the given header |value| as both a Public-Key-Pins-Report-Only
64 // and Public-Key-Pins header. Returns true if the value parses
65 // successfully for both header types, and if the parsed hashes and
66 // report_uri match for both header types.
67 bool ParseAsHPKPHeader(const std::string
& value
,
68 const HashValueVector
& chain_hashes
,
69 base::TimeDelta
* max_age
,
70 bool* include_subdomains
,
71 HashValueVector
* hashes
,
74 bool report_only_include_subdomains
;
75 HashValueVector report_only_hashes
;
76 if (!ParseHPKPReportOnlyHeader(value
, &report_only_include_subdomains
,
77 &report_only_hashes
, &report_only_uri
)) {
81 bool result
= ParseHPKPHeader(value
, chain_hashes
, max_age
,
82 include_subdomains
, hashes
, report_uri
);
83 if (!result
|| report_only_include_subdomains
!= *include_subdomains
||
84 report_only_uri
!= *report_uri
||
85 report_only_hashes
.size() != hashes
->size()) {
89 for (size_t i
= 0; i
< report_only_hashes
.size(); i
++) {
90 if (!(*hashes
)[i
].Equals(report_only_hashes
[i
]))
97 class HttpSecurityHeadersTest
: public testing::Test
{
101 TEST_F(HttpSecurityHeadersTest
, BogusHeaders
) {
102 base::TimeDelta max_age
;
103 bool include_subdomains
= false;
106 ParseHSTSHeader(std::string(), &max_age
, &include_subdomains
));
107 EXPECT_FALSE(ParseHSTSHeader(" ", &max_age
, &include_subdomains
));
108 EXPECT_FALSE(ParseHSTSHeader("abc", &max_age
, &include_subdomains
));
109 EXPECT_FALSE(ParseHSTSHeader(" abc", &max_age
, &include_subdomains
));
110 EXPECT_FALSE(ParseHSTSHeader(" abc ", &max_age
, &include_subdomains
));
111 EXPECT_FALSE(ParseHSTSHeader("max-age", &max_age
, &include_subdomains
));
112 EXPECT_FALSE(ParseHSTSHeader(" max-age", &max_age
,
113 &include_subdomains
));
114 EXPECT_FALSE(ParseHSTSHeader(" max-age ", &max_age
,
115 &include_subdomains
));
116 EXPECT_FALSE(ParseHSTSHeader("max-age=", &max_age
, &include_subdomains
));
117 EXPECT_FALSE(ParseHSTSHeader(" max-age=", &max_age
,
118 &include_subdomains
));
119 EXPECT_FALSE(ParseHSTSHeader(" max-age =", &max_age
,
120 &include_subdomains
));
121 EXPECT_FALSE(ParseHSTSHeader(" max-age= ", &max_age
,
122 &include_subdomains
));
123 EXPECT_FALSE(ParseHSTSHeader(" max-age = ", &max_age
,
124 &include_subdomains
));
125 EXPECT_FALSE(ParseHSTSHeader(" max-age = xy", &max_age
,
126 &include_subdomains
));
127 EXPECT_FALSE(ParseHSTSHeader(" max-age = 3488a923", &max_age
,
128 &include_subdomains
));
129 EXPECT_FALSE(ParseHSTSHeader("max-age=3488a923 ", &max_age
,
130 &include_subdomains
));
131 EXPECT_FALSE(ParseHSTSHeader("max-ag=3488923", &max_age
,
132 &include_subdomains
));
133 EXPECT_FALSE(ParseHSTSHeader("max-aged=3488923", &max_age
,
134 &include_subdomains
));
135 EXPECT_FALSE(ParseHSTSHeader("max-age==3488923", &max_age
,
136 &include_subdomains
));
137 EXPECT_FALSE(ParseHSTSHeader("amax-age=3488923", &max_age
,
138 &include_subdomains
));
139 EXPECT_FALSE(ParseHSTSHeader("max-age=-3488923", &max_age
,
140 &include_subdomains
));
141 EXPECT_FALSE(ParseHSTSHeader("max-age=3488923 e", &max_age
,
142 &include_subdomains
));
143 EXPECT_FALSE(ParseHSTSHeader("max-age=3488923 includesubdomain",
144 &max_age
, &include_subdomains
));
145 EXPECT_FALSE(ParseHSTSHeader("max-age=3488923includesubdomains",
146 &max_age
, &include_subdomains
));
147 EXPECT_FALSE(ParseHSTSHeader("max-age=3488923=includesubdomains",
148 &max_age
, &include_subdomains
));
149 EXPECT_FALSE(ParseHSTSHeader("max-age=3488923 includesubdomainx",
150 &max_age
, &include_subdomains
));
151 EXPECT_FALSE(ParseHSTSHeader("max-age=3488923 includesubdomain=",
152 &max_age
, &include_subdomains
));
153 EXPECT_FALSE(ParseHSTSHeader("max-age=3488923 includesubdomain=true",
154 &max_age
, &include_subdomains
));
155 EXPECT_FALSE(ParseHSTSHeader("max-age=3488923 includesubdomainsx",
156 &max_age
, &include_subdomains
));
157 EXPECT_FALSE(ParseHSTSHeader("max-age=3488923 includesubdomains x",
158 &max_age
, &include_subdomains
));
159 EXPECT_FALSE(ParseHSTSHeader("max-age=34889.23 includesubdomains",
160 &max_age
, &include_subdomains
));
161 EXPECT_FALSE(ParseHSTSHeader("max-age=34889 includesubdomains",
162 &max_age
, &include_subdomains
));
163 EXPECT_FALSE(ParseHSTSHeader(";;;; ;;;",
164 &max_age
, &include_subdomains
));
165 EXPECT_FALSE(ParseHSTSHeader(";;;; includeSubDomains;;;",
166 &max_age
, &include_subdomains
));
167 EXPECT_FALSE(ParseHSTSHeader(" includeSubDomains; ",
168 &max_age
, &include_subdomains
));
169 EXPECT_FALSE(ParseHSTSHeader(";",
170 &max_age
, &include_subdomains
));
171 EXPECT_FALSE(ParseHSTSHeader("max-age; ;",
172 &max_age
, &include_subdomains
));
174 // Check the out args were not updated by checking the default
175 // values for its predictable fields.
176 EXPECT_EQ(0, max_age
.InSeconds());
177 EXPECT_FALSE(include_subdomains
);
180 static void TestBogusPinsHeaders(HashValueTag tag
) {
181 base::TimeDelta max_age
;
182 bool include_subdomains
;
183 HashValueVector hashes
;
184 HashValueVector chain_hashes
;
187 // Set some fake "chain" hashes
188 chain_hashes
.push_back(GetTestHashValue(1, tag
));
189 chain_hashes
.push_back(GetTestHashValue(2, tag
));
190 chain_hashes
.push_back(GetTestHashValue(3, tag
));
192 // The good pin must be in the chain, the backup pin must not be
193 std::string good_pin
= GetTestPin(2, tag
);
194 std::string good_pin_unquoted
= GetTestPinUnquoted(2, tag
);
195 std::string backup_pin
= GetTestPin(4, tag
);
197 EXPECT_FALSE(ParseAsHPKPHeader(std::string(), chain_hashes
, &max_age
,
198 &include_subdomains
, &hashes
, &report_uri
));
199 EXPECT_FALSE(ParseAsHPKPHeader(" ", chain_hashes
, &max_age
,
200 &include_subdomains
, &hashes
, &report_uri
));
201 EXPECT_FALSE(ParseAsHPKPHeader("abc", chain_hashes
, &max_age
,
202 &include_subdomains
, &hashes
, &report_uri
));
203 EXPECT_FALSE(ParseAsHPKPHeader(" abc", chain_hashes
, &max_age
,
204 &include_subdomains
, &hashes
, &report_uri
));
205 EXPECT_FALSE(ParseAsHPKPHeader(" abc ", chain_hashes
, &max_age
,
206 &include_subdomains
, &hashes
, &report_uri
));
207 EXPECT_FALSE(ParseAsHPKPHeader("max-age", chain_hashes
, &max_age
,
208 &include_subdomains
, &hashes
, &report_uri
));
209 EXPECT_FALSE(ParseAsHPKPHeader(" max-age", chain_hashes
, &max_age
,
210 &include_subdomains
, &hashes
, &report_uri
));
211 EXPECT_FALSE(ParseAsHPKPHeader(" max-age ", chain_hashes
, &max_age
,
212 &include_subdomains
, &hashes
, &report_uri
));
213 EXPECT_FALSE(ParseAsHPKPHeader("max-age=", chain_hashes
, &max_age
,
214 &include_subdomains
, &hashes
, &report_uri
));
215 EXPECT_FALSE(ParseAsHPKPHeader(" max-age=", chain_hashes
, &max_age
,
216 &include_subdomains
, &hashes
, &report_uri
));
217 EXPECT_FALSE(ParseAsHPKPHeader(" max-age =", chain_hashes
, &max_age
,
218 &include_subdomains
, &hashes
, &report_uri
));
219 EXPECT_FALSE(ParseAsHPKPHeader(" max-age= ", chain_hashes
, &max_age
,
220 &include_subdomains
, &hashes
, &report_uri
));
221 EXPECT_FALSE(ParseAsHPKPHeader(" max-age = ", chain_hashes
, &max_age
,
222 &include_subdomains
, &hashes
, &report_uri
));
223 EXPECT_FALSE(ParseAsHPKPHeader(" max-age = xy", chain_hashes
, &max_age
,
224 &include_subdomains
, &hashes
, &report_uri
));
225 EXPECT_FALSE(ParseAsHPKPHeader(" max-age = 3488a923", chain_hashes
,
226 &max_age
, &include_subdomains
, &hashes
,
228 EXPECT_FALSE(ParseAsHPKPHeader("max-age=3488a923 ", chain_hashes
, &max_age
,
229 &include_subdomains
, &hashes
, &report_uri
));
230 EXPECT_FALSE(ParseAsHPKPHeader(
231 "max-ag=3488923pins=" + good_pin
+ "," + backup_pin
, chain_hashes
,
232 &max_age
, &include_subdomains
, &hashes
, &report_uri
));
233 EXPECT_FALSE(ParseAsHPKPHeader(
234 "max-age=3488923;pins=" + good_pin
+ "," + backup_pin
+
235 "report-uri=\"http://foo.com\"",
236 chain_hashes
, &max_age
, &include_subdomains
, &hashes
, &report_uri
));
237 EXPECT_FALSE(ParseAsHPKPHeader("max-aged=3488923" + backup_pin
, chain_hashes
,
238 &max_age
, &include_subdomains
, &hashes
,
240 EXPECT_FALSE(ParseAsHPKPHeader("max-aged=3488923; " + backup_pin
,
241 chain_hashes
, &max_age
, &include_subdomains
,
242 &hashes
, &report_uri
));
243 EXPECT_FALSE(ParseAsHPKPHeader(
244 "max-aged=3488923; " + backup_pin
+ ";" + backup_pin
, chain_hashes
,
245 &max_age
, &include_subdomains
, &hashes
, &report_uri
));
246 EXPECT_FALSE(ParseAsHPKPHeader(
247 "max-aged=3488923; " + good_pin
+ ";" + good_pin
, chain_hashes
, &max_age
,
248 &include_subdomains
, &hashes
, &report_uri
));
249 EXPECT_FALSE(ParseAsHPKPHeader("max-aged=3488923; " + good_pin
, chain_hashes
,
250 &max_age
, &include_subdomains
, &hashes
,
252 EXPECT_FALSE(ParseAsHPKPHeader("max-age==3488923", chain_hashes
, &max_age
,
253 &include_subdomains
, &hashes
, &report_uri
));
254 EXPECT_FALSE(ParseAsHPKPHeader("amax-age=3488923", chain_hashes
, &max_age
,
255 &include_subdomains
, &hashes
, &report_uri
));
256 EXPECT_FALSE(ParseAsHPKPHeader("max-age=-3488923", chain_hashes
, &max_age
,
257 &include_subdomains
, &hashes
, &report_uri
));
258 EXPECT_FALSE(ParseAsHPKPHeader("max-age=3488923;", chain_hashes
, &max_age
,
259 &include_subdomains
, &hashes
, &report_uri
));
260 EXPECT_FALSE(ParseAsHPKPHeader("max-age=3488923 e", chain_hashes
,
261 &max_age
, &include_subdomains
, &hashes
,
263 EXPECT_FALSE(ParseAsHPKPHeader("max-age=3488923 includesubdomain",
264 chain_hashes
, &max_age
, &include_subdomains
,
265 &hashes
, &report_uri
));
266 EXPECT_FALSE(ParseAsHPKPHeader(
267 "max-age=3488923 report-uri=\"http://foo.com\"", chain_hashes
,
268 &max_age
, &include_subdomains
, &hashes
, &report_uri
));
269 EXPECT_FALSE(ParseAsHPKPHeader("max-age=34889.23", chain_hashes
, &max_age
,
270 &include_subdomains
, &hashes
, &report_uri
));
271 EXPECT_FALSE(ParseAsHPKPHeader(
272 "max-age=243; " + good_pin_unquoted
+ ";" + backup_pin
, chain_hashes
,
273 &max_age
, &include_subdomains
, &hashes
, &report_uri
));
274 EXPECT_FALSE(ParseAsHPKPHeader(
275 "max-age=243; " + good_pin
+ ";" + backup_pin
+ ";report-uri=;",
276 chain_hashes
, &max_age
, &include_subdomains
, &hashes
, &report_uri
));
277 EXPECT_FALSE(ParseAsHPKPHeader("max-age=243; " + good_pin
+ ";" + backup_pin
+
278 ";report-uri=http://foo.com;",
279 chain_hashes
, &max_age
, &include_subdomains
,
280 &hashes
, &report_uri
));
281 EXPECT_FALSE(ParseAsHPKPHeader(
282 "max-age=243; " + good_pin
+ ";" + backup_pin
+ ";report-uri=''",
283 chain_hashes
, &max_age
, &include_subdomains
, &hashes
, &report_uri
));
285 // Test that the parser rejects misquoted strings.
286 EXPECT_FALSE(ParseAsHPKPHeader(
287 "max-age=999; " + backup_pin
+ "; " + good_pin
+
288 "; report-uri=\"http://foo;bar\'",
289 chain_hashes
, &max_age
, &include_subdomains
, &hashes
, &report_uri
));
291 // Test that the parser rejects invalid report-uris.
292 EXPECT_FALSE(ParseAsHPKPHeader("max-age=999; " + backup_pin
+ "; " +
293 good_pin
+ "; report-uri=\"foo;bar\'",
294 chain_hashes
, &max_age
, &include_subdomains
,
295 &hashes
, &report_uri
));
297 // Check the out args were not updated by checking the default
298 // values for its predictable fields.
299 EXPECT_EQ(0, max_age
.InSeconds());
300 EXPECT_EQ(hashes
.size(), (size_t)0);
303 TEST_F(HttpSecurityHeadersTest
, ValidSTSHeaders
) {
304 base::TimeDelta max_age
;
305 base::TimeDelta expect_max_age
;
306 bool include_subdomains
= false;
308 EXPECT_TRUE(ParseHSTSHeader("max-age=243", &max_age
,
309 &include_subdomains
));
310 expect_max_age
= base::TimeDelta::FromSeconds(243);
311 EXPECT_EQ(expect_max_age
, max_age
);
312 EXPECT_FALSE(include_subdomains
);
314 EXPECT_TRUE(ParseHSTSHeader("max-age=3488923;", &max_age
,
315 &include_subdomains
));
317 EXPECT_TRUE(ParseHSTSHeader(" Max-agE = 567", &max_age
,
318 &include_subdomains
));
319 expect_max_age
= base::TimeDelta::FromSeconds(567);
320 EXPECT_EQ(expect_max_age
, max_age
);
321 EXPECT_FALSE(include_subdomains
);
323 EXPECT_TRUE(ParseHSTSHeader(" mAx-aGe = 890 ", &max_age
,
324 &include_subdomains
));
325 expect_max_age
= base::TimeDelta::FromSeconds(890);
326 EXPECT_EQ(expect_max_age
, max_age
);
327 EXPECT_FALSE(include_subdomains
);
329 EXPECT_TRUE(ParseHSTSHeader("max-age=123;incLudesUbdOmains", &max_age
,
330 &include_subdomains
));
331 expect_max_age
= base::TimeDelta::FromSeconds(123);
332 EXPECT_EQ(expect_max_age
, max_age
);
333 EXPECT_TRUE(include_subdomains
);
335 EXPECT_TRUE(ParseHSTSHeader("incLudesUbdOmains; max-age=123", &max_age
,
336 &include_subdomains
));
337 expect_max_age
= base::TimeDelta::FromSeconds(123);
338 EXPECT_EQ(expect_max_age
, max_age
);
339 EXPECT_TRUE(include_subdomains
);
341 EXPECT_TRUE(ParseHSTSHeader(" incLudesUbdOmains; max-age=123",
342 &max_age
, &include_subdomains
));
343 expect_max_age
= base::TimeDelta::FromSeconds(123);
344 EXPECT_EQ(expect_max_age
, max_age
);
345 EXPECT_TRUE(include_subdomains
);
347 EXPECT_TRUE(ParseHSTSHeader(
348 " incLudesUbdOmains; max-age=123; pumpkin=kitten", &max_age
,
349 &include_subdomains
));
350 expect_max_age
= base::TimeDelta::FromSeconds(123);
351 EXPECT_EQ(expect_max_age
, max_age
);
352 EXPECT_TRUE(include_subdomains
);
354 EXPECT_TRUE(ParseHSTSHeader(
355 " pumpkin=894; incLudesUbdOmains; max-age=123 ", &max_age
,
356 &include_subdomains
));
357 expect_max_age
= base::TimeDelta::FromSeconds(123);
358 EXPECT_EQ(expect_max_age
, max_age
);
359 EXPECT_TRUE(include_subdomains
);
361 EXPECT_TRUE(ParseHSTSHeader(
362 " pumpkin; incLudesUbdOmains; max-age=123 ", &max_age
,
363 &include_subdomains
));
364 expect_max_age
= base::TimeDelta::FromSeconds(123);
365 EXPECT_EQ(expect_max_age
, max_age
);
366 EXPECT_TRUE(include_subdomains
);
368 EXPECT_TRUE(ParseHSTSHeader(
369 " pumpkin; incLudesUbdOmains; max-age=\"123\" ", &max_age
,
370 &include_subdomains
));
371 expect_max_age
= base::TimeDelta::FromSeconds(123);
372 EXPECT_EQ(expect_max_age
, max_age
);
373 EXPECT_TRUE(include_subdomains
);
375 EXPECT_TRUE(ParseHSTSHeader(
376 "animal=\"squirrel; distinguished\"; incLudesUbdOmains; max-age=123",
377 &max_age
, &include_subdomains
));
378 expect_max_age
= base::TimeDelta::FromSeconds(123);
379 EXPECT_EQ(expect_max_age
, max_age
);
380 EXPECT_TRUE(include_subdomains
);
382 EXPECT_TRUE(ParseHSTSHeader("max-age=394082; incLudesUbdOmains",
383 &max_age
, &include_subdomains
));
384 expect_max_age
= base::TimeDelta::FromSeconds(394082);
385 EXPECT_EQ(expect_max_age
, max_age
);
386 EXPECT_TRUE(include_subdomains
);
388 EXPECT_TRUE(ParseHSTSHeader(
389 "max-age=39408299 ;incLudesUbdOmains", &max_age
,
390 &include_subdomains
));
391 expect_max_age
= base::TimeDelta::FromSeconds(
392 std::min(kMaxHSTSAgeSecs
, static_cast<int64
>(INT64_C(39408299))));
393 EXPECT_EQ(expect_max_age
, max_age
);
394 EXPECT_TRUE(include_subdomains
);
396 EXPECT_TRUE(ParseHSTSHeader(
397 "max-age=394082038 ; incLudesUbdOmains", &max_age
,
398 &include_subdomains
));
399 expect_max_age
= base::TimeDelta::FromSeconds(
400 std::min(kMaxHSTSAgeSecs
, static_cast<int64
>(INT64_C(394082038))));
401 EXPECT_EQ(expect_max_age
, max_age
);
402 EXPECT_TRUE(include_subdomains
);
404 EXPECT_TRUE(ParseHSTSHeader(
405 "max-age=394082038 ; incLudesUbdOmains;", &max_age
,
406 &include_subdomains
));
407 expect_max_age
= base::TimeDelta::FromSeconds(
408 std::min(kMaxHSTSAgeSecs
, static_cast<int64
>(INT64_C(394082038))));
409 EXPECT_EQ(expect_max_age
, max_age
);
410 EXPECT_TRUE(include_subdomains
);
412 EXPECT_TRUE(ParseHSTSHeader(
413 ";; max-age=394082038 ; incLudesUbdOmains; ;", &max_age
,
414 &include_subdomains
));
415 expect_max_age
= base::TimeDelta::FromSeconds(
416 std::min(kMaxHSTSAgeSecs
, static_cast<int64
>(INT64_C(394082038))));
417 EXPECT_EQ(expect_max_age
, max_age
);
418 EXPECT_TRUE(include_subdomains
);
420 EXPECT_TRUE(ParseHSTSHeader(
421 ";; max-age=394082038 ;", &max_age
,
422 &include_subdomains
));
423 expect_max_age
= base::TimeDelta::FromSeconds(
424 std::min(kMaxHSTSAgeSecs
, static_cast<int64
>(INT64_C(394082038))));
425 EXPECT_EQ(expect_max_age
, max_age
);
426 EXPECT_FALSE(include_subdomains
);
428 EXPECT_TRUE(ParseHSTSHeader(
429 ";; ; ; max-age=394082038;;; includeSubdomains ;; ;", &max_age
,
430 &include_subdomains
));
431 expect_max_age
= base::TimeDelta::FromSeconds(
432 std::min(kMaxHSTSAgeSecs
, static_cast<int64
>(INT64_C(394082038))));
433 EXPECT_EQ(expect_max_age
, max_age
);
434 EXPECT_TRUE(include_subdomains
);
436 EXPECT_TRUE(ParseHSTSHeader(
437 "incLudesUbdOmains ; max-age=394082038 ;;", &max_age
,
438 &include_subdomains
));
439 expect_max_age
= base::TimeDelta::FromSeconds(
440 std::min(kMaxHSTSAgeSecs
, static_cast<int64
>(INT64_C(394082038))));
441 EXPECT_EQ(expect_max_age
, max_age
);
442 EXPECT_TRUE(include_subdomains
);
444 EXPECT_TRUE(ParseHSTSHeader(
445 " max-age=0 ; incLudesUbdOmains ", &max_age
,
446 &include_subdomains
));
447 expect_max_age
= base::TimeDelta::FromSeconds(0);
448 EXPECT_EQ(expect_max_age
, max_age
);
449 EXPECT_TRUE(include_subdomains
);
451 EXPECT_TRUE(ParseHSTSHeader(
452 " max-age=999999999999999999999999999999999999999999999 ;"
453 " incLudesUbdOmains ", &max_age
, &include_subdomains
));
454 expect_max_age
= base::TimeDelta::FromSeconds(
456 EXPECT_EQ(expect_max_age
, max_age
);
457 EXPECT_TRUE(include_subdomains
);
460 static void TestValidPKPHeaders(HashValueTag tag
) {
461 base::TimeDelta max_age
;
462 base::TimeDelta expect_max_age
;
463 bool include_subdomains
;
464 HashValueVector hashes
;
465 HashValueVector chain_hashes
;
466 GURL expect_report_uri
;
469 // Set some fake "chain" hashes into chain_hashes
470 chain_hashes
.push_back(GetTestHashValue(1, tag
));
471 chain_hashes
.push_back(GetTestHashValue(2, tag
));
472 chain_hashes
.push_back(GetTestHashValue(3, tag
));
474 // The good pin must be in the chain, the backup pin must not be
475 std::string good_pin
= GetTestPin(2, tag
);
476 std::string good_pin2
= GetTestPin(3, tag
);
477 std::string backup_pin
= GetTestPin(4, tag
);
479 EXPECT_TRUE(ParseAsHPKPHeader("max-age=243; " + good_pin
+ ";" + backup_pin
,
480 chain_hashes
, &max_age
, &include_subdomains
,
481 &hashes
, &report_uri
));
482 expect_max_age
= base::TimeDelta::FromSeconds(243);
483 EXPECT_EQ(expect_max_age
, max_age
);
484 EXPECT_FALSE(include_subdomains
);
485 EXPECT_TRUE(report_uri
.is_empty());
487 EXPECT_TRUE(ParseAsHPKPHeader("max-age=243; " + good_pin
+ ";" + backup_pin
+
488 "; report-uri= \"http://example.test/foo\"",
489 chain_hashes
, &max_age
, &include_subdomains
,
490 &hashes
, &report_uri
));
491 expect_max_age
= base::TimeDelta::FromSeconds(243);
492 expect_report_uri
= GURL("http://example.test/foo");
493 EXPECT_EQ(expect_max_age
, max_age
);
494 EXPECT_FALSE(include_subdomains
);
495 EXPECT_EQ(expect_report_uri
, report_uri
);
497 EXPECT_TRUE(ParseAsHPKPHeader(
498 " " + good_pin
+ "; " + backup_pin
+
499 " ; Max-agE = 567; repOrT-URi = \"http://example.test/foo\"",
500 chain_hashes
, &max_age
, &include_subdomains
, &hashes
, &report_uri
));
501 expect_max_age
= base::TimeDelta::FromSeconds(567);
502 expect_report_uri
= GURL("http://example.test/foo");
503 EXPECT_EQ(expect_max_age
, max_age
);
504 EXPECT_FALSE(include_subdomains
);
505 EXPECT_EQ(expect_report_uri
, report_uri
);
507 EXPECT_TRUE(ParseAsHPKPHeader("includeSubDOMAINS;" + good_pin
+ ";" +
508 backup_pin
+ " ; mAx-aGe = 890 ",
509 chain_hashes
, &max_age
, &include_subdomains
,
510 &hashes
, &report_uri
));
511 expect_max_age
= base::TimeDelta::FromSeconds(890);
512 EXPECT_EQ(expect_max_age
, max_age
);
513 EXPECT_TRUE(include_subdomains
);
515 EXPECT_TRUE(ParseAsHPKPHeader(
516 good_pin
+ ";" + backup_pin
+ "; max-age=123;IGNORED;", chain_hashes
,
517 &max_age
, &include_subdomains
, &hashes
, &report_uri
));
518 expect_max_age
= base::TimeDelta::FromSeconds(123);
519 EXPECT_EQ(expect_max_age
, max_age
);
520 EXPECT_FALSE(include_subdomains
);
522 EXPECT_TRUE(ParseAsHPKPHeader(
523 "max-age=394082;" + backup_pin
+ ";" + good_pin
+ "; ", chain_hashes
,
524 &max_age
, &include_subdomains
, &hashes
, &report_uri
));
525 expect_max_age
= base::TimeDelta::FromSeconds(394082);
526 EXPECT_EQ(expect_max_age
, max_age
);
527 EXPECT_FALSE(include_subdomains
);
529 EXPECT_TRUE(ParseAsHPKPHeader(
530 "max-age=39408299 ;" + backup_pin
+ ";" + good_pin
+ "; ", chain_hashes
,
531 &max_age
, &include_subdomains
, &hashes
, &report_uri
));
532 expect_max_age
= base::TimeDelta::FromSeconds(
533 std::min(kMaxHSTSAgeSecs
, static_cast<int64
>(INT64_C(39408299))));
534 EXPECT_EQ(expect_max_age
, max_age
);
535 EXPECT_FALSE(include_subdomains
);
537 EXPECT_TRUE(ParseAsHPKPHeader(
538 "max-age=39408038 ; cybers=39408038 ; includeSubdomains; " +
539 good_pin
+ ";" + backup_pin
+ "; ",
540 chain_hashes
, &max_age
, &include_subdomains
, &hashes
, &report_uri
));
541 expect_max_age
= base::TimeDelta::FromSeconds(
542 std::min(kMaxHSTSAgeSecs
, static_cast<int64
>(INT64_C(394082038))));
543 EXPECT_EQ(expect_max_age
, max_age
);
544 EXPECT_TRUE(include_subdomains
);
546 EXPECT_TRUE(ParseAsHPKPHeader(
547 " max-age=0 ; " + good_pin
+ ";" + backup_pin
, chain_hashes
, &max_age
,
548 &include_subdomains
, &hashes
, &report_uri
));
549 expect_max_age
= base::TimeDelta::FromSeconds(0);
550 EXPECT_EQ(expect_max_age
, max_age
);
551 EXPECT_FALSE(include_subdomains
);
553 EXPECT_TRUE(ParseAsHPKPHeader(
554 " max-age=0 ; includeSubdomains; " + good_pin
+ ";" + backup_pin
,
555 chain_hashes
, &max_age
, &include_subdomains
, &hashes
, &report_uri
));
556 expect_max_age
= base::TimeDelta::FromSeconds(0);
557 EXPECT_EQ(expect_max_age
, max_age
);
558 EXPECT_TRUE(include_subdomains
);
560 EXPECT_TRUE(ParseAsHPKPHeader(
561 " max-age=999999999999999999999999999999999999999999999 ; " +
562 backup_pin
+ ";" + good_pin
+ "; ",
563 chain_hashes
, &max_age
, &include_subdomains
, &hashes
, &report_uri
));
564 expect_max_age
= base::TimeDelta::FromSeconds(kMaxHSTSAgeSecs
);
565 EXPECT_EQ(expect_max_age
, max_age
);
566 EXPECT_FALSE(include_subdomains
);
568 EXPECT_TRUE(ParseAsHPKPHeader(
569 " max-age=999999999999999999999999999999999999999999999 ; " +
570 backup_pin
+ ";" + good_pin
+
571 "; report-uri=\"http://example.test/foo\"",
572 chain_hashes
, &max_age
, &include_subdomains
, &hashes
, &report_uri
));
573 expect_max_age
= base::TimeDelta::FromSeconds(kMaxHSTSAgeSecs
);
574 expect_report_uri
= GURL("http://example.test/foo");
575 EXPECT_EQ(expect_max_age
, max_age
);
576 EXPECT_FALSE(include_subdomains
);
577 EXPECT_EQ(expect_report_uri
, report_uri
);
579 // Test that parsing a different header resets the hashes.
581 EXPECT_TRUE(ParseAsHPKPHeader(
582 " max-age=999; " + backup_pin
+ ";" + good_pin
+ "; ", chain_hashes
,
583 &max_age
, &include_subdomains
, &hashes
, &report_uri
));
584 EXPECT_EQ(2u, hashes
.size());
585 EXPECT_TRUE(ParseAsHPKPHeader(
586 " max-age=999; " + backup_pin
+ ";" + good_pin2
+ "; ", chain_hashes
,
587 &max_age
, &include_subdomains
, &hashes
, &report_uri
));
588 EXPECT_EQ(2u, hashes
.size());
590 // Test that the parser correctly parses an unencoded ';' inside a
591 // quoted report-uri.
592 EXPECT_TRUE(ParseAsHPKPHeader("max-age=999; " + backup_pin
+ "; " + good_pin
+
593 "; report-uri=\"http://foo.com/?;bar\"",
594 chain_hashes
, &max_age
, &include_subdomains
,
595 &hashes
, &report_uri
));
596 expect_max_age
= base::TimeDelta::FromSeconds(999);
597 expect_report_uri
= GURL("http://foo.com/?;bar");
598 EXPECT_EQ(expect_max_age
, max_age
);
599 EXPECT_FALSE(include_subdomains
);
600 EXPECT_EQ(expect_report_uri
, report_uri
);
602 // Test that the parser correctly parses a report-uri with a >0x7f
604 std::string uri
= "http://foo.com/";
606 expect_report_uri
= GURL(uri
);
607 EXPECT_TRUE(ParseAsHPKPHeader("max-age=999; " + backup_pin
+ "; " + good_pin
+
608 "; report-uri=\"" + uri
+ "\"",
609 chain_hashes
, &max_age
, &include_subdomains
,
610 &hashes
, &report_uri
));
611 expect_max_age
= base::TimeDelta::FromSeconds(999);
612 EXPECT_EQ(expect_max_age
, max_age
);
613 EXPECT_FALSE(include_subdomains
);
614 EXPECT_EQ(expect_report_uri
, report_uri
);
616 // Test that the parser allows quoted max-age values.
617 EXPECT_TRUE(ParseAsHPKPHeader(
618 "max-age='999'; " + backup_pin
+ "; " + good_pin
, chain_hashes
, &max_age
,
619 &include_subdomains
, &hashes
, &report_uri
));
620 expect_max_age
= base::TimeDelta::FromSeconds(999);
621 EXPECT_EQ(expect_max_age
, max_age
);
622 EXPECT_FALSE(include_subdomains
);
624 // Test that the parser handles escaped values.
625 expect_report_uri
= GURL("http://foo.com'a");
626 EXPECT_TRUE(ParseAsHPKPHeader("max-age=999; " + backup_pin
+ "; " + good_pin
+
627 "; report-uri='http://foo.com\\'\\a'",
628 chain_hashes
, &max_age
, &include_subdomains
,
629 &hashes
, &report_uri
));
630 expect_max_age
= base::TimeDelta::FromSeconds(999);
631 EXPECT_EQ(expect_max_age
, max_age
);
632 EXPECT_FALSE(include_subdomains
);
633 EXPECT_EQ(expect_report_uri
, report_uri
);
635 // Test that the parser does not require max-age for Report-Only
637 expect_report_uri
= GURL("http://foo.com");
638 EXPECT_TRUE(ParseHPKPReportOnlyHeader(
639 backup_pin
+ "; " + good_pin
+ "; report-uri='http://foo.com'",
640 &include_subdomains
, &hashes
, &report_uri
));
641 EXPECT_EQ(expect_report_uri
, report_uri
);
644 TEST_F(HttpSecurityHeadersTest
, BogusPinsHeadersSHA256
) {
645 TestBogusPinsHeaders(HASH_VALUE_SHA256
);
648 TEST_F(HttpSecurityHeadersTest
, ValidPKPHeadersSHA256
) {
649 TestValidPKPHeaders(HASH_VALUE_SHA256
);
652 TEST_F(HttpSecurityHeadersTest
, UpdateDynamicPKPOnly
) {
653 TransportSecurityState state
;
654 TransportSecurityState::STSState static_sts_state
;
655 TransportSecurityState::PKPState static_pkp_state
;
657 // docs.google.com has preloaded pins.
658 std::string domain
= "docs.google.com";
659 state
.enable_static_pins_
= true;
661 state
.GetStaticDomainState(domain
, &static_sts_state
, &static_pkp_state
));
662 EXPECT_GT(static_pkp_state
.spki_hashes
.size(), 1UL);
663 HashValueVector saved_hashes
= static_pkp_state
.spki_hashes
;
665 // Add a header, which should only update the dynamic state.
666 HashValue good_hash
= GetTestHashValue(1, HASH_VALUE_SHA256
);
667 HashValue backup_hash
= GetTestHashValue(2, HASH_VALUE_SHA256
);
668 std::string good_pin
= GetTestPin(1, HASH_VALUE_SHA256
);
669 std::string backup_pin
= GetTestPin(2, HASH_VALUE_SHA256
);
670 GURL
report_uri("http://google.com");
671 std::string header
= "max-age = 10000; " + good_pin
+ "; " + backup_pin
+
672 ";report-uri=\"" + report_uri
.spec() + "\"";
674 // Construct a fake SSLInfo that will pass AddHPKPHeader's checks.
676 ssl_info
.public_key_hashes
.push_back(good_hash
);
677 ssl_info
.public_key_hashes
.push_back(saved_hashes
[0]);
678 EXPECT_TRUE(state
.AddHPKPHeader(domain
, header
, ssl_info
));
680 // Expect the static state to remain unchanged.
681 TransportSecurityState::STSState new_static_sts_state
;
682 TransportSecurityState::PKPState new_static_pkp_state
;
683 EXPECT_TRUE(state
.GetStaticDomainState(domain
, &new_static_sts_state
,
684 &new_static_pkp_state
));
685 for (size_t i
= 0; i
< saved_hashes
.size(); ++i
) {
687 HashValuesEqual(saved_hashes
[i
])(new_static_pkp_state
.spki_hashes
[i
]));
690 // Expect the dynamic state to reflect the header.
691 TransportSecurityState::PKPState dynamic_pkp_state
;
692 EXPECT_TRUE(state
.GetDynamicPKPState(domain
, &dynamic_pkp_state
));
693 EXPECT_EQ(2UL, dynamic_pkp_state
.spki_hashes
.size());
694 EXPECT_EQ(report_uri
, dynamic_pkp_state
.report_uri
);
696 HashValueVector::const_iterator hash
= std::find_if(
697 dynamic_pkp_state
.spki_hashes
.begin(),
698 dynamic_pkp_state
.spki_hashes
.end(), HashValuesEqual(good_hash
));
699 EXPECT_NE(dynamic_pkp_state
.spki_hashes
.end(), hash
);
701 hash
= std::find_if(dynamic_pkp_state
.spki_hashes
.begin(),
702 dynamic_pkp_state
.spki_hashes
.end(),
703 HashValuesEqual(backup_hash
));
704 EXPECT_NE(dynamic_pkp_state
.spki_hashes
.end(), hash
);
706 // Expect the overall state to reflect the header, too.
707 EXPECT_TRUE(state
.HasPublicKeyPins(domain
));
708 HashValueVector hashes
;
709 hashes
.push_back(good_hash
);
710 std::string failure_log
;
711 const bool is_issued_by_known_root
= true;
712 HostPortPair
domain_port(domain
, 443);
713 EXPECT_TRUE(state
.CheckPublicKeyPins(
714 domain_port
, is_issued_by_known_root
, hashes
, nullptr, nullptr,
715 TransportSecurityState::DISABLE_PIN_REPORTS
, &failure_log
));
717 TransportSecurityState::PKPState new_dynamic_pkp_state
;
718 EXPECT_TRUE(state
.GetDynamicPKPState(domain
, &new_dynamic_pkp_state
));
719 EXPECT_EQ(2UL, new_dynamic_pkp_state
.spki_hashes
.size());
720 EXPECT_EQ(report_uri
, new_dynamic_pkp_state
.report_uri
);
722 hash
= std::find_if(new_dynamic_pkp_state
.spki_hashes
.begin(),
723 new_dynamic_pkp_state
.spki_hashes
.end(),
724 HashValuesEqual(good_hash
));
725 EXPECT_NE(new_dynamic_pkp_state
.spki_hashes
.end(), hash
);
727 hash
= std::find_if(new_dynamic_pkp_state
.spki_hashes
.begin(),
728 new_dynamic_pkp_state
.spki_hashes
.end(),
729 HashValuesEqual(backup_hash
));
730 EXPECT_NE(new_dynamic_pkp_state
.spki_hashes
.end(), hash
);
733 TEST_F(HttpSecurityHeadersTest
, UpdateDynamicPKPMaxAge0
) {
734 TransportSecurityState state
;
735 TransportSecurityState::STSState static_sts_state
;
736 TransportSecurityState::PKPState static_pkp_state
;
738 // docs.google.com has preloaded pins.
739 std::string domain
= "docs.google.com";
740 state
.enable_static_pins_
= true;
742 state
.GetStaticDomainState(domain
, &static_sts_state
, &static_pkp_state
));
743 EXPECT_GT(static_pkp_state
.spki_hashes
.size(), 1UL);
744 HashValueVector saved_hashes
= static_pkp_state
.spki_hashes
;
746 // Add a header, which should only update the dynamic state.
747 HashValue good_hash
= GetTestHashValue(1, HASH_VALUE_SHA256
);
748 std::string good_pin
= GetTestPin(1, HASH_VALUE_SHA256
);
749 std::string backup_pin
= GetTestPin(2, HASH_VALUE_SHA256
);
750 std::string header
= "max-age = 10000; " + good_pin
+ "; " + backup_pin
;
752 // Construct a fake SSLInfo that will pass AddHPKPHeader's checks.
754 ssl_info
.public_key_hashes
.push_back(good_hash
);
755 ssl_info
.public_key_hashes
.push_back(saved_hashes
[0]);
756 EXPECT_TRUE(state
.AddHPKPHeader(domain
, header
, ssl_info
));
758 // Expect the static state to remain unchanged.
759 TransportSecurityState::STSState new_static_sts_state
;
760 TransportSecurityState::PKPState new_static_pkp_state
;
761 EXPECT_TRUE(state
.GetStaticDomainState(domain
, &new_static_sts_state
,
762 &new_static_pkp_state
));
763 EXPECT_EQ(saved_hashes
.size(), new_static_pkp_state
.spki_hashes
.size());
764 for (size_t i
= 0; i
< saved_hashes
.size(); ++i
) {
766 HashValuesEqual(saved_hashes
[i
])(new_static_pkp_state
.spki_hashes
[i
]));
769 // Expect the dynamic state to have pins.
770 TransportSecurityState::PKPState new_dynamic_pkp_state
;
771 EXPECT_TRUE(state
.GetDynamicPKPState(domain
, &new_dynamic_pkp_state
));
772 EXPECT_EQ(2UL, new_dynamic_pkp_state
.spki_hashes
.size());
773 EXPECT_TRUE(new_dynamic_pkp_state
.HasPublicKeyPins());
775 // Now set another header with max-age=0, and check that the pins are
776 // cleared in the dynamic state only.
777 header
= "max-age = 0; " + good_pin
+ "; " + backup_pin
;
778 EXPECT_TRUE(state
.AddHPKPHeader(domain
, header
, ssl_info
));
780 // Expect the static state to remain unchanged.
781 TransportSecurityState::PKPState new_static_pkp_state2
;
782 EXPECT_TRUE(state
.GetStaticDomainState(domain
, &static_sts_state
,
783 &new_static_pkp_state2
));
784 EXPECT_EQ(saved_hashes
.size(), new_static_pkp_state2
.spki_hashes
.size());
785 for (size_t i
= 0; i
< saved_hashes
.size(); ++i
) {
787 HashValuesEqual(saved_hashes
[i
])(new_static_pkp_state2
.spki_hashes
[i
]));
790 // Expect the dynamic pins to be gone.
791 TransportSecurityState::PKPState new_dynamic_pkp_state2
;
792 EXPECT_FALSE(state
.GetDynamicPKPState(domain
, &new_dynamic_pkp_state2
));
794 // Expect the exact-matching static policy to continue to apply, even
795 // though dynamic policy has been removed. (This policy may change in the
796 // future, in which case this test must be updated.)
797 EXPECT_TRUE(state
.HasPublicKeyPins(domain
));
798 EXPECT_TRUE(state
.ShouldSSLErrorsBeFatal(domain
));
799 std::string failure_log
;
801 // Damage the hashes to cause a pin validation failure.
802 new_static_pkp_state2
.spki_hashes
[0].data()[0] ^= 0x80;
803 new_static_pkp_state2
.spki_hashes
[1].data()[0] ^= 0x80;
804 new_static_pkp_state2
.spki_hashes
[2].data()[0] ^= 0x80;
806 const bool is_issued_by_known_root
= true;
807 HostPortPair
domain_port(domain
, 443);
808 EXPECT_FALSE(state
.CheckPublicKeyPins(
809 domain_port
, is_issued_by_known_root
, new_static_pkp_state2
.spki_hashes
,
810 nullptr, nullptr, TransportSecurityState::DISABLE_PIN_REPORTS
,
812 EXPECT_NE(0UL, failure_log
.length());
815 // Tests that when a static HSTS and a static HPKP entry are present, adding a
816 // dynamic HSTS header does not clobber the static HPKP entry. Further, adding a
817 // dynamic HPKP entry could not affect the HSTS entry for the site.
818 TEST_F(HttpSecurityHeadersTest
, NoClobberPins
) {
819 TransportSecurityState state
;
820 TransportSecurityState::STSState sts_state
;
821 TransportSecurityState::PKPState pkp_state
;
823 // accounts.google.com has preloaded pins.
824 std::string domain
= "accounts.google.com";
825 state
.enable_static_pins_
= true;
827 // Retrieve the static STS and PKP states as it is by default, including its
829 EXPECT_TRUE(state
.GetStaticDomainState(domain
, &sts_state
, &pkp_state
));
830 HashValueVector saved_hashes
= pkp_state
.spki_hashes
;
831 EXPECT_TRUE(sts_state
.ShouldUpgradeToSSL());
832 EXPECT_TRUE(pkp_state
.HasPublicKeyPins());
833 EXPECT_TRUE(state
.ShouldUpgradeToSSL(domain
));
834 EXPECT_TRUE(state
.HasPublicKeyPins(domain
));
836 // Add a dynamic HSTS header. CheckPublicKeyPins should still pass when given
837 // the original |saved_hashes|, indicating that the static PKP data is still
838 // configured for the domain.
839 EXPECT_TRUE(state
.AddHSTSHeader(domain
, "includesubdomains; max-age=10000"));
840 EXPECT_TRUE(state
.ShouldUpgradeToSSL(domain
));
841 std::string failure_log
;
842 const bool is_issued_by_known_root
= true;
843 HostPortPair
domain_port(domain
, 443);
844 EXPECT_TRUE(state
.CheckPublicKeyPins(
845 domain_port
, is_issued_by_known_root
, saved_hashes
, nullptr, nullptr,
846 TransportSecurityState::DISABLE_PIN_REPORTS
, &failure_log
));
848 // Add an HPKP header, which should only update the dynamic state.
849 HashValue good_hash
= GetTestHashValue(1, HASH_VALUE_SHA256
);
850 std::string good_pin
= GetTestPin(1, HASH_VALUE_SHA256
);
851 std::string backup_pin
= GetTestPin(2, HASH_VALUE_SHA256
);
852 std::string header
= "max-age = 10000; " + good_pin
+ "; " + backup_pin
;
854 // Construct a fake SSLInfo that will pass AddHPKPHeader's checks.
856 ssl_info
.public_key_hashes
.push_back(good_hash
);
857 ssl_info
.public_key_hashes
.push_back(saved_hashes
[0]);
858 EXPECT_TRUE(state
.AddHPKPHeader(domain
, header
, ssl_info
));
860 EXPECT_TRUE(state
.AddHPKPHeader(domain
, header
, ssl_info
));
861 // HSTS should still be configured for this domain.
862 EXPECT_TRUE(sts_state
.ShouldUpgradeToSSL());
863 EXPECT_TRUE(state
.ShouldUpgradeToSSL(domain
));
864 // The dynamic pins, which do not match |saved_hashes|, should take
865 // precedence over the static pins and cause the check to fail.
866 EXPECT_FALSE(state
.CheckPublicKeyPins(
867 domain_port
, is_issued_by_known_root
, saved_hashes
, nullptr, nullptr,
868 TransportSecurityState::DISABLE_PIN_REPORTS
, &failure_log
));
871 // Tests that seeing an invalid HPKP header leaves the existing one alone.
872 TEST_F(HttpSecurityHeadersTest
, IgnoreInvalidHeaders
) {
873 TransportSecurityState state
;
875 HashValue good_hash
= GetTestHashValue(1, HASH_VALUE_SHA256
);
876 std::string good_pin
= GetTestPin(1, HASH_VALUE_SHA256
);
877 std::string bad_pin
= GetTestPin(2, HASH_VALUE_SHA256
);
878 std::string backup_pin
= GetTestPin(3, HASH_VALUE_SHA256
);
881 ssl_info
.public_key_hashes
.push_back(good_hash
);
883 // Add a valid HPKP header.
884 EXPECT_TRUE(state
.AddHPKPHeader(
885 "example.com", "max-age = 10000; " + good_pin
+ "; " + backup_pin
,
888 // Check the insertion was valid.
889 EXPECT_TRUE(state
.HasPublicKeyPins("example.com"));
890 std::string failure_log
;
891 bool is_issued_by_known_root
= true;
892 HostPortPair
domain_port("example.com", 443);
893 EXPECT_TRUE(state
.CheckPublicKeyPins(
894 domain_port
, is_issued_by_known_root
, ssl_info
.public_key_hashes
, nullptr,
895 nullptr, TransportSecurityState::DISABLE_PIN_REPORTS
, &failure_log
));
897 // Now assert an invalid one. This should fail.
898 EXPECT_FALSE(state
.AddHPKPHeader(
899 "example.com", "max-age = 10000; " + bad_pin
+ "; " + backup_pin
,
902 // The old pins must still exist.
903 EXPECT_TRUE(state
.HasPublicKeyPins("example.com"));
904 EXPECT_TRUE(state
.CheckPublicKeyPins(
905 domain_port
, is_issued_by_known_root
, ssl_info
.public_key_hashes
, nullptr,
906 nullptr, TransportSecurityState::DISABLE_PIN_REPORTS
, &failure_log
));