1 // Copyright 2014 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.
6 #include "core/frame/SubresourceIntegrity.h"
8 #include "core/HTMLNames.h"
9 #include "core/dom/Document.h"
10 #include "core/html/HTMLScriptElement.h"
11 #include "platform/Crypto.h"
12 #include "platform/weborigin/KURL.h"
13 #include "platform/weborigin/SecurityOrigin.h"
14 #include "wtf/RefPtr.h"
15 #include "wtf/text/WTFString.h"
16 #include <gtest/gtest.h>
20 static const char kBasicScript[] = "alert('test');";
21 static const char kSha256Integrity[] = "ni:///sha256;GAF48QOoxRvu0gZAmQivUdJPyBacqznBAXwnkfpmQX4=";
22 static const char kSha384Integrity[] = "ni:///sha384;nep3XpvhUxpCMOVXIFPecThAqdY/uVeiD4kXSqXpx0YJUWU4fTTaFgciTuZk7fmE";
23 static const char kSha512Integrity[] = "ni:///sha512;TXkJw18PqlVlEUXXjeXbGetop1TKB3wYQIp1/ihxCOFGUfG9TYOaA1MlkpTAqSV6yaevLO8Tj5pgH1JmZ++ItA==";
24 static const char kSha384IntegrityLabeledAs256[] = "ni:///sha256;nep3XpvhUxpCMOVXIFPecThAqdY/uVeiD4kXSqXpx0YJUWU4fTTaFgciTuZk7fmE";
25 static const char kUnsupportedHashFunctionIntegrity[] = "ni:///sha1;JfLW308qMPKfb4DaHpUBEESwuPc=";
27 class SubresourceIntegrityTest : public ::testing::Test {
29 SubresourceIntegrityTest()
30 : secureURL(ParsedURLString, "https://example.test:443")
31 , insecureURL(ParsedURLString, "http://example.test:80")
32 , secureOrigin(SecurityOrigin::create(secureURL))
33 , insecureOrigin(SecurityOrigin::create(insecureURL))
40 document = Document::create();
41 scriptElement = HTMLScriptElement::create(*document, true);
44 void expectAlgorithm(const String& text, HashAlgorithm expectedAlgorithm)
46 Vector<UChar> characters;
47 text.appendTo(characters);
48 const UChar* position = characters.data();
49 const UChar* end = characters.end();
50 HashAlgorithm algorithm;
52 EXPECT_TRUE(SubresourceIntegrity::parseAlgorithm(position, end, algorithm));
53 EXPECT_EQ(expectedAlgorithm, algorithm);
54 EXPECT_EQ(';', *position);
57 void expectAlgorithmFailure(const String& text)
59 Vector<UChar> characters;
60 text.appendTo(characters);
61 const UChar* position = characters.data();
62 const UChar* begin = characters.data();
63 const UChar* end = characters.end();
64 HashAlgorithm algorithm;
66 EXPECT_FALSE(SubresourceIntegrity::parseAlgorithm(position, end, algorithm));
67 EXPECT_EQ(begin, position);
70 void expectDigest(const String& text, const char* expectedDigest)
72 Vector<UChar> characters;
73 text.appendTo(characters);
74 const UChar* position = characters.data();
75 const UChar* end = characters.end();
78 EXPECT_TRUE(SubresourceIntegrity::parseDigest(position, end, digest));
79 EXPECT_EQ(expectedDigest, digest);
82 void expectDigestFailure(const String& text)
84 Vector<UChar> characters;
85 text.appendTo(characters);
86 const UChar* position = characters.data();
87 const UChar* end = characters.end();
90 EXPECT_FALSE(SubresourceIntegrity::parseDigest(position, end, digest));
91 EXPECT_TRUE(digest.isEmpty());
94 void expectParse(const char* integrityAttribute, const char* expectedDigest, HashAlgorithm expectedAlgorithm)
97 HashAlgorithm algorithm;
99 EXPECT_TRUE(SubresourceIntegrity::parseIntegrityAttribute(integrityAttribute, digest, algorithm, *document));
100 EXPECT_EQ(expectedDigest, digest);
101 EXPECT_EQ(expectedAlgorithm, algorithm);
104 void expectParseFailure(const char* integrityAttribute)
107 HashAlgorithm algorithm;
109 EXPECT_FALSE(SubresourceIntegrity::parseIntegrityAttribute(integrityAttribute, digest, algorithm, *document));
112 void expectIntegrity(const char* integrity, const char* script, const KURL& url)
114 scriptElement->setAttribute(HTMLNames::integrityAttr, integrity);
115 EXPECT_TRUE(SubresourceIntegrity::CheckSubresourceIntegrity(*scriptElement, script, url));
118 void expectIntegrityFailure(const char* integrity, const char* script, const KURL& url)
120 scriptElement->setAttribute(HTMLNames::integrityAttr, integrity);
121 EXPECT_FALSE(SubresourceIntegrity::CheckSubresourceIntegrity(*scriptElement, script, url));
126 RefPtr<SecurityOrigin> secureOrigin;
127 RefPtr<SecurityOrigin> insecureOrigin;
129 RefPtrWillBePersistent<Document> document;
130 RefPtrWillBePersistent<HTMLScriptElement> scriptElement;
133 TEST_F(SubresourceIntegrityTest, ParseAlgorithm)
135 expectAlgorithm("sha256;", HashAlgorithmSha256);
136 expectAlgorithm("sha384;", HashAlgorithmSha384);
137 expectAlgorithm("sha512;", HashAlgorithmSha512);
139 expectAlgorithmFailure("sha1;");
140 expectAlgorithmFailure("sha-1;");
141 expectAlgorithmFailure("sha-256;");
142 expectAlgorithmFailure("sha-384;");
143 expectAlgorithmFailure("sha-512;");
146 TEST_F(SubresourceIntegrityTest, ParseDigest)
148 expectDigest("abcdefg", "abcdefg");
149 expectDigest("abcdefg?", "abcdefg");
151 expectDigestFailure("?");
152 expectDigestFailure("&&&foobar&&&");
153 expectDigestFailure("\x01\x02\x03\x04");
157 // End-to-end parsing tests.
160 TEST_F(SubresourceIntegrityTest, Parsing)
162 expectParseFailure("");
163 expectParseFailure("not/really/a/valid/anything");
164 expectParseFailure("foobar:///sha256;abcdefg");
165 expectParseFailure("ni://sha256;abcdefg");
166 expectParseFailure("ni:///not-sha256-at-all;abcdefg");
167 expectParseFailure("ni:///sha256;&&&foobar&&&");
168 expectParseFailure("ni:///sha256;\x01\x02\x03\x04");
171 "ni:///sha256;BpfBw7ivV8q2jLiT13fxDYAe2tJllusRSZ273h2nFSE=",
172 "BpfBw7ivV8q2jLiT13fxDYAe2tJllusRSZ273h2nFSE=",
173 HashAlgorithmSha256);
176 " ni:///sha256;BpfBw7ivV8q2jLiT13fxDYAe2tJllusRSZ273h2nFSE= ",
177 "BpfBw7ivV8q2jLiT13fxDYAe2tJllusRSZ273h2nFSE=",
178 HashAlgorithmSha256);
181 "ni:///sha384;XVVXBGoYw6AJOh9J/Z8pBDMVVPfkBpngexkA7JqZu8d5GENND6TEIup/tA1v5GPr",
182 "XVVXBGoYw6AJOh9J/Z8pBDMVVPfkBpngexkA7JqZu8d5GENND6TEIup/tA1v5GPr",
183 HashAlgorithmSha384);
186 "ni:///sha512;tbUPioKbVBplr0b1ucnWB57SJWt4x9dOE0Vy2mzCXvH3FepqDZ+07yMK81ytlg0MPaIrPAjcHqba5csorDWtKg==",
187 "tbUPioKbVBplr0b1ucnWB57SJWt4x9dOE0Vy2mzCXvH3FepqDZ+07yMK81ytlg0MPaIrPAjcHqba5csorDWtKg==",
188 HashAlgorithmSha512);
192 // End-to-end tests of ::CheckSubresourceIntegrity.
195 TEST_F(SubresourceIntegrityTest, CheckSubresourceIntegrityInSecureOrigin)
197 document->updateSecurityOrigin(secureOrigin->isolatedCopy());
199 // Verify basic sha256, sha384, and sha512 integrity checks.
200 expectIntegrity(kSha256Integrity, kBasicScript, secureURL);
201 expectIntegrity(kSha384Integrity, kBasicScript, secureURL);
202 expectIntegrity(kSha512Integrity, kBasicScript, secureURL);
204 // The hash label must match the hash value.
205 expectIntegrityFailure(kSha384IntegrityLabeledAs256, kBasicScript, secureURL);
207 // Unsupported hash functions should fail.
208 expectIntegrityFailure(kUnsupportedHashFunctionIntegrity, kBasicScript, secureURL);
211 TEST_F(SubresourceIntegrityTest, CheckSubresourceIntegrityInInsecureOrigin)
213 // The same checks as CheckSubresourceIntegrityInSecureOrigin should fail here.
214 document->updateSecurityOrigin(insecureOrigin->isolatedCopy());
216 expectIntegrityFailure(kSha256Integrity, kBasicScript, secureURL);
217 expectIntegrityFailure(kSha384Integrity, kBasicScript, secureURL);
218 expectIntegrityFailure(kSha512Integrity, kBasicScript, secureURL);
219 expectIntegrityFailure(kSha384IntegrityLabeledAs256, kBasicScript, secureURL);
220 expectIntegrityFailure(kUnsupportedHashFunctionIntegrity, kBasicScript, secureURL);