Drop IntegrityMetadataPair
.
This CL turns `IntegrityMetadata` into a simple struct, and uses it directly in `IntegrityMetadataSet` rather than converting it into a `std::pair` along the way. This CL shouldn't cause any change in behavior, it just simplifies a weird bit of infrastructure. Change-Id: I3696aac46efbb04c4b1c01f9c1f149b7eb580f8b Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/6400757 Commit-Queue: Mike West <mkwst@chromium.org> Reviewed-by: Antonio Sartori <antoniosartori@chromium.org> Cr-Commit-Position: refs/heads/main@{#1439264}
This commit is contained in:
parent
88c7d24d8a
commit
2307b98658
third_party/blink/renderer
@ -325,13 +325,14 @@ bool AreAllMatchingIntegrityChecksPresent(
|
||||
|
||||
// Check that all hashes present in the integrity metadata are allowed
|
||||
// by the relevant policy:
|
||||
for (const IntegrityMetadataPair& hash : integrity_metadata.hashes) {
|
||||
for (const IntegrityMetadata& hash : integrity_metadata.hashes) {
|
||||
// Convert the hash from integrity metadata format to CSP format.
|
||||
network::mojom::blink::CSPHashSourcePtr csp_hash =
|
||||
network::mojom::blink::CSPHashSource::New();
|
||||
csp_hash->algorithm = hash.second;
|
||||
if (!ParseBase64Digest(hash.first, csp_hash->value))
|
||||
csp_hash->algorithm = hash.algorithm;
|
||||
if (!ParseBase64Digest(hash.digest, csp_hash->value)) {
|
||||
return false;
|
||||
}
|
||||
// All integrity hashes must be listed in the CSP.
|
||||
if (!CSPSourceListAllowHash(*directive, *csp_hash))
|
||||
return false;
|
||||
@ -339,12 +340,12 @@ bool AreAllMatchingIntegrityChecksPresent(
|
||||
|
||||
// Now check that all public keys present in the integrity metadata are
|
||||
// allowed by the relevant policy:
|
||||
for (const IntegrityMetadataPair& key : integrity_metadata.public_keys) {
|
||||
for (const IntegrityMetadata& key : integrity_metadata.public_keys) {
|
||||
// Convert the hash from integrity metadata format to CSP format.
|
||||
network::mojom::blink::CSPHashSourcePtr csp_hash =
|
||||
network::mojom::blink::CSPHashSource::New();
|
||||
csp_hash->algorithm = key.second;
|
||||
if (!ParseBase64Digest(key.first, csp_hash->value)) {
|
||||
csp_hash->algorithm = key.algorithm;
|
||||
if (!ParseBase64Digest(key.digest, csp_hash->value)) {
|
||||
return false;
|
||||
}
|
||||
// All integrity hashes must be listed in the CSP.
|
||||
|
@ -6,19 +6,19 @@
|
||||
|
||||
namespace blink {
|
||||
|
||||
void IntegrityMetadataSet::Insert(const IntegrityMetadataPair& pair) {
|
||||
switch (pair.second) {
|
||||
void IntegrityMetadataSet::Insert(IntegrityMetadata item) {
|
||||
switch (item.algorithm) {
|
||||
case IntegrityAlgorithm::kSha256:
|
||||
case IntegrityAlgorithm::kSha384:
|
||||
case IntegrityAlgorithm::kSha512:
|
||||
if (!hashes.Contains(pair)) {
|
||||
hashes.push_back(std::move(pair));
|
||||
if (!hashes.Contains(item)) {
|
||||
hashes.push_back(std::move(item));
|
||||
}
|
||||
break;
|
||||
|
||||
case IntegrityAlgorithm::kEd25519:
|
||||
if (!public_keys.Contains(pair)) {
|
||||
public_keys.push_back(std::move(pair));
|
||||
if (!public_keys.Contains(item)) {
|
||||
public_keys.push_back(std::move(item));
|
||||
}
|
||||
break;
|
||||
}
|
||||
@ -26,13 +26,6 @@ void IntegrityMetadataSet::Insert(const IntegrityMetadataPair& pair) {
|
||||
|
||||
IntegrityMetadata::IntegrityMetadata(WTF::String digest,
|
||||
IntegrityAlgorithm algorithm)
|
||||
: digest_(digest), algorithm_(algorithm) {}
|
||||
|
||||
IntegrityMetadata::IntegrityMetadata(IntegrityMetadataPair pair)
|
||||
: digest_(pair.first), algorithm_(pair.second) {}
|
||||
|
||||
IntegrityMetadataPair IntegrityMetadata::ToPair() const {
|
||||
return IntegrityMetadataPair(digest_, algorithm_);
|
||||
}
|
||||
: digest(std::move(digest)), algorithm(algorithm) {}
|
||||
|
||||
} // namespace blink
|
||||
|
@ -16,10 +16,19 @@
|
||||
|
||||
namespace blink {
|
||||
|
||||
class IntegrityMetadata;
|
||||
|
||||
using IntegrityAlgorithm = network::mojom::blink::IntegrityAlgorithm;
|
||||
using IntegrityMetadataPair = std::pair<String, IntegrityAlgorithm>;
|
||||
|
||||
struct PLATFORM_EXPORT IntegrityMetadata {
|
||||
IntegrityMetadata() = default;
|
||||
IntegrityMetadata(String digest, IntegrityAlgorithm);
|
||||
|
||||
bool operator==(const IntegrityMetadata& other) const {
|
||||
return this->digest == other.digest && this->algorithm == other.algorithm;
|
||||
}
|
||||
|
||||
String digest;
|
||||
IntegrityAlgorithm algorithm;
|
||||
};
|
||||
|
||||
// Contains the result of SRI's "Parse Metadata" algorithm:
|
||||
//
|
||||
@ -27,10 +36,10 @@ using IntegrityMetadataPair = std::pair<String, IntegrityAlgorithm>;
|
||||
struct PLATFORM_EXPORT IntegrityMetadataSet {
|
||||
IntegrityMetadataSet() = default;
|
||||
bool empty() const { return hashes.empty() && public_keys.empty(); }
|
||||
WTF::Vector<IntegrityMetadataPair> hashes;
|
||||
WTF::Vector<IntegrityMetadataPair> public_keys;
|
||||
WTF::Vector<IntegrityMetadata> hashes;
|
||||
WTF::Vector<IntegrityMetadata> public_keys;
|
||||
|
||||
void Insert(const IntegrityMetadataPair& pair);
|
||||
void Insert(IntegrityMetadata pair);
|
||||
|
||||
bool operator==(const IntegrityMetadataSet& other) const {
|
||||
return this->hashes == other.hashes &&
|
||||
@ -38,26 +47,6 @@ struct PLATFORM_EXPORT IntegrityMetadataSet {
|
||||
}
|
||||
};
|
||||
|
||||
class PLATFORM_EXPORT IntegrityMetadata {
|
||||
STACK_ALLOCATED();
|
||||
|
||||
public:
|
||||
IntegrityMetadata() = default;
|
||||
IntegrityMetadata(String digest, IntegrityAlgorithm);
|
||||
IntegrityMetadata(IntegrityMetadataPair);
|
||||
|
||||
String Digest() const { return digest_; }
|
||||
void SetDigest(const String& digest) { digest_ = digest; }
|
||||
IntegrityAlgorithm Algorithm() const { return algorithm_; }
|
||||
void SetAlgorithm(IntegrityAlgorithm algorithm) { algorithm_ = algorithm; }
|
||||
|
||||
IntegrityMetadataPair ToPair() const;
|
||||
|
||||
private:
|
||||
String digest_;
|
||||
IntegrityAlgorithm algorithm_;
|
||||
};
|
||||
|
||||
enum class ResourceIntegrityDisposition : uint8_t {
|
||||
kNotChecked = 0,
|
||||
kNetworkError,
|
||||
|
@ -471,7 +471,7 @@ void ResourceRequestHead::SetFetchIntegrity(
|
||||
void ResourceRequestHead::SetExpectedPublicKeys(
|
||||
const IntegrityMetadataSet& metadata) {
|
||||
for (const auto& public_key : metadata.public_keys) {
|
||||
expected_public_keys_.push_back(public_key.first);
|
||||
expected_public_keys_.push_back(public_key.digest);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -230,7 +230,7 @@ bool SubresourceIntegrity::CheckSubresourceIntegrityImpl(
|
||||
}
|
||||
|
||||
bool SubresourceIntegrity::CheckHashesImpl(
|
||||
const WTF::Vector<IntegrityMetadataPair>& hashes,
|
||||
const WTF::Vector<IntegrityMetadata>& hashes,
|
||||
const SegmentedBuffer* buffer,
|
||||
const KURL& resource_url,
|
||||
const FeatureContext* feature_context,
|
||||
@ -268,13 +268,13 @@ bool SubresourceIntegrity::CheckHashesImpl(
|
||||
// Then we loop through the asserted hashes, ignoring any that don't use
|
||||
// the strongest algorithm asserted:
|
||||
for (const IntegrityMetadata& metadata : hashes) {
|
||||
if (metadata.Algorithm() != strongest_algorithm) {
|
||||
if (metadata.algorithm != strongest_algorithm) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// And finally decode the metadata's digest for comparison.
|
||||
Vector<char> decoded_metadata;
|
||||
Base64Decode(metadata.Digest(), decoded_metadata);
|
||||
Base64Decode(metadata.digest, decoded_metadata);
|
||||
DigestValue expected_value;
|
||||
expected_value.AppendSpan(base::as_byte_span(decoded_metadata));
|
||||
|
||||
@ -311,14 +311,14 @@ bool SubresourceIntegrity::CheckHashesImpl(
|
||||
}
|
||||
|
||||
bool SubresourceIntegrity::CheckSignaturesImpl(
|
||||
const WTF::Vector<IntegrityMetadataPair>& integrity_pairs,
|
||||
const WTF::Vector<IntegrityMetadata>& integrity_list,
|
||||
const KURL& resource_url,
|
||||
const String& raw_headers,
|
||||
IntegrityReport& integrity_report) {
|
||||
// This implements steps 6 and 8.3 of
|
||||
// https://wicg.github.io/signature-based-sri/#matching.
|
||||
//
|
||||
if (integrity_pairs.empty()) {
|
||||
if (integrity_list.empty()) {
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -344,7 +344,7 @@ bool SubresourceIntegrity::CheckSignaturesImpl(
|
||||
|
||||
// This would be caught below, but we'll exit early for unsigned resources
|
||||
// so we can provide a better error message in the console.
|
||||
if (signatures.empty() && !integrity_pairs.empty()) {
|
||||
if (signatures.empty() && !integrity_list.empty()) {
|
||||
integrity_report.AddConsoleErrorMessage(
|
||||
"Subresource Integrity: The resource at `" +
|
||||
resource_url.ElidedString() +
|
||||
@ -353,8 +353,8 @@ bool SubresourceIntegrity::CheckSignaturesImpl(
|
||||
return false;
|
||||
}
|
||||
|
||||
for (const IntegrityMetadata& metadata : integrity_pairs) {
|
||||
String public_key = metadata.Digest();
|
||||
for (const IntegrityMetadata& metadata : integrity_list) {
|
||||
String public_key = metadata.digest;
|
||||
for (const auto& signature : signatures) {
|
||||
if (signature->keyid == public_key) {
|
||||
return true;
|
||||
@ -370,7 +370,7 @@ bool SubresourceIntegrity::CheckSignaturesImpl(
|
||||
}
|
||||
|
||||
IntegrityAlgorithm SubresourceIntegrity::FindBestAlgorithm(
|
||||
const WTF::Vector<IntegrityMetadataPair>& metadata_pairs) {
|
||||
const WTF::Vector<IntegrityMetadata>& metadata_list) {
|
||||
// Find the "strongest" algorithm in the set. (This relies on
|
||||
// IntegrityAlgorithm declaration order matching the "strongest" order, so
|
||||
// make the compiler check this assumption first.)
|
||||
@ -380,12 +380,13 @@ IntegrityAlgorithm SubresourceIntegrity::FindBestAlgorithm(
|
||||
"of the integrity algorithms.");
|
||||
|
||||
// metadata_set is non-empty, so we are guaranteed to always have a result.
|
||||
DCHECK(!metadata_pairs.empty());
|
||||
DCHECK(!metadata_list.empty());
|
||||
return std::max_element(
|
||||
metadata_pairs.begin(), metadata_pairs.end(),
|
||||
[](const IntegrityMetadataPair& a,
|
||||
const IntegrityMetadataPair& b) { return a.second < b.second; })
|
||||
->second;
|
||||
metadata_list.begin(), metadata_list.end(),
|
||||
[](const IntegrityMetadata& a, const IntegrityMetadata& b) {
|
||||
return a.algorithm < b.algorithm;
|
||||
})
|
||||
->algorithm;
|
||||
}
|
||||
|
||||
SubresourceIntegrity::AlgorithmParseResult
|
||||
@ -529,7 +530,7 @@ void SubresourceIntegrity::ParseIntegrityAttribute(
|
||||
}
|
||||
}
|
||||
|
||||
IntegrityMetadata integrity_metadata(digest, algorithm);
|
||||
IntegrityMetadata integrity_metadata(std::move(digest), algorithm);
|
||||
if (integrity_report) {
|
||||
if (IsHashingAlgorithm(algorithm)) {
|
||||
integrity_report->AddUseCount(WebFeature::kSRIHashAssertion);
|
||||
@ -537,7 +538,7 @@ void SubresourceIntegrity::ParseIntegrityAttribute(
|
||||
integrity_report->AddUseCount(WebFeature::kSRIPublicKeyAssertion);
|
||||
}
|
||||
}
|
||||
metadata_set.Insert(std::move(integrity_metadata.ToPair()));
|
||||
metadata_set.Insert(std::move(integrity_metadata));
|
||||
}
|
||||
}
|
||||
|
||||
@ -588,7 +589,7 @@ bool SubresourceIntegrity::VerifyInlineIntegrity(
|
||||
|
||||
for (const auto& key : integrity_metadata.public_keys) {
|
||||
Vector<char> decoded_key;
|
||||
if (!Base64Decode(key.first, decoded_key) || decoded_key.size() != 32u) {
|
||||
if (!Base64Decode(key.digest, decoded_key) || decoded_key.size() != 32u) {
|
||||
// TODO(391907163): Log an error for invalid public key digests.
|
||||
continue;
|
||||
}
|
||||
|
@ -101,7 +101,7 @@ class PLATFORM_EXPORT SubresourceIntegrity final {
|
||||
HashMap<HashAlgorithm, String>* computed_hashes);
|
||||
|
||||
// Handles hash validation during SRI checks.
|
||||
static bool CheckHashesImpl(const WTF::Vector<IntegrityMetadataPair>&,
|
||||
static bool CheckHashesImpl(const WTF::Vector<IntegrityMetadata>&,
|
||||
const SegmentedBuffer*,
|
||||
const KURL&,
|
||||
const FeatureContext*,
|
||||
@ -109,7 +109,7 @@ class PLATFORM_EXPORT SubresourceIntegrity final {
|
||||
HashMap<HashAlgorithm, String>* computed_hashes);
|
||||
|
||||
// Handles signature-based matching during SRI checks
|
||||
static bool CheckSignaturesImpl(const WTF::Vector<IntegrityMetadataPair>&,
|
||||
static bool CheckSignaturesImpl(const WTF::Vector<IntegrityMetadata>&,
|
||||
const KURL& resource_url,
|
||||
const String& raw_headers,
|
||||
IntegrityReport&);
|
||||
@ -118,7 +118,7 @@ class PLATFORM_EXPORT SubresourceIntegrity final {
|
||||
using AlgorithmParseResult = base::expected<size_t, AlgorithmParseError>;
|
||||
|
||||
static IntegrityAlgorithm FindBestAlgorithm(
|
||||
const WTF::Vector<IntegrityMetadataPair>&);
|
||||
const WTF::Vector<IntegrityMetadata>&);
|
||||
|
||||
static bool CheckSubresourceIntegrityDigest(const IntegrityMetadata&,
|
||||
const SegmentedBuffer* buffer);
|
||||
|
@ -72,12 +72,12 @@ constexpr char kBadSha256AndBadSha384Integrities[] =
|
||||
constexpr char kUnsupportedHashFunctionIntegrity[] =
|
||||
"sha1-JfLW308qMPKfb4DaHpUBEESwuPc=";
|
||||
|
||||
auto CompareIntegrityMetadataPair = [](const IntegrityMetadataPair& a,
|
||||
const IntegrityMetadataPair& b) {
|
||||
if (a.first != b.first) {
|
||||
return WTF::CodeUnitCompareLessThan(a.first, b.first);
|
||||
auto CompareIntegrityMetadata = [](const IntegrityMetadata& a,
|
||||
const IntegrityMetadata& b) {
|
||||
if (a.digest != b.digest) {
|
||||
return WTF::CodeUnitCompareLessThan(a.digest, b.digest);
|
||||
}
|
||||
return a.second < b.second;
|
||||
return a.algorithm < b.algorithm;
|
||||
};
|
||||
|
||||
} // namespace
|
||||
@ -155,8 +155,8 @@ class SubresourceIntegrityTest : public testing::Test {
|
||||
EXPECT_EQ(1u, metadata_set.hashes.size());
|
||||
if (metadata_set.hashes.size() > 0) {
|
||||
IntegrityMetadata metadata = *metadata_set.hashes.begin();
|
||||
EXPECT_EQ(expected_digest, metadata.Digest());
|
||||
EXPECT_EQ(expected_algorithm, metadata.Algorithm());
|
||||
EXPECT_EQ(expected_digest, metadata.digest);
|
||||
EXPECT_EQ(expected_algorithm, metadata.algorithm);
|
||||
}
|
||||
}
|
||||
|
||||
@ -165,7 +165,7 @@ class SubresourceIntegrityTest : public testing::Test {
|
||||
base::span<const IntegrityMetadata> expected_metadata) {
|
||||
IntegrityMetadataSet expected_metadata_set;
|
||||
for (const auto& expected : expected_metadata) {
|
||||
expected_metadata_set.Insert(std::move(expected.ToPair()));
|
||||
expected_metadata_set.Insert(std::move(expected));
|
||||
}
|
||||
IntegrityMetadataSet metadata_set;
|
||||
SubresourceIntegrity::ParseIntegrityAttribute(
|
||||
@ -580,7 +580,7 @@ TEST_F(SubresourceIntegrityTest, FindBestAlgorithm) {
|
||||
IntegrityAlgorithm::kEd25519,
|
||||
};
|
||||
|
||||
WTF::Vector<IntegrityMetadataPair> alg_set;
|
||||
WTF::Vector<IntegrityMetadata> alg_set;
|
||||
for (IntegrityAlgorithm alg : algs) {
|
||||
SCOPED_TRACE(alg);
|
||||
|
||||
@ -589,7 +589,7 @@ TEST_F(SubresourceIntegrityTest, FindBestAlgorithm) {
|
||||
|
||||
// Check that each algorithm in the test cases is stronger than the
|
||||
// previously-tested algorithms.
|
||||
alg_set.push_back(std::make_pair("", alg));
|
||||
alg_set.push_back(IntegrityMetadata("", alg));
|
||||
EXPECT_EQ(alg, SubresourceIntegrity::FindBestAlgorithm(alg_set));
|
||||
}
|
||||
}
|
||||
@ -639,8 +639,8 @@ class SubresourceIntegritySignatureTest
|
||||
ASSERT_EQ(1u, metadata_set.public_keys.size());
|
||||
|
||||
IntegrityMetadata metadata = *metadata_set.public_keys.begin();
|
||||
EXPECT_EQ(digest, metadata.Digest());
|
||||
EXPECT_EQ(IntegrityAlgorithm::kEd25519, metadata.Algorithm());
|
||||
EXPECT_EQ(digest, metadata.digest);
|
||||
EXPECT_EQ(IntegrityAlgorithm::kEd25519, metadata.algorithm);
|
||||
} else {
|
||||
ASSERT_EQ(0u, metadata_set.public_keys.size());
|
||||
}
|
||||
@ -649,8 +649,8 @@ class SubresourceIntegritySignatureTest
|
||||
// Evalutes whether the given string is parsed into a set of IntegrityMetadata
|
||||
// items that contains each of the items in |hashes| and |public_keys|.
|
||||
void ValidateMultipleItems(const String& integrity_attribute,
|
||||
const Vector<IntegrityMetadataPair>& hashes,
|
||||
const Vector<IntegrityMetadataPair>& public_keys) {
|
||||
const Vector<IntegrityMetadata>& hashes,
|
||||
const Vector<IntegrityMetadata>& public_keys) {
|
||||
IntegrityMetadataSet metadata_set;
|
||||
SubresourceIntegrity::ParseIntegrityAttribute(
|
||||
integrity_attribute, metadata_set, /*feature_context=*/nullptr);
|
||||
@ -729,20 +729,20 @@ TEST_P(SubresourceIntegritySignatureTest, ParseSingleSignature) {
|
||||
}
|
||||
|
||||
TEST_P(SubresourceIntegritySignatureTest, ParseMultipleSignatures) {
|
||||
Vector<IntegrityMetadataPair> signature_pairs = {
|
||||
std::make_pair("AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=",
|
||||
IntegrityAlgorithm::kEd25519),
|
||||
std::make_pair("BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB=",
|
||||
IntegrityAlgorithm::kEd25519),
|
||||
std::make_pair("CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC=",
|
||||
IntegrityAlgorithm::kEd25519),
|
||||
Vector<IntegrityMetadata> signature_pairs = {
|
||||
IntegrityMetadata("AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=",
|
||||
IntegrityAlgorithm::kEd25519),
|
||||
IntegrityMetadata("BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB=",
|
||||
IntegrityAlgorithm::kEd25519),
|
||||
IntegrityMetadata("CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC=",
|
||||
IntegrityAlgorithm::kEd25519),
|
||||
};
|
||||
|
||||
do {
|
||||
StringBuilder attribute;
|
||||
for (const auto& pair : signature_pairs) {
|
||||
attribute.Append(AlgorithmToPrefix(pair.second));
|
||||
attribute.Append(pair.first);
|
||||
attribute.Append(AlgorithmToPrefix(pair.algorithm));
|
||||
attribute.Append(pair.digest);
|
||||
attribute.Append(' ');
|
||||
}
|
||||
SCOPED_TRACE(attribute.ToString());
|
||||
@ -757,40 +757,41 @@ TEST_P(SubresourceIntegritySignatureTest, ParseMultipleSignatures) {
|
||||
ValidateMultipleItems(attribute.ToString() + " ed25519-???", {},
|
||||
signature_pairs);
|
||||
} while (std::next_permutation(signature_pairs.begin(), signature_pairs.end(),
|
||||
CompareIntegrityMetadataPair));
|
||||
CompareIntegrityMetadata));
|
||||
}
|
||||
|
||||
TEST_P(SubresourceIntegritySignatureTest, ParseBoth) {
|
||||
Vector<IntegrityMetadataPair> hash_pairs = {
|
||||
Vector<IntegrityMetadata> hash_pairs = {
|
||||
// "Hello, world."
|
||||
std::make_pair("+MO/YqmqPm/BYZwlDkir51GTc9Pt9BvmLrXcRRma8u8=",
|
||||
IntegrityAlgorithm::kSha256),
|
||||
std::make_pair(
|
||||
IntegrityMetadata("+MO/YqmqPm/BYZwlDkir51GTc9Pt9BvmLrXcRRma8u8=",
|
||||
IntegrityAlgorithm::kSha256),
|
||||
IntegrityMetadata(
|
||||
"S7LmUoguRQsq3IHIZ0Xhm5jjCDqH6uUQbumuj5CnrIFDk+RyBW/dWuqzEiV4mPaB",
|
||||
IntegrityAlgorithm::kSha384),
|
||||
std::make_pair("rQw3wx1psxXzqB8TyM3nAQlK2RcluhsNwxmcqXE2YbgoDW735o8TPmIR4"
|
||||
"uWpoxUERddvFwjgRSGw7gNPCwuvJg==",
|
||||
IntegrityAlgorithm::kSha512),
|
||||
IntegrityMetadata(
|
||||
"rQw3wx1psxXzqB8TyM3nAQlK2RcluhsNwxmcqXE2YbgoDW735o8TPmIR4"
|
||||
"uWpoxUERddvFwjgRSGw7gNPCwuvJg==",
|
||||
IntegrityAlgorithm::kSha512),
|
||||
};
|
||||
Vector<IntegrityMetadataPair> signature_pairs = {
|
||||
std::make_pair("AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=",
|
||||
IntegrityAlgorithm::kEd25519),
|
||||
std::make_pair("BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB=",
|
||||
IntegrityAlgorithm::kEd25519),
|
||||
std::make_pair("CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC=",
|
||||
IntegrityAlgorithm::kEd25519),
|
||||
Vector<IntegrityMetadata> signature_pairs = {
|
||||
IntegrityMetadata("AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=",
|
||||
IntegrityAlgorithm::kEd25519),
|
||||
IntegrityMetadata("BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB=",
|
||||
IntegrityAlgorithm::kEd25519),
|
||||
IntegrityMetadata("CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC=",
|
||||
IntegrityAlgorithm::kEd25519),
|
||||
};
|
||||
|
||||
do {
|
||||
StringBuilder attribute;
|
||||
for (const auto& pair : signature_pairs) {
|
||||
attribute.Append(AlgorithmToPrefix(pair.second));
|
||||
attribute.Append(pair.first);
|
||||
attribute.Append(AlgorithmToPrefix(pair.algorithm));
|
||||
attribute.Append(pair.digest);
|
||||
attribute.Append(' ');
|
||||
}
|
||||
for (const auto& pair : hash_pairs) {
|
||||
attribute.Append(AlgorithmToPrefix(pair.second));
|
||||
attribute.Append(pair.first);
|
||||
attribute.Append(AlgorithmToPrefix(pair.algorithm));
|
||||
attribute.Append(pair.digest);
|
||||
attribute.Append(' ');
|
||||
}
|
||||
SCOPED_TRACE(attribute.ToString());
|
||||
@ -805,7 +806,7 @@ TEST_P(SubresourceIntegritySignatureTest, ParseBoth) {
|
||||
ValidateMultipleItems(attribute.ToString() + " ed25519-???", hash_pairs,
|
||||
signature_pairs);
|
||||
} while (std::next_permutation(signature_pairs.begin(), signature_pairs.end(),
|
||||
CompareIntegrityMetadataPair));
|
||||
CompareIntegrityMetadata));
|
||||
}
|
||||
|
||||
TEST_P(SubresourceIntegritySignatureTest, CheckEmpty) {
|
||||
@ -830,7 +831,7 @@ TEST_P(SubresourceIntegritySignatureTest, CheckEmpty) {
|
||||
TEST_P(SubresourceIntegritySignatureTest, CheckNotSigned) {
|
||||
IntegrityReport integrity_report;
|
||||
IntegrityMetadataSet metadata_set;
|
||||
metadata_set.Insert(std::make_pair("", IntegrityAlgorithm::kEd25519));
|
||||
metadata_set.Insert(IntegrityMetadata("", IntegrityAlgorithm::kEd25519));
|
||||
String raw_headers = "";
|
||||
|
||||
// If the flag is set, the lack of a signature will fail any signature
|
||||
@ -876,7 +877,7 @@ TEST_P(SubresourceIntegritySignatureTest, CheckValidSignature) {
|
||||
IntegrityReport integrity_report;
|
||||
IntegrityMetadataSet metadata_set;
|
||||
metadata_set.public_keys = {
|
||||
std::make_pair(kPublicKey, IntegrityAlgorithm::kEd25519)};
|
||||
IntegrityMetadata(kPublicKey, IntegrityAlgorithm::kEd25519)};
|
||||
|
||||
// Valid signature matching the integrity requirement should always pass.
|
||||
EXPECT_TRUE(SubresourceIntegrity::CheckSubresourceIntegrity(
|
||||
|
@ -65,10 +65,10 @@ std::optional<UnencodedDigest> UnencodedDigest::Create(
|
||||
IntegrityMetadata parsed_digest;
|
||||
size_t expected_digest_length = 0;
|
||||
if (entry.first == kSHA256Token) {
|
||||
parsed_digest.SetAlgorithm(IntegrityAlgorithm::kSha256);
|
||||
parsed_digest.algorithm = IntegrityAlgorithm::kSha256;
|
||||
expected_digest_length = 32;
|
||||
} else if (entry.first == kSHA512Token) {
|
||||
parsed_digest.SetAlgorithm(IntegrityAlgorithm::kSha512);
|
||||
parsed_digest.algorithm = IntegrityAlgorithm::kSha512;
|
||||
expected_digest_length = 64;
|
||||
} else {
|
||||
// Skip over entries with unknown algorithm tokens.
|
||||
@ -95,8 +95,8 @@ std::optional<UnencodedDigest> UnencodedDigest::Create(
|
||||
|
||||
// Store the byte sequence as a base64-encoded digest, matching CSP and
|
||||
// SRI's existing `IntegrityMetadata` implementation.
|
||||
parsed_digest.SetDigest(Base64Encode(base::as_byte_span(digest)));
|
||||
integrity_metadata.Insert(std::move(parsed_digest.ToPair()));
|
||||
parsed_digest.digest = Base64Encode(base::as_byte_span(digest));
|
||||
integrity_metadata.Insert(std::move(parsed_digest));
|
||||
}
|
||||
|
||||
if (integrity_metadata.hashes.empty()) {
|
||||
@ -107,7 +107,7 @@ std::optional<UnencodedDigest> UnencodedDigest::Create(
|
||||
|
||||
bool UnencodedDigest::DoesMatch(WTF::SegmentedBuffer* data) {
|
||||
for (const IntegrityMetadata& digest : integrity_metadata_.hashes) {
|
||||
HashAlgorithm algorithm = GetHashAlgorithm(digest.Algorithm());
|
||||
HashAlgorithm algorithm = GetHashAlgorithm(digest.algorithm);
|
||||
DigestValue computed_digest;
|
||||
if (!ComputeDigest(algorithm, data, computed_digest)) {
|
||||
// TODO(https://crbug.com/381044049): Emit errors.
|
||||
@ -116,7 +116,7 @@ bool UnencodedDigest::DoesMatch(WTF::SegmentedBuffer* data) {
|
||||
|
||||
// Convert the stored digest into a `DigestValue`
|
||||
Vector<char> digest_bytes;
|
||||
Base64Decode(digest.Digest(), digest_bytes);
|
||||
Base64Decode(digest.digest, digest_bytes);
|
||||
DigestValue expected_digest(base::as_byte_span(digest_bytes));
|
||||
|
||||
// If any specified digest doesn't match the digest computed over |data|,
|
||||
|
@ -30,7 +30,7 @@ class PLATFORM_EXPORT UnencodedDigest {
|
||||
// `Unencoded-Digest` header is present, and `std::nullopt` otherwise.
|
||||
static std::optional<UnencodedDigest> Create(const HTTPHeaderMap&);
|
||||
|
||||
const WTF::Vector<IntegrityMetadataPair>& digests() const {
|
||||
const WTF::Vector<IntegrityMetadata>& digests() const {
|
||||
return integrity_metadata_.hashes;
|
||||
}
|
||||
|
||||
|
@ -173,13 +173,13 @@ TEST(UnencodedDigestParserTest, WellFormedHeaderWithSingleDigest) {
|
||||
headers.Set(http_names::kUnencodedDigest, AtomicString(test.header));
|
||||
|
||||
IntegrityMetadata expected;
|
||||
expected.SetAlgorithm(test.alg);
|
||||
expected.SetDigest(kHelloWorlds.at(test.alg));
|
||||
expected.algorithm = test.alg;
|
||||
expected.digest = kHelloWorlds.at(test.alg);
|
||||
|
||||
auto result = UnencodedDigest::Create(headers);
|
||||
EXPECT_TRUE(result.has_value());
|
||||
EXPECT_EQ(1u, result->digests().size());
|
||||
EXPECT_TRUE(result->digests().Contains(expected.ToPair()));
|
||||
EXPECT_TRUE(result->digests().Contains(expected));
|
||||
}
|
||||
}
|
||||
|
||||
@ -220,9 +220,9 @@ TEST(UnencodedDigestParserTest, MultipleDigests) {
|
||||
|
||||
for (const auto& algorithm : test.alg) {
|
||||
IntegrityMetadata expected;
|
||||
expected.SetAlgorithm(algorithm);
|
||||
expected.SetDigest(kHelloWorlds.at(algorithm));
|
||||
EXPECT_TRUE(result->digests().Contains(expected.ToPair()));
|
||||
expected.algorithm = algorithm;
|
||||
expected.digest = kHelloWorlds.at(algorithm);
|
||||
EXPECT_TRUE(result->digests().Contains(expected));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user