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"
10 #include "base/strings/string_piece.h"
11 #include "crypto/sha2.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
) {
41 case HASH_VALUE_SHA256
:
45 NOTREACHED() << "Unknown HashValueTag " << hash_value
.tag
;
46 return std::string("ERROR");
56 std::string
GetTestPin(uint8 label
, HashValueTag tag
) {
57 return GetTestPinImpl(label
, tag
, true);
60 std::string
GetTestPinUnquoted(uint8 label
, HashValueTag tag
) {
61 return GetTestPinImpl(label
, tag
, false);
67 class HttpSecurityHeadersTest
: public testing::Test
{
71 TEST_F(HttpSecurityHeadersTest
, BogusHeaders
) {
72 base::TimeDelta max_age
;
73 bool include_subdomains
= false;
76 ParseHSTSHeader(std::string(), &max_age
, &include_subdomains
));
77 EXPECT_FALSE(ParseHSTSHeader(" ", &max_age
, &include_subdomains
));
78 EXPECT_FALSE(ParseHSTSHeader("abc", &max_age
, &include_subdomains
));
79 EXPECT_FALSE(ParseHSTSHeader(" abc", &max_age
, &include_subdomains
));
80 EXPECT_FALSE(ParseHSTSHeader(" abc ", &max_age
, &include_subdomains
));
81 EXPECT_FALSE(ParseHSTSHeader("max-age", &max_age
, &include_subdomains
));
82 EXPECT_FALSE(ParseHSTSHeader(" max-age", &max_age
,
83 &include_subdomains
));
84 EXPECT_FALSE(ParseHSTSHeader(" max-age ", &max_age
,
85 &include_subdomains
));
86 EXPECT_FALSE(ParseHSTSHeader("max-age=", &max_age
, &include_subdomains
));
87 EXPECT_FALSE(ParseHSTSHeader(" max-age=", &max_age
,
88 &include_subdomains
));
89 EXPECT_FALSE(ParseHSTSHeader(" max-age =", &max_age
,
90 &include_subdomains
));
91 EXPECT_FALSE(ParseHSTSHeader(" max-age= ", &max_age
,
92 &include_subdomains
));
93 EXPECT_FALSE(ParseHSTSHeader(" max-age = ", &max_age
,
94 &include_subdomains
));
95 EXPECT_FALSE(ParseHSTSHeader(" max-age = xy", &max_age
,
96 &include_subdomains
));
97 EXPECT_FALSE(ParseHSTSHeader(" max-age = 3488a923", &max_age
,
98 &include_subdomains
));
99 EXPECT_FALSE(ParseHSTSHeader("max-age=3488a923 ", &max_age
,
100 &include_subdomains
));
101 EXPECT_FALSE(ParseHSTSHeader("max-ag=3488923", &max_age
,
102 &include_subdomains
));
103 EXPECT_FALSE(ParseHSTSHeader("max-aged=3488923", &max_age
,
104 &include_subdomains
));
105 EXPECT_FALSE(ParseHSTSHeader("max-age==3488923", &max_age
,
106 &include_subdomains
));
107 EXPECT_FALSE(ParseHSTSHeader("amax-age=3488923", &max_age
,
108 &include_subdomains
));
109 EXPECT_FALSE(ParseHSTSHeader("max-age=-3488923", &max_age
,
110 &include_subdomains
));
111 EXPECT_FALSE(ParseHSTSHeader("max-age=3488923 e", &max_age
,
112 &include_subdomains
));
113 EXPECT_FALSE(ParseHSTSHeader("max-age=3488923 includesubdomain",
114 &max_age
, &include_subdomains
));
115 EXPECT_FALSE(ParseHSTSHeader("max-age=3488923includesubdomains",
116 &max_age
, &include_subdomains
));
117 EXPECT_FALSE(ParseHSTSHeader("max-age=3488923=includesubdomains",
118 &max_age
, &include_subdomains
));
119 EXPECT_FALSE(ParseHSTSHeader("max-age=3488923 includesubdomainx",
120 &max_age
, &include_subdomains
));
121 EXPECT_FALSE(ParseHSTSHeader("max-age=3488923 includesubdomain=",
122 &max_age
, &include_subdomains
));
123 EXPECT_FALSE(ParseHSTSHeader("max-age=3488923 includesubdomain=true",
124 &max_age
, &include_subdomains
));
125 EXPECT_FALSE(ParseHSTSHeader("max-age=3488923 includesubdomainsx",
126 &max_age
, &include_subdomains
));
127 EXPECT_FALSE(ParseHSTSHeader("max-age=3488923 includesubdomains x",
128 &max_age
, &include_subdomains
));
129 EXPECT_FALSE(ParseHSTSHeader("max-age=34889.23 includesubdomains",
130 &max_age
, &include_subdomains
));
131 EXPECT_FALSE(ParseHSTSHeader("max-age=34889 includesubdomains",
132 &max_age
, &include_subdomains
));
133 EXPECT_FALSE(ParseHSTSHeader(";;;; ;;;",
134 &max_age
, &include_subdomains
));
135 EXPECT_FALSE(ParseHSTSHeader(";;;; includeSubDomains;;;",
136 &max_age
, &include_subdomains
));
137 EXPECT_FALSE(ParseHSTSHeader(" includeSubDomains; ",
138 &max_age
, &include_subdomains
));
139 EXPECT_FALSE(ParseHSTSHeader(";",
140 &max_age
, &include_subdomains
));
141 EXPECT_FALSE(ParseHSTSHeader("max-age; ;",
142 &max_age
, &include_subdomains
));
144 // Check the out args were not updated by checking the default
145 // values for its predictable fields.
146 EXPECT_EQ(0, max_age
.InSeconds());
147 EXPECT_FALSE(include_subdomains
);
150 static void TestBogusPinsHeaders(HashValueTag tag
) {
151 base::TimeDelta max_age
;
152 bool include_subdomains
;
153 HashValueVector hashes
;
154 HashValueVector chain_hashes
;
156 // Set some fake "chain" hashes
157 chain_hashes
.push_back(GetTestHashValue(1, tag
));
158 chain_hashes
.push_back(GetTestHashValue(2, tag
));
159 chain_hashes
.push_back(GetTestHashValue(3, tag
));
161 // The good pin must be in the chain, the backup pin must not be
162 std::string good_pin
= GetTestPin(2, tag
);
163 std::string good_pin_unquoted
= GetTestPinUnquoted(2, tag
);
164 std::string backup_pin
= GetTestPin(4, tag
);
166 EXPECT_FALSE(ParseHPKPHeader(std::string(), chain_hashes
, &max_age
,
167 &include_subdomains
, &hashes
));
168 EXPECT_FALSE(ParseHPKPHeader(" ", chain_hashes
, &max_age
,
169 &include_subdomains
, &hashes
));
170 EXPECT_FALSE(ParseHPKPHeader("abc", chain_hashes
, &max_age
,
171 &include_subdomains
, &hashes
));
172 EXPECT_FALSE(ParseHPKPHeader(" abc", chain_hashes
, &max_age
,
173 &include_subdomains
, &hashes
));
174 EXPECT_FALSE(ParseHPKPHeader(" abc ", chain_hashes
, &max_age
,
175 &include_subdomains
, &hashes
));
176 EXPECT_FALSE(ParseHPKPHeader("max-age", chain_hashes
, &max_age
,
177 &include_subdomains
, &hashes
));
178 EXPECT_FALSE(ParseHPKPHeader(" max-age", chain_hashes
, &max_age
,
179 &include_subdomains
, &hashes
));
180 EXPECT_FALSE(ParseHPKPHeader(" max-age ", chain_hashes
, &max_age
,
181 &include_subdomains
, &hashes
));
182 EXPECT_FALSE(ParseHPKPHeader("max-age=", chain_hashes
, &max_age
,
183 &include_subdomains
, &hashes
));
184 EXPECT_FALSE(ParseHPKPHeader(" max-age=", chain_hashes
, &max_age
,
185 &include_subdomains
, &hashes
));
186 EXPECT_FALSE(ParseHPKPHeader(" max-age =", chain_hashes
, &max_age
,
187 &include_subdomains
, &hashes
));
188 EXPECT_FALSE(ParseHPKPHeader(" max-age= ", chain_hashes
, &max_age
,
189 &include_subdomains
, &hashes
));
190 EXPECT_FALSE(ParseHPKPHeader(" max-age = ", chain_hashes
,
191 &max_age
, &include_subdomains
, &hashes
));
192 EXPECT_FALSE(ParseHPKPHeader(" max-age = xy", chain_hashes
,
193 &max_age
, &include_subdomains
, &hashes
));
194 EXPECT_FALSE(ParseHPKPHeader(" max-age = 3488a923",
195 chain_hashes
, &max_age
, &include_subdomains
,
197 EXPECT_FALSE(ParseHPKPHeader("max-age=3488a923 ", chain_hashes
,
198 &max_age
, &include_subdomains
, &hashes
));
199 EXPECT_FALSE(ParseHPKPHeader("max-ag=3488923pins=" + good_pin
+ "," +
201 chain_hashes
, &max_age
, &include_subdomains
,
203 EXPECT_FALSE(ParseHPKPHeader("max-aged=3488923" + backup_pin
,
204 chain_hashes
, &max_age
, &include_subdomains
,
206 EXPECT_FALSE(ParseHPKPHeader("max-aged=3488923; " + backup_pin
,
207 chain_hashes
, &max_age
, &include_subdomains
,
209 EXPECT_FALSE(ParseHPKPHeader("max-aged=3488923; " + backup_pin
+ ";" +
211 chain_hashes
, &max_age
, &include_subdomains
,
213 EXPECT_FALSE(ParseHPKPHeader("max-aged=3488923; " + good_pin
+ ";" +
215 chain_hashes
, &max_age
, &include_subdomains
,
217 EXPECT_FALSE(ParseHPKPHeader("max-aged=3488923; " + good_pin
,
218 chain_hashes
, &max_age
, &include_subdomains
,
220 EXPECT_FALSE(ParseHPKPHeader("max-age==3488923", chain_hashes
, &max_age
,
221 &include_subdomains
, &hashes
));
222 EXPECT_FALSE(ParseHPKPHeader("amax-age=3488923", chain_hashes
, &max_age
,
223 &include_subdomains
, &hashes
));
224 EXPECT_FALSE(ParseHPKPHeader("max-age=-3488923", chain_hashes
, &max_age
,
225 &include_subdomains
, &hashes
));
226 EXPECT_FALSE(ParseHPKPHeader("max-age=3488923;", chain_hashes
, &max_age
,
227 &include_subdomains
, &hashes
));
228 EXPECT_FALSE(ParseHPKPHeader("max-age=3488923 e", chain_hashes
,
229 &max_age
, &include_subdomains
, &hashes
));
230 EXPECT_FALSE(ParseHPKPHeader("max-age=3488923 includesubdomain",
231 chain_hashes
, &max_age
, &include_subdomains
,
233 EXPECT_FALSE(ParseHPKPHeader("max-age=34889.23", chain_hashes
, &max_age
,
234 &include_subdomains
, &hashes
));
236 ParseHPKPHeader("max-age=243; " + good_pin_unquoted
+ ";" + backup_pin
,
237 chain_hashes
, &max_age
, &include_subdomains
, &hashes
));
239 // Check the out args were not updated by checking the default
240 // values for its predictable fields.
241 EXPECT_EQ(0, max_age
.InSeconds());
242 EXPECT_EQ(hashes
.size(), (size_t)0);
245 TEST_F(HttpSecurityHeadersTest
, ValidSTSHeaders
) {
246 base::TimeDelta max_age
;
247 base::TimeDelta expect_max_age
;
248 bool include_subdomains
= false;
250 EXPECT_TRUE(ParseHSTSHeader("max-age=243", &max_age
,
251 &include_subdomains
));
252 expect_max_age
= base::TimeDelta::FromSeconds(243);
253 EXPECT_EQ(expect_max_age
, max_age
);
254 EXPECT_FALSE(include_subdomains
);
256 EXPECT_TRUE(ParseHSTSHeader("max-age=3488923;", &max_age
,
257 &include_subdomains
));
259 EXPECT_TRUE(ParseHSTSHeader(" Max-agE = 567", &max_age
,
260 &include_subdomains
));
261 expect_max_age
= base::TimeDelta::FromSeconds(567);
262 EXPECT_EQ(expect_max_age
, max_age
);
263 EXPECT_FALSE(include_subdomains
);
265 EXPECT_TRUE(ParseHSTSHeader(" mAx-aGe = 890 ", &max_age
,
266 &include_subdomains
));
267 expect_max_age
= base::TimeDelta::FromSeconds(890);
268 EXPECT_EQ(expect_max_age
, max_age
);
269 EXPECT_FALSE(include_subdomains
);
271 EXPECT_TRUE(ParseHSTSHeader("max-age=123;incLudesUbdOmains", &max_age
,
272 &include_subdomains
));
273 expect_max_age
= base::TimeDelta::FromSeconds(123);
274 EXPECT_EQ(expect_max_age
, max_age
);
275 EXPECT_TRUE(include_subdomains
);
277 EXPECT_TRUE(ParseHSTSHeader("incLudesUbdOmains; max-age=123", &max_age
,
278 &include_subdomains
));
279 expect_max_age
= base::TimeDelta::FromSeconds(123);
280 EXPECT_EQ(expect_max_age
, max_age
);
281 EXPECT_TRUE(include_subdomains
);
283 EXPECT_TRUE(ParseHSTSHeader(" incLudesUbdOmains; max-age=123",
284 &max_age
, &include_subdomains
));
285 expect_max_age
= base::TimeDelta::FromSeconds(123);
286 EXPECT_EQ(expect_max_age
, max_age
);
287 EXPECT_TRUE(include_subdomains
);
289 EXPECT_TRUE(ParseHSTSHeader(
290 " incLudesUbdOmains; max-age=123; pumpkin=kitten", &max_age
,
291 &include_subdomains
));
292 expect_max_age
= base::TimeDelta::FromSeconds(123);
293 EXPECT_EQ(expect_max_age
, max_age
);
294 EXPECT_TRUE(include_subdomains
);
296 EXPECT_TRUE(ParseHSTSHeader(
297 " pumpkin=894; incLudesUbdOmains; max-age=123 ", &max_age
,
298 &include_subdomains
));
299 expect_max_age
= base::TimeDelta::FromSeconds(123);
300 EXPECT_EQ(expect_max_age
, max_age
);
301 EXPECT_TRUE(include_subdomains
);
303 EXPECT_TRUE(ParseHSTSHeader(
304 " pumpkin; incLudesUbdOmains; max-age=123 ", &max_age
,
305 &include_subdomains
));
306 expect_max_age
= base::TimeDelta::FromSeconds(123);
307 EXPECT_EQ(expect_max_age
, max_age
);
308 EXPECT_TRUE(include_subdomains
);
310 EXPECT_TRUE(ParseHSTSHeader(
311 " pumpkin; incLudesUbdOmains; max-age=\"123\" ", &max_age
,
312 &include_subdomains
));
313 expect_max_age
= base::TimeDelta::FromSeconds(123);
314 EXPECT_EQ(expect_max_age
, max_age
);
315 EXPECT_TRUE(include_subdomains
);
317 EXPECT_TRUE(ParseHSTSHeader(
318 "animal=\"squirrel; distinguished\"; incLudesUbdOmains; max-age=123",
319 &max_age
, &include_subdomains
));
320 expect_max_age
= base::TimeDelta::FromSeconds(123);
321 EXPECT_EQ(expect_max_age
, max_age
);
322 EXPECT_TRUE(include_subdomains
);
324 EXPECT_TRUE(ParseHSTSHeader("max-age=394082; incLudesUbdOmains",
325 &max_age
, &include_subdomains
));
326 expect_max_age
= base::TimeDelta::FromSeconds(394082);
327 EXPECT_EQ(expect_max_age
, max_age
);
328 EXPECT_TRUE(include_subdomains
);
330 EXPECT_TRUE(ParseHSTSHeader(
331 "max-age=39408299 ;incLudesUbdOmains", &max_age
,
332 &include_subdomains
));
333 expect_max_age
= base::TimeDelta::FromSeconds(
334 std::min(kMaxHSTSAgeSecs
, static_cast<int64
>(INT64_C(39408299))));
335 EXPECT_EQ(expect_max_age
, max_age
);
336 EXPECT_TRUE(include_subdomains
);
338 EXPECT_TRUE(ParseHSTSHeader(
339 "max-age=394082038 ; incLudesUbdOmains", &max_age
,
340 &include_subdomains
));
341 expect_max_age
= base::TimeDelta::FromSeconds(
342 std::min(kMaxHSTSAgeSecs
, static_cast<int64
>(INT64_C(394082038))));
343 EXPECT_EQ(expect_max_age
, max_age
);
344 EXPECT_TRUE(include_subdomains
);
346 EXPECT_TRUE(ParseHSTSHeader(
347 "max-age=394082038 ; incLudesUbdOmains;", &max_age
,
348 &include_subdomains
));
349 expect_max_age
= base::TimeDelta::FromSeconds(
350 std::min(kMaxHSTSAgeSecs
, static_cast<int64
>(INT64_C(394082038))));
351 EXPECT_EQ(expect_max_age
, max_age
);
352 EXPECT_TRUE(include_subdomains
);
354 EXPECT_TRUE(ParseHSTSHeader(
355 ";; max-age=394082038 ; incLudesUbdOmains; ;", &max_age
,
356 &include_subdomains
));
357 expect_max_age
= base::TimeDelta::FromSeconds(
358 std::min(kMaxHSTSAgeSecs
, static_cast<int64
>(INT64_C(394082038))));
359 EXPECT_EQ(expect_max_age
, max_age
);
360 EXPECT_TRUE(include_subdomains
);
362 EXPECT_TRUE(ParseHSTSHeader(
363 ";; max-age=394082038 ;", &max_age
,
364 &include_subdomains
));
365 expect_max_age
= base::TimeDelta::FromSeconds(
366 std::min(kMaxHSTSAgeSecs
, static_cast<int64
>(INT64_C(394082038))));
367 EXPECT_EQ(expect_max_age
, max_age
);
368 EXPECT_FALSE(include_subdomains
);
370 EXPECT_TRUE(ParseHSTSHeader(
371 ";; ; ; max-age=394082038;;; includeSubdomains ;; ;", &max_age
,
372 &include_subdomains
));
373 expect_max_age
= base::TimeDelta::FromSeconds(
374 std::min(kMaxHSTSAgeSecs
, static_cast<int64
>(INT64_C(394082038))));
375 EXPECT_EQ(expect_max_age
, max_age
);
376 EXPECT_TRUE(include_subdomains
);
378 EXPECT_TRUE(ParseHSTSHeader(
379 "incLudesUbdOmains ; max-age=394082038 ;;", &max_age
,
380 &include_subdomains
));
381 expect_max_age
= base::TimeDelta::FromSeconds(
382 std::min(kMaxHSTSAgeSecs
, static_cast<int64
>(INT64_C(394082038))));
383 EXPECT_EQ(expect_max_age
, max_age
);
384 EXPECT_TRUE(include_subdomains
);
386 EXPECT_TRUE(ParseHSTSHeader(
387 " max-age=0 ; incLudesUbdOmains ", &max_age
,
388 &include_subdomains
));
389 expect_max_age
= base::TimeDelta::FromSeconds(0);
390 EXPECT_EQ(expect_max_age
, max_age
);
391 EXPECT_TRUE(include_subdomains
);
393 EXPECT_TRUE(ParseHSTSHeader(
394 " max-age=999999999999999999999999999999999999999999999 ;"
395 " incLudesUbdOmains ", &max_age
, &include_subdomains
));
396 expect_max_age
= base::TimeDelta::FromSeconds(
398 EXPECT_EQ(expect_max_age
, max_age
);
399 EXPECT_TRUE(include_subdomains
);
402 static void TestValidPKPHeaders(HashValueTag tag
) {
403 base::TimeDelta max_age
;
404 base::TimeDelta expect_max_age
;
405 bool include_subdomains
;
406 HashValueVector hashes
;
407 HashValueVector chain_hashes
;
409 // Set some fake "chain" hashes into chain_hashes
410 chain_hashes
.push_back(GetTestHashValue(1, tag
));
411 chain_hashes
.push_back(GetTestHashValue(2, tag
));
412 chain_hashes
.push_back(GetTestHashValue(3, tag
));
414 // The good pin must be in the chain, the backup pin must not be
415 std::string good_pin
= GetTestPin(2, tag
);
416 std::string good_pin2
= GetTestPin(3, tag
);
417 std::string backup_pin
= GetTestPin(4, tag
);
419 EXPECT_TRUE(ParseHPKPHeader(
420 "max-age=243; " + good_pin
+ ";" + backup_pin
,
421 chain_hashes
, &max_age
, &include_subdomains
, &hashes
));
422 expect_max_age
= base::TimeDelta::FromSeconds(243);
423 EXPECT_EQ(expect_max_age
, max_age
);
424 EXPECT_FALSE(include_subdomains
);
426 EXPECT_TRUE(ParseHPKPHeader(
427 " " + good_pin
+ "; " + backup_pin
+ " ; Max-agE = 567",
428 chain_hashes
, &max_age
, &include_subdomains
, &hashes
));
429 expect_max_age
= base::TimeDelta::FromSeconds(567);
430 EXPECT_EQ(expect_max_age
, max_age
);
431 EXPECT_FALSE(include_subdomains
);
433 EXPECT_TRUE(ParseHPKPHeader(
434 "includeSubDOMAINS;" + good_pin
+ ";" + backup_pin
+
436 chain_hashes
, &max_age
, &include_subdomains
, &hashes
));
437 expect_max_age
= base::TimeDelta::FromSeconds(890);
438 EXPECT_EQ(expect_max_age
, max_age
);
439 EXPECT_TRUE(include_subdomains
);
441 EXPECT_TRUE(ParseHPKPHeader(
442 good_pin
+ ";" + backup_pin
+ "; max-age=123;IGNORED;",
443 chain_hashes
, &max_age
, &include_subdomains
, &hashes
));
444 expect_max_age
= base::TimeDelta::FromSeconds(123);
445 EXPECT_EQ(expect_max_age
, max_age
);
446 EXPECT_FALSE(include_subdomains
);
448 EXPECT_TRUE(ParseHPKPHeader(
449 "max-age=394082;" + backup_pin
+ ";" + good_pin
+ "; ",
450 chain_hashes
, &max_age
, &include_subdomains
, &hashes
));
451 expect_max_age
= base::TimeDelta::FromSeconds(394082);
452 EXPECT_EQ(expect_max_age
, max_age
);
453 EXPECT_FALSE(include_subdomains
);
455 EXPECT_TRUE(ParseHPKPHeader(
456 "max-age=39408299 ;" + backup_pin
+ ";" + good_pin
+ "; ",
457 chain_hashes
, &max_age
, &include_subdomains
, &hashes
));
458 expect_max_age
= base::TimeDelta::FromSeconds(
459 std::min(kMaxHSTSAgeSecs
, static_cast<int64
>(INT64_C(39408299))));
460 EXPECT_EQ(expect_max_age
, max_age
);
461 EXPECT_FALSE(include_subdomains
);
463 EXPECT_TRUE(ParseHPKPHeader(
464 "max-age=39408038 ; cybers=39408038 ; includeSubdomains; " +
465 good_pin
+ ";" + backup_pin
+ "; ",
466 chain_hashes
, &max_age
, &include_subdomains
, &hashes
));
467 expect_max_age
= base::TimeDelta::FromSeconds(
468 std::min(kMaxHSTSAgeSecs
, static_cast<int64
>(INT64_C(394082038))));
469 EXPECT_EQ(expect_max_age
, max_age
);
470 EXPECT_TRUE(include_subdomains
);
472 EXPECT_TRUE(ParseHPKPHeader(
473 " max-age=0 ; " + good_pin
+ ";" + backup_pin
,
474 chain_hashes
, &max_age
, &include_subdomains
, &hashes
));
475 expect_max_age
= base::TimeDelta::FromSeconds(0);
476 EXPECT_EQ(expect_max_age
, max_age
);
477 EXPECT_FALSE(include_subdomains
);
479 EXPECT_TRUE(ParseHPKPHeader(
480 " max-age=0 ; includeSubdomains; " + good_pin
+ ";" + backup_pin
,
481 chain_hashes
, &max_age
, &include_subdomains
, &hashes
));
482 expect_max_age
= base::TimeDelta::FromSeconds(0);
483 EXPECT_EQ(expect_max_age
, max_age
);
484 EXPECT_TRUE(include_subdomains
);
486 EXPECT_TRUE(ParseHPKPHeader(
487 " max-age=999999999999999999999999999999999999999999999 ; " +
488 backup_pin
+ ";" + good_pin
+ "; ",
489 chain_hashes
, &max_age
, &include_subdomains
, &hashes
));
490 expect_max_age
= base::TimeDelta::FromSeconds(kMaxHSTSAgeSecs
);
491 EXPECT_EQ(expect_max_age
, max_age
);
492 EXPECT_FALSE(include_subdomains
);
494 // Test that parsing a different header resets the hashes.
496 EXPECT_TRUE(ParseHPKPHeader(
498 backup_pin
+ ";" + good_pin
+ "; ",
499 chain_hashes
, &max_age
, &include_subdomains
, &hashes
));
500 EXPECT_EQ(2u, hashes
.size());
501 EXPECT_TRUE(ParseHPKPHeader(
502 " max-age=999; " + backup_pin
+ ";" + good_pin2
+ "; ", chain_hashes
,
503 &max_age
, &include_subdomains
, &hashes
));
504 EXPECT_EQ(2u, hashes
.size());
507 TEST_F(HttpSecurityHeadersTest
, BogusPinsHeadersSHA1
) {
508 TestBogusPinsHeaders(HASH_VALUE_SHA1
);
511 TEST_F(HttpSecurityHeadersTest
, BogusPinsHeadersSHA256
) {
512 TestBogusPinsHeaders(HASH_VALUE_SHA256
);
515 TEST_F(HttpSecurityHeadersTest
, ValidPKPHeadersSHA1
) {
516 TestValidPKPHeaders(HASH_VALUE_SHA1
);
519 TEST_F(HttpSecurityHeadersTest
, ValidPKPHeadersSHA256
) {
520 TestValidPKPHeaders(HASH_VALUE_SHA256
);
523 TEST_F(HttpSecurityHeadersTest
, UpdateDynamicPKPOnly
) {
524 TransportSecurityState state
;
525 TransportSecurityState::DomainState static_domain_state
;
527 // docs.google.com has preloaded pins.
528 std::string domain
= "docs.google.com";
529 state
.enable_static_pins_
= true;
531 state
.GetStaticDomainState(domain
, &static_domain_state
));
532 EXPECT_GT(static_domain_state
.pkp
.spki_hashes
.size(), 1UL);
533 HashValueVector saved_hashes
= static_domain_state
.pkp
.spki_hashes
;
535 // Add a header, which should only update the dynamic state.
536 HashValue good_hash
= GetTestHashValue(1, HASH_VALUE_SHA1
);
537 HashValue backup_hash
= GetTestHashValue(2, HASH_VALUE_SHA1
);
538 std::string good_pin
= GetTestPin(1, HASH_VALUE_SHA1
);
539 std::string backup_pin
= GetTestPin(2, HASH_VALUE_SHA1
);
540 std::string header
= "max-age = 10000; " + good_pin
+ "; " + backup_pin
;
542 // Construct a fake SSLInfo that will pass AddHPKPHeader's checks.
544 ssl_info
.public_key_hashes
.push_back(good_hash
);
545 ssl_info
.public_key_hashes
.push_back(saved_hashes
[0]);
546 EXPECT_TRUE(state
.AddHPKPHeader(domain
, header
, ssl_info
));
548 // Expect the static state to remain unchanged.
549 TransportSecurityState::DomainState new_static_domain_state
;
550 EXPECT_TRUE(state
.GetStaticDomainState(
551 domain
, &new_static_domain_state
));
552 for (size_t i
= 0; i
< saved_hashes
.size(); ++i
) {
553 EXPECT_TRUE(HashValuesEqual(saved_hashes
[i
])(
554 new_static_domain_state
.pkp
.spki_hashes
[i
]));
557 // Expect the dynamic state to reflect the header.
558 TransportSecurityState::DomainState dynamic_domain_state
;
559 EXPECT_TRUE(state
.GetDynamicDomainState(domain
, &dynamic_domain_state
));
560 EXPECT_EQ(2UL, dynamic_domain_state
.pkp
.spki_hashes
.size());
562 HashValueVector::const_iterator hash
=
563 std::find_if(dynamic_domain_state
.pkp
.spki_hashes
.begin(),
564 dynamic_domain_state
.pkp
.spki_hashes
.end(),
565 HashValuesEqual(good_hash
));
566 EXPECT_NE(dynamic_domain_state
.pkp
.spki_hashes
.end(), hash
);
568 hash
= std::find_if(dynamic_domain_state
.pkp
.spki_hashes
.begin(),
569 dynamic_domain_state
.pkp
.spki_hashes
.end(),
570 HashValuesEqual(backup_hash
));
571 EXPECT_NE(dynamic_domain_state
.pkp
.spki_hashes
.end(), hash
);
573 // Expect the overall state to reflect the header, too.
574 EXPECT_TRUE(state
.HasPublicKeyPins(domain
));
575 HashValueVector hashes
;
576 hashes
.push_back(good_hash
);
577 std::string failure_log
;
578 const bool is_issued_by_known_root
= true;
579 EXPECT_TRUE(state
.CheckPublicKeyPins(
580 domain
, is_issued_by_known_root
, hashes
, &failure_log
));
582 TransportSecurityState::DomainState new_dynamic_domain_state
;
583 EXPECT_TRUE(state
.GetDynamicDomainState(domain
, &new_dynamic_domain_state
));
584 EXPECT_EQ(2UL, new_dynamic_domain_state
.pkp
.spki_hashes
.size());
586 hash
= std::find_if(new_dynamic_domain_state
.pkp
.spki_hashes
.begin(),
587 new_dynamic_domain_state
.pkp
.spki_hashes
.end(),
588 HashValuesEqual(good_hash
));
589 EXPECT_NE(new_dynamic_domain_state
.pkp
.spki_hashes
.end(), hash
);
591 hash
= std::find_if(new_dynamic_domain_state
.pkp
.spki_hashes
.begin(),
592 new_dynamic_domain_state
.pkp
.spki_hashes
.end(),
593 HashValuesEqual(backup_hash
));
594 EXPECT_NE(new_dynamic_domain_state
.pkp
.spki_hashes
.end(), hash
);
597 TEST_F(HttpSecurityHeadersTest
, UpdateDynamicPKPMaxAge0
) {
598 TransportSecurityState state
;
599 TransportSecurityState::DomainState static_domain_state
;
601 // docs.google.com has preloaded pins.
602 std::string domain
= "docs.google.com";
603 state
.enable_static_pins_
= true;
605 state
.GetStaticDomainState(domain
, &static_domain_state
));
606 EXPECT_GT(static_domain_state
.pkp
.spki_hashes
.size(), 1UL);
607 HashValueVector saved_hashes
= static_domain_state
.pkp
.spki_hashes
;
609 // Add a header, which should only update the dynamic state.
610 HashValue good_hash
= GetTestHashValue(1, HASH_VALUE_SHA1
);
611 std::string good_pin
= GetTestPin(1, HASH_VALUE_SHA1
);
612 std::string backup_pin
= GetTestPin(2, HASH_VALUE_SHA1
);
613 std::string header
= "max-age = 10000; " + good_pin
+ "; " + backup_pin
;
615 // Construct a fake SSLInfo that will pass AddHPKPHeader's checks.
617 ssl_info
.public_key_hashes
.push_back(good_hash
);
618 ssl_info
.public_key_hashes
.push_back(saved_hashes
[0]);
619 EXPECT_TRUE(state
.AddHPKPHeader(domain
, header
, ssl_info
));
621 // Expect the static state to remain unchanged.
622 TransportSecurityState::DomainState new_static_domain_state
;
623 EXPECT_TRUE(state
.GetStaticDomainState(
624 domain
, &new_static_domain_state
));
625 EXPECT_EQ(saved_hashes
.size(),
626 new_static_domain_state
.pkp
.spki_hashes
.size());
627 for (size_t i
= 0; i
< saved_hashes
.size(); ++i
) {
628 EXPECT_TRUE(HashValuesEqual(saved_hashes
[i
])(
629 new_static_domain_state
.pkp
.spki_hashes
[i
]));
632 // Expect the dynamic state to have pins.
633 TransportSecurityState::DomainState new_dynamic_domain_state
;
634 EXPECT_TRUE(state
.GetDynamicDomainState(domain
, &new_dynamic_domain_state
));
635 EXPECT_EQ(2UL, new_dynamic_domain_state
.pkp
.spki_hashes
.size());
636 EXPECT_TRUE(new_dynamic_domain_state
.HasPublicKeyPins());
638 // Now set another header with max-age=0, and check that the pins are
639 // cleared in the dynamic state only.
640 header
= "max-age = 0; " + good_pin
+ "; " + backup_pin
;
641 EXPECT_TRUE(state
.AddHPKPHeader(domain
, header
, ssl_info
));
643 // Expect the static state to remain unchanged.
644 TransportSecurityState::DomainState new_static_domain_state2
;
645 EXPECT_TRUE(state
.GetStaticDomainState(
646 domain
, &new_static_domain_state2
));
647 EXPECT_EQ(saved_hashes
.size(),
648 new_static_domain_state2
.pkp
.spki_hashes
.size());
649 for (size_t i
= 0; i
< saved_hashes
.size(); ++i
) {
650 EXPECT_TRUE(HashValuesEqual(saved_hashes
[i
])(
651 new_static_domain_state2
.pkp
.spki_hashes
[i
]));
654 // Expect the dynamic pins to be gone.
655 TransportSecurityState::DomainState new_dynamic_domain_state2
;
656 EXPECT_FALSE(state
.GetDynamicDomainState(domain
, &new_dynamic_domain_state2
));
658 // Expect the exact-matching static policy to continue to apply, even
659 // though dynamic policy has been removed. (This policy may change in the
660 // future, in which case this test must be updated.)
661 EXPECT_TRUE(state
.HasPublicKeyPins(domain
));
662 EXPECT_TRUE(state
.ShouldSSLErrorsBeFatal(domain
));
663 std::string failure_log
;
664 // Damage the hashes to cause a pin validation failure.
665 new_static_domain_state2
.pkp
.spki_hashes
[0].data()[0] ^= 0x80;
666 new_static_domain_state2
.pkp
.spki_hashes
[1].data()[0] ^= 0x80;
667 new_static_domain_state2
.pkp
.spki_hashes
[2].data()[0] ^= 0x80;
668 const bool is_issued_by_known_root
= true;
670 state
.CheckPublicKeyPins(domain
,
671 is_issued_by_known_root
,
672 new_static_domain_state2
.pkp
.spki_hashes
,
674 EXPECT_NE(0UL, failure_log
.length());
677 // Tests that when a static HSTS and a static HPKP entry are present, adding a
678 // dynamic HSTS header does not clobber the static HPKP entry. Further, adding a
679 // dynamic HPKP entry could not affect the HSTS entry for the site.
680 TEST_F(HttpSecurityHeadersTest
, NoClobberPins
) {
681 TransportSecurityState state
;
682 TransportSecurityState::DomainState domain_state
;
684 // accounts.google.com has preloaded pins.
685 std::string domain
= "accounts.google.com";
686 state
.enable_static_pins_
= true;
688 // Retrieve the DomainState as it is by default, including its known good
690 EXPECT_TRUE(state
.GetStaticDomainState(domain
, &domain_state
));
691 HashValueVector saved_hashes
= domain_state
.pkp
.spki_hashes
;
692 EXPECT_TRUE(domain_state
.ShouldUpgradeToSSL());
693 EXPECT_TRUE(domain_state
.HasPublicKeyPins());
694 EXPECT_TRUE(state
.ShouldUpgradeToSSL(domain
));
695 EXPECT_TRUE(state
.HasPublicKeyPins(domain
));
697 // Add a dynamic HSTS header. CheckPublicKeyPins should still pass when given
698 // the original |saved_hashes|, indicating that the static PKP data is still
699 // configured for the domain.
700 EXPECT_TRUE(state
.AddHSTSHeader(domain
, "includesubdomains; max-age=10000"));
701 EXPECT_TRUE(state
.ShouldUpgradeToSSL(domain
));
702 std::string failure_log
;
703 const bool is_issued_by_known_root
= true;
704 EXPECT_TRUE(state
.CheckPublicKeyPins(domain
,
705 is_issued_by_known_root
,
709 // Add an HPKP header, which should only update the dynamic state.
710 HashValue good_hash
= GetTestHashValue(1, HASH_VALUE_SHA1
);
711 std::string good_pin
= GetTestPin(1, HASH_VALUE_SHA1
);
712 std::string backup_pin
= GetTestPin(2, HASH_VALUE_SHA1
);
713 std::string header
= "max-age = 10000; " + good_pin
+ "; " + backup_pin
;
715 // Construct a fake SSLInfo that will pass AddHPKPHeader's checks.
717 ssl_info
.public_key_hashes
.push_back(good_hash
);
718 ssl_info
.public_key_hashes
.push_back(saved_hashes
[0]);
719 EXPECT_TRUE(state
.AddHPKPHeader(domain
, header
, ssl_info
));
721 EXPECT_TRUE(state
.AddHPKPHeader(domain
, header
, ssl_info
));
722 // HSTS should still be configured for this domain.
723 EXPECT_TRUE(domain_state
.ShouldUpgradeToSSL());
724 EXPECT_TRUE(state
.ShouldUpgradeToSSL(domain
));
725 // The dynamic pins, which do not match |saved_hashes|, should take
726 // precedence over the static pins and cause the check to fail.
727 EXPECT_FALSE(state
.CheckPublicKeyPins(domain
,
728 is_issued_by_known_root
,
733 // Tests that seeing an invalid HPKP header leaves the existing one alone.
734 TEST_F(HttpSecurityHeadersTest
, IgnoreInvalidHeaders
) {
735 TransportSecurityState state
;
737 HashValue good_hash
= GetTestHashValue(1, HASH_VALUE_SHA256
);
738 std::string good_pin
= GetTestPin(1, HASH_VALUE_SHA256
);
739 std::string bad_pin
= GetTestPin(2, HASH_VALUE_SHA256
);
740 std::string backup_pin
= GetTestPin(3, HASH_VALUE_SHA256
);
743 ssl_info
.public_key_hashes
.push_back(good_hash
);
745 // Add a valid HPKP header.
746 EXPECT_TRUE(state
.AddHPKPHeader(
747 "example.com", "max-age = 10000; " + good_pin
+ "; " + backup_pin
,
750 // Check the insertion was valid.
751 EXPECT_TRUE(state
.HasPublicKeyPins("example.com"));
752 std::string failure_log
;
753 bool is_issued_by_known_root
= true;
754 EXPECT_TRUE(state
.CheckPublicKeyPins("example.com", is_issued_by_known_root
,
755 ssl_info
.public_key_hashes
,
758 // Now assert an invalid one. This should fail.
759 EXPECT_FALSE(state
.AddHPKPHeader(
760 "example.com", "max-age = 10000; " + bad_pin
+ "; " + backup_pin
,
763 // The old pins must still exist.
764 EXPECT_TRUE(state
.HasPublicKeyPins("example.com"));
765 EXPECT_TRUE(state
.CheckPublicKeyPins("example.com", is_issued_by_known_root
,
766 ssl_info
.public_key_hashes
,