• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 <algorithm>
6 
7 #include "base/base64.h"
8 #include "base/sha1.h"
9 #include "base/strings/string_piece.h"
10 #include "crypto/sha2.h"
11 #include "net/base/net_log.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/ssl/ssl_info.h"
17 #include "testing/gtest/include/gtest/gtest.h"
18 
19 namespace net {
20 
21 namespace {
22 
GetTestHashValue(uint8 label,HashValueTag tag)23 HashValue GetTestHashValue(uint8 label, HashValueTag tag) {
24   HashValue hash_value(tag);
25   memset(hash_value.data(), label, hash_value.size());
26   return hash_value;
27 }
28 
GetTestPin(uint8 label,HashValueTag tag)29 std::string GetTestPin(uint8 label, HashValueTag tag) {
30   HashValue hash_value = GetTestHashValue(label, tag);
31   std::string base64;
32   base::Base64Encode(base::StringPiece(
33       reinterpret_cast<char*>(hash_value.data()), hash_value.size()), &base64);
34 
35   switch (hash_value.tag) {
36     case HASH_VALUE_SHA1:
37       return std::string("pin-sha1=\"") + base64 + "\"";
38     case HASH_VALUE_SHA256:
39       return std::string("pin-sha256=\"") + base64 + "\"";
40     default:
41       NOTREACHED() << "Unknown HashValueTag " << hash_value.tag;
42       return std::string("ERROR");
43   }
44 }
45 
46 };
47 
48 
49 class HttpSecurityHeadersTest : public testing::Test {
50 };
51 
52 
TEST_F(HttpSecurityHeadersTest,BogusHeaders)53 TEST_F(HttpSecurityHeadersTest, BogusHeaders) {
54   base::TimeDelta max_age;
55   bool include_subdomains = false;
56 
57   EXPECT_FALSE(
58       ParseHSTSHeader(std::string(), &max_age, &include_subdomains));
59   EXPECT_FALSE(ParseHSTSHeader("    ", &max_age, &include_subdomains));
60   EXPECT_FALSE(ParseHSTSHeader("abc", &max_age, &include_subdomains));
61   EXPECT_FALSE(ParseHSTSHeader("  abc", &max_age, &include_subdomains));
62   EXPECT_FALSE(ParseHSTSHeader("  abc   ", &max_age, &include_subdomains));
63   EXPECT_FALSE(ParseHSTSHeader("max-age", &max_age, &include_subdomains));
64   EXPECT_FALSE(ParseHSTSHeader("  max-age", &max_age,
65                                &include_subdomains));
66   EXPECT_FALSE(ParseHSTSHeader("  max-age  ", &max_age,
67                                &include_subdomains));
68   EXPECT_FALSE(ParseHSTSHeader("max-age=", &max_age, &include_subdomains));
69   EXPECT_FALSE(ParseHSTSHeader("   max-age=", &max_age,
70                                &include_subdomains));
71   EXPECT_FALSE(ParseHSTSHeader("   max-age  =", &max_age,
72                                &include_subdomains));
73   EXPECT_FALSE(ParseHSTSHeader("   max-age=   ", &max_age,
74                                &include_subdomains));
75   EXPECT_FALSE(ParseHSTSHeader("   max-age  =     ", &max_age,
76                                &include_subdomains));
77   EXPECT_FALSE(ParseHSTSHeader("   max-age  =     xy", &max_age,
78                                &include_subdomains));
79   EXPECT_FALSE(ParseHSTSHeader("   max-age  =     3488a923", &max_age,
80                                &include_subdomains));
81   EXPECT_FALSE(ParseHSTSHeader("max-age=3488a923  ", &max_age,
82                                &include_subdomains));
83   EXPECT_FALSE(ParseHSTSHeader("max-ag=3488923", &max_age,
84                                &include_subdomains));
85   EXPECT_FALSE(ParseHSTSHeader("max-aged=3488923", &max_age,
86                                &include_subdomains));
87   EXPECT_FALSE(ParseHSTSHeader("max-age==3488923", &max_age,
88                                &include_subdomains));
89   EXPECT_FALSE(ParseHSTSHeader("amax-age=3488923", &max_age,
90                                &include_subdomains));
91   EXPECT_FALSE(ParseHSTSHeader("max-age=-3488923", &max_age,
92                                &include_subdomains));
93   EXPECT_FALSE(ParseHSTSHeader("max-age=3488923;", &max_age,
94                                &include_subdomains));
95   EXPECT_FALSE(ParseHSTSHeader("max-age=3488923     e", &max_age,
96                                &include_subdomains));
97   EXPECT_FALSE(ParseHSTSHeader("max-age=3488923     includesubdomain",
98                                &max_age, &include_subdomains));
99   EXPECT_FALSE(ParseHSTSHeader("max-age=3488923includesubdomains",
100                                &max_age, &include_subdomains));
101   EXPECT_FALSE(ParseHSTSHeader("max-age=3488923=includesubdomains",
102                                &max_age, &include_subdomains));
103   EXPECT_FALSE(ParseHSTSHeader("max-age=3488923 includesubdomainx",
104                                &max_age, &include_subdomains));
105   EXPECT_FALSE(ParseHSTSHeader("max-age=3488923 includesubdomain=",
106                                &max_age, &include_subdomains));
107   EXPECT_FALSE(ParseHSTSHeader("max-age=3488923 includesubdomain=true",
108                                &max_age, &include_subdomains));
109   EXPECT_FALSE(ParseHSTSHeader("max-age=3488923 includesubdomainsx",
110                                &max_age, &include_subdomains));
111   EXPECT_FALSE(ParseHSTSHeader("max-age=3488923 includesubdomains x",
112                                &max_age, &include_subdomains));
113   EXPECT_FALSE(ParseHSTSHeader("max-age=34889.23 includesubdomains",
114                                &max_age, &include_subdomains));
115   EXPECT_FALSE(ParseHSTSHeader("max-age=34889 includesubdomains",
116                                &max_age, &include_subdomains));
117 
118   // Check the out args were not updated by checking the default
119   // values for its predictable fields.
120   EXPECT_EQ(0, max_age.InSeconds());
121   EXPECT_FALSE(include_subdomains);
122 }
123 
TestBogusPinsHeaders(HashValueTag tag)124 static void TestBogusPinsHeaders(HashValueTag tag) {
125   base::TimeDelta max_age;
126   bool include_subdomains;
127   HashValueVector hashes;
128   HashValueVector chain_hashes;
129 
130   // Set some fake "chain" hashes
131   chain_hashes.push_back(GetTestHashValue(1, tag));
132   chain_hashes.push_back(GetTestHashValue(2, tag));
133   chain_hashes.push_back(GetTestHashValue(3, tag));
134 
135   // The good pin must be in the chain, the backup pin must not be
136   std::string good_pin = GetTestPin(2, tag);
137   std::string backup_pin = GetTestPin(4, tag);
138 
139   EXPECT_FALSE(ParseHPKPHeader(std::string(), chain_hashes, &max_age,
140                                &include_subdomains, &hashes));
141   EXPECT_FALSE(ParseHPKPHeader("    ", chain_hashes, &max_age,
142                                &include_subdomains, &hashes));
143   EXPECT_FALSE(ParseHPKPHeader("abc", chain_hashes, &max_age,
144                                &include_subdomains, &hashes));
145   EXPECT_FALSE(ParseHPKPHeader("  abc", chain_hashes, &max_age,
146                                &include_subdomains, &hashes));
147   EXPECT_FALSE(ParseHPKPHeader("  abc   ", chain_hashes, &max_age,
148                                &include_subdomains, &hashes));
149   EXPECT_FALSE(ParseHPKPHeader("max-age", chain_hashes, &max_age,
150                                &include_subdomains, &hashes));
151   EXPECT_FALSE(ParseHPKPHeader("  max-age", chain_hashes, &max_age,
152                                &include_subdomains, &hashes));
153   EXPECT_FALSE(ParseHPKPHeader("  max-age  ", chain_hashes, &max_age,
154                                &include_subdomains, &hashes));
155   EXPECT_FALSE(ParseHPKPHeader("max-age=", chain_hashes, &max_age,
156                                &include_subdomains, &hashes));
157   EXPECT_FALSE(ParseHPKPHeader("   max-age=", chain_hashes, &max_age,
158                                &include_subdomains, &hashes));
159   EXPECT_FALSE(ParseHPKPHeader("   max-age  =", chain_hashes, &max_age,
160                                &include_subdomains, &hashes));
161   EXPECT_FALSE(ParseHPKPHeader("   max-age=   ", chain_hashes, &max_age,
162                                &include_subdomains, &hashes));
163   EXPECT_FALSE(ParseHPKPHeader("   max-age  =     ", chain_hashes,
164                                &max_age, &include_subdomains, &hashes));
165   EXPECT_FALSE(ParseHPKPHeader("   max-age  =     xy", chain_hashes,
166                                &max_age, &include_subdomains, &hashes));
167   EXPECT_FALSE(ParseHPKPHeader("   max-age  =     3488a923",
168                                chain_hashes, &max_age, &include_subdomains,
169                                &hashes));
170   EXPECT_FALSE(ParseHPKPHeader("max-age=3488a923  ", chain_hashes,
171                                &max_age, &include_subdomains, &hashes));
172   EXPECT_FALSE(ParseHPKPHeader("max-ag=3488923pins=" + good_pin + "," +
173                                backup_pin,
174                                chain_hashes, &max_age, &include_subdomains,
175                                &hashes));
176   EXPECT_FALSE(ParseHPKPHeader("max-aged=3488923" + backup_pin,
177                                chain_hashes, &max_age, &include_subdomains,
178                                &hashes));
179   EXPECT_FALSE(ParseHPKPHeader("max-aged=3488923; " + backup_pin,
180                                chain_hashes, &max_age, &include_subdomains,
181                                &hashes));
182   EXPECT_FALSE(ParseHPKPHeader("max-aged=3488923; " + backup_pin + ";" +
183                                backup_pin,
184                                chain_hashes, &max_age, &include_subdomains,
185                                &hashes));
186   EXPECT_FALSE(ParseHPKPHeader("max-aged=3488923; " + good_pin + ";" +
187                                good_pin,
188                                chain_hashes, &max_age, &include_subdomains,
189                                &hashes));
190   EXPECT_FALSE(ParseHPKPHeader("max-aged=3488923; " + good_pin,
191                                chain_hashes, &max_age, &include_subdomains,
192                                &hashes));
193   EXPECT_FALSE(ParseHPKPHeader("max-age==3488923", chain_hashes, &max_age,
194                                &include_subdomains, &hashes));
195   EXPECT_FALSE(ParseHPKPHeader("amax-age=3488923", chain_hashes, &max_age,
196                                &include_subdomains, &hashes));
197   EXPECT_FALSE(ParseHPKPHeader("max-age=-3488923", chain_hashes, &max_age,
198                                &include_subdomains, &hashes));
199   EXPECT_FALSE(ParseHPKPHeader("max-age=3488923;", chain_hashes, &max_age,
200                                &include_subdomains, &hashes));
201   EXPECT_FALSE(ParseHPKPHeader("max-age=3488923     e", chain_hashes,
202                                &max_age, &include_subdomains, &hashes));
203   EXPECT_FALSE(ParseHPKPHeader("max-age=3488923     includesubdomain",
204                                chain_hashes, &max_age, &include_subdomains,
205                                &hashes));
206   EXPECT_FALSE(ParseHPKPHeader("max-age=34889.23", chain_hashes, &max_age,
207                                &include_subdomains, &hashes));
208 
209   // Check the out args were not updated by checking the default
210   // values for its predictable fields.
211   EXPECT_EQ(0, max_age.InSeconds());
212   EXPECT_EQ(hashes.size(), (size_t)0);
213 }
214 
TEST_F(HttpSecurityHeadersTest,ValidSTSHeaders)215 TEST_F(HttpSecurityHeadersTest, ValidSTSHeaders) {
216   base::TimeDelta max_age;
217   base::TimeDelta expect_max_age;
218   bool include_subdomains = false;
219 
220   EXPECT_TRUE(ParseHSTSHeader("max-age=243", &max_age,
221                               &include_subdomains));
222   expect_max_age = base::TimeDelta::FromSeconds(243);
223   EXPECT_EQ(expect_max_age, max_age);
224   EXPECT_FALSE(include_subdomains);
225 
226   EXPECT_TRUE(ParseHSTSHeader("  Max-agE    = 567", &max_age,
227                               &include_subdomains));
228   expect_max_age = base::TimeDelta::FromSeconds(567);
229   EXPECT_EQ(expect_max_age, max_age);
230   EXPECT_FALSE(include_subdomains);
231 
232   EXPECT_TRUE(ParseHSTSHeader("  mAx-aGe    = 890      ", &max_age,
233                               &include_subdomains));
234   expect_max_age = base::TimeDelta::FromSeconds(890);
235   EXPECT_EQ(expect_max_age, max_age);
236   EXPECT_FALSE(include_subdomains);
237 
238   EXPECT_TRUE(ParseHSTSHeader("max-age=123;incLudesUbdOmains", &max_age,
239                               &include_subdomains));
240   expect_max_age = base::TimeDelta::FromSeconds(123);
241   EXPECT_EQ(expect_max_age, max_age);
242   EXPECT_TRUE(include_subdomains);
243 
244   EXPECT_TRUE(ParseHSTSHeader("incLudesUbdOmains; max-age=123", &max_age,
245                               &include_subdomains));
246   expect_max_age = base::TimeDelta::FromSeconds(123);
247   EXPECT_EQ(expect_max_age, max_age);
248   EXPECT_TRUE(include_subdomains);
249 
250   EXPECT_TRUE(ParseHSTSHeader("   incLudesUbdOmains; max-age=123",
251                               &max_age, &include_subdomains));
252   expect_max_age = base::TimeDelta::FromSeconds(123);
253   EXPECT_EQ(expect_max_age, max_age);
254   EXPECT_TRUE(include_subdomains);
255 
256   EXPECT_TRUE(ParseHSTSHeader(
257       "   incLudesUbdOmains; max-age=123; pumpkin=kitten", &max_age,
258                                    &include_subdomains));
259   expect_max_age = base::TimeDelta::FromSeconds(123);
260   EXPECT_EQ(expect_max_age, max_age);
261   EXPECT_TRUE(include_subdomains);
262 
263   EXPECT_TRUE(ParseHSTSHeader(
264       "   pumpkin=894; incLudesUbdOmains; max-age=123  ", &max_age,
265                                    &include_subdomains));
266   expect_max_age = base::TimeDelta::FromSeconds(123);
267   EXPECT_EQ(expect_max_age, max_age);
268   EXPECT_TRUE(include_subdomains);
269 
270   EXPECT_TRUE(ParseHSTSHeader(
271       "   pumpkin; incLudesUbdOmains; max-age=123  ", &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);
276 
277   EXPECT_TRUE(ParseHSTSHeader(
278       "   pumpkin; incLudesUbdOmains; max-age=\"123\"  ", &max_age,
279                                    &include_subdomains));
280   expect_max_age = base::TimeDelta::FromSeconds(123);
281   EXPECT_EQ(expect_max_age, max_age);
282   EXPECT_TRUE(include_subdomains);
283 
284   EXPECT_TRUE(ParseHSTSHeader(
285       "animal=\"squirrel; distinguished\"; incLudesUbdOmains; max-age=123",
286                                    &max_age, &include_subdomains));
287   expect_max_age = base::TimeDelta::FromSeconds(123);
288   EXPECT_EQ(expect_max_age, max_age);
289   EXPECT_TRUE(include_subdomains);
290 
291   EXPECT_TRUE(ParseHSTSHeader("max-age=394082;  incLudesUbdOmains",
292                               &max_age, &include_subdomains));
293   expect_max_age = base::TimeDelta::FromSeconds(394082);
294   EXPECT_EQ(expect_max_age, max_age);
295   EXPECT_TRUE(include_subdomains);
296 
297   EXPECT_TRUE(ParseHSTSHeader(
298       "max-age=39408299  ;incLudesUbdOmains", &max_age,
299       &include_subdomains));
300   expect_max_age = base::TimeDelta::FromSeconds(
301       std::min(kMaxHSTSAgeSecs, static_cast<int64>(GG_INT64_C(39408299))));
302   EXPECT_EQ(expect_max_age, max_age);
303   EXPECT_TRUE(include_subdomains);
304 
305   EXPECT_TRUE(ParseHSTSHeader(
306       "max-age=394082038  ; incLudesUbdOmains", &max_age,
307       &include_subdomains));
308   expect_max_age = base::TimeDelta::FromSeconds(
309       std::min(kMaxHSTSAgeSecs, static_cast<int64>(GG_INT64_C(394082038))));
310   EXPECT_EQ(expect_max_age, max_age);
311   EXPECT_TRUE(include_subdomains);
312 
313   EXPECT_TRUE(ParseHSTSHeader(
314       "  max-age=0  ;  incLudesUbdOmains   ", &max_age,
315       &include_subdomains));
316   expect_max_age = base::TimeDelta::FromSeconds(0);
317   EXPECT_EQ(expect_max_age, max_age);
318   EXPECT_TRUE(include_subdomains);
319 
320   EXPECT_TRUE(ParseHSTSHeader(
321       "  max-age=999999999999999999999999999999999999999999999  ;"
322       "  incLudesUbdOmains   ", &max_age, &include_subdomains));
323   expect_max_age = base::TimeDelta::FromSeconds(
324       kMaxHSTSAgeSecs);
325   EXPECT_EQ(expect_max_age, max_age);
326   EXPECT_TRUE(include_subdomains);
327 }
328 
TestValidPKPHeaders(HashValueTag tag)329 static void TestValidPKPHeaders(HashValueTag tag) {
330   base::TimeDelta max_age;
331   base::TimeDelta expect_max_age;
332   bool include_subdomains;
333   HashValueVector hashes;
334   HashValueVector chain_hashes;
335 
336   // Set some fake "chain" hashes into chain_hashes
337   chain_hashes.push_back(GetTestHashValue(1, tag));
338   chain_hashes.push_back(GetTestHashValue(2, tag));
339   chain_hashes.push_back(GetTestHashValue(3, tag));
340 
341   // The good pin must be in the chain, the backup pin must not be
342   std::string good_pin = GetTestPin(2, tag);
343   std::string backup_pin = GetTestPin(4, tag);
344 
345   EXPECT_TRUE(ParseHPKPHeader(
346       "max-age=243; " + good_pin + ";" + backup_pin,
347       chain_hashes, &max_age, &include_subdomains, &hashes));
348   expect_max_age = base::TimeDelta::FromSeconds(243);
349   EXPECT_EQ(expect_max_age, max_age);
350   EXPECT_FALSE(include_subdomains);
351 
352   EXPECT_TRUE(ParseHPKPHeader(
353       "   " + good_pin + "; " + backup_pin + "  ; Max-agE    = 567",
354       chain_hashes, &max_age, &include_subdomains, &hashes));
355   expect_max_age = base::TimeDelta::FromSeconds(567);
356   EXPECT_EQ(expect_max_age, max_age);
357   EXPECT_FALSE(include_subdomains);
358 
359   EXPECT_TRUE(ParseHPKPHeader(
360       "includeSubDOMAINS;" + good_pin + ";" + backup_pin +
361       "  ; mAx-aGe    = 890      ",
362       chain_hashes, &max_age, &include_subdomains, &hashes));
363   expect_max_age = base::TimeDelta::FromSeconds(890);
364   EXPECT_EQ(expect_max_age, max_age);
365   EXPECT_TRUE(include_subdomains);
366 
367   EXPECT_TRUE(ParseHPKPHeader(
368       good_pin + ";" + backup_pin + "; max-age=123;IGNORED;",
369       chain_hashes, &max_age, &include_subdomains, &hashes));
370   expect_max_age = base::TimeDelta::FromSeconds(123);
371   EXPECT_EQ(expect_max_age, max_age);
372   EXPECT_FALSE(include_subdomains);
373 
374   EXPECT_TRUE(ParseHPKPHeader(
375       "max-age=394082;" + backup_pin + ";" + good_pin + ";  ",
376       chain_hashes, &max_age, &include_subdomains, &hashes));
377   expect_max_age = base::TimeDelta::FromSeconds(394082);
378   EXPECT_EQ(expect_max_age, max_age);
379   EXPECT_FALSE(include_subdomains);
380 
381   EXPECT_TRUE(ParseHPKPHeader(
382       "max-age=39408299  ;" + backup_pin + ";" + good_pin + ";  ",
383       chain_hashes, &max_age, &include_subdomains, &hashes));
384   expect_max_age = base::TimeDelta::FromSeconds(
385       std::min(kMaxHSTSAgeSecs, static_cast<int64>(GG_INT64_C(39408299))));
386   EXPECT_EQ(expect_max_age, max_age);
387   EXPECT_FALSE(include_subdomains);
388 
389   EXPECT_TRUE(ParseHPKPHeader(
390       "max-age=39408038  ;    cybers=39408038  ;  includeSubdomains; " +
391           good_pin + ";" + backup_pin + ";   ",
392       chain_hashes, &max_age, &include_subdomains, &hashes));
393   expect_max_age = base::TimeDelta::FromSeconds(
394       std::min(kMaxHSTSAgeSecs, static_cast<int64>(GG_INT64_C(394082038))));
395   EXPECT_EQ(expect_max_age, max_age);
396   EXPECT_TRUE(include_subdomains);
397 
398   EXPECT_TRUE(ParseHPKPHeader(
399       "  max-age=0  ;  " + good_pin + ";" + backup_pin,
400       chain_hashes, &max_age, &include_subdomains, &hashes));
401   expect_max_age = base::TimeDelta::FromSeconds(0);
402   EXPECT_EQ(expect_max_age, max_age);
403   EXPECT_FALSE(include_subdomains);
404 
405   EXPECT_TRUE(ParseHPKPHeader(
406       "  max-age=0 ; includeSubdomains;  " + good_pin + ";" + backup_pin,
407       chain_hashes, &max_age, &include_subdomains, &hashes));
408   expect_max_age = base::TimeDelta::FromSeconds(0);
409   EXPECT_EQ(expect_max_age, max_age);
410   EXPECT_TRUE(include_subdomains);
411 
412   EXPECT_TRUE(ParseHPKPHeader(
413       "  max-age=999999999999999999999999999999999999999999999  ;  " +
414           backup_pin + ";" + good_pin + ";   ",
415       chain_hashes, &max_age, &include_subdomains, &hashes));
416   expect_max_age = base::TimeDelta::FromSeconds(kMaxHSTSAgeSecs);
417   EXPECT_EQ(expect_max_age, max_age);
418   EXPECT_FALSE(include_subdomains);
419 
420   // Test that parsing the same header twice doesn't duplicate the recorded
421   // hashes.
422   hashes.clear();
423   EXPECT_TRUE(ParseHPKPHeader(
424       "  max-age=999;  " +
425           backup_pin + ";" + good_pin + ";   ",
426       chain_hashes, &max_age, &include_subdomains, &hashes));
427   EXPECT_EQ(2u, hashes.size());
428   EXPECT_TRUE(ParseHPKPHeader(
429       "  max-age=999;  " +
430           backup_pin + ";" + good_pin + ";   ",
431       chain_hashes, &max_age, &include_subdomains, &hashes));
432   EXPECT_EQ(2u, hashes.size());
433 }
434 
TEST_F(HttpSecurityHeadersTest,BogusPinsHeadersSHA1)435 TEST_F(HttpSecurityHeadersTest, BogusPinsHeadersSHA1) {
436   TestBogusPinsHeaders(HASH_VALUE_SHA1);
437 }
438 
TEST_F(HttpSecurityHeadersTest,BogusPinsHeadersSHA256)439 TEST_F(HttpSecurityHeadersTest, BogusPinsHeadersSHA256) {
440   TestBogusPinsHeaders(HASH_VALUE_SHA256);
441 }
442 
TEST_F(HttpSecurityHeadersTest,ValidPKPHeadersSHA1)443 TEST_F(HttpSecurityHeadersTest, ValidPKPHeadersSHA1) {
444   TestValidPKPHeaders(HASH_VALUE_SHA1);
445 }
446 
TEST_F(HttpSecurityHeadersTest,ValidPKPHeadersSHA256)447 TEST_F(HttpSecurityHeadersTest, ValidPKPHeadersSHA256) {
448   TestValidPKPHeaders(HASH_VALUE_SHA256);
449 }
450 
TEST_F(HttpSecurityHeadersTest,UpdateDynamicPKPOnly)451 TEST_F(HttpSecurityHeadersTest, UpdateDynamicPKPOnly) {
452   TransportSecurityState state;
453   TransportSecurityState::DomainState domain_state;
454 
455   // docs.google.com has preloaded pins.
456   std::string domain = "docs.google.com";
457   EXPECT_TRUE(state.GetDomainState(domain, true, &domain_state));
458   EXPECT_GT(domain_state.static_spki_hashes.size(), 1UL);
459   HashValueVector saved_hashes = domain_state.static_spki_hashes;
460 
461   // Add a header, which should only update the dynamic state.
462   HashValue good_hash = GetTestHashValue(1, HASH_VALUE_SHA1);
463   HashValue backup_hash = GetTestHashValue(2, HASH_VALUE_SHA1);
464   std::string good_pin = GetTestPin(1, HASH_VALUE_SHA1);
465   std::string backup_pin = GetTestPin(2, HASH_VALUE_SHA1);
466   std::string header = "max-age = 10000; " + good_pin + "; " + backup_pin;
467 
468   // Construct a fake SSLInfo that will pass AddHPKPHeader's checks.
469   SSLInfo ssl_info;
470   ssl_info.public_key_hashes.push_back(good_hash);
471   ssl_info.public_key_hashes.push_back(saved_hashes[0]);
472   EXPECT_TRUE(state.AddHPKPHeader(domain, header, ssl_info));
473 
474   // Expect the preloaded state to remain unchanged.
475   std::string canonicalized_host = TransportSecurityState::CanonicalizeHost(
476       domain);
477   TransportSecurityState::DomainState static_domain_state;
478   EXPECT_TRUE(state.GetStaticDomainState(canonicalized_host,
479                                          true,
480                                          &static_domain_state));
481   for (size_t i = 0; i < saved_hashes.size(); ++i) {
482     EXPECT_TRUE(HashValuesEqual(
483         saved_hashes[i])(static_domain_state.static_spki_hashes[i]));
484   }
485 
486   // Expect the dynamic state to reflect the header.
487   TransportSecurityState::DomainState dynamic_domain_state;
488   EXPECT_TRUE(state.GetDynamicDomainState(domain, &dynamic_domain_state));
489   EXPECT_EQ(2UL, dynamic_domain_state.dynamic_spki_hashes.size());
490 
491   HashValueVector::const_iterator hash = std::find_if(
492       dynamic_domain_state.dynamic_spki_hashes.begin(),
493       dynamic_domain_state.dynamic_spki_hashes.end(),
494       HashValuesEqual(good_hash));
495   EXPECT_NE(dynamic_domain_state.dynamic_spki_hashes.end(), hash);
496 
497   hash = std::find_if(
498       dynamic_domain_state.dynamic_spki_hashes.begin(),
499       dynamic_domain_state.dynamic_spki_hashes.end(),
500       HashValuesEqual(backup_hash));
501   EXPECT_NE(dynamic_domain_state.dynamic_spki_hashes.end(), hash);
502 
503   // Expect the overall state to reflect the header, too.
504   EXPECT_TRUE(state.GetDomainState(domain, true, &domain_state));
505   EXPECT_EQ(2UL, domain_state.dynamic_spki_hashes.size());
506 
507   hash = std::find_if(domain_state.dynamic_spki_hashes.begin(),
508                       domain_state.dynamic_spki_hashes.end(),
509                       HashValuesEqual(good_hash));
510   EXPECT_NE(domain_state.dynamic_spki_hashes.end(), hash);
511 
512   hash = std::find_if(
513       domain_state.dynamic_spki_hashes.begin(),
514       domain_state.dynamic_spki_hashes.end(),
515       HashValuesEqual(backup_hash));
516   EXPECT_NE(domain_state.dynamic_spki_hashes.end(), hash);
517 }
518 
519 };    // namespace net
520