0

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:
Mike West 2025-03-28 01:27:44 -07:00 committed by Chromium LUCI CQ
parent 88c7d24d8a
commit 2307b98658
10 changed files with 110 additions and 125 deletions

@ -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));
}
}
}