/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ /* vim: set ts=8 sts=2 et sw=2 tw=80: */ /* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
/** * Returns whether or not the sub-resource about to be loaded is eligible * for integrity checks. If it's not, the checks will be skipped and the * sub-resource will be loaded.
*/ static nsresult IsEligible(nsIChannel* aChannel,
mozilla::LoadTainting aTainting, const nsACString& aSourceFileURI,
nsIConsoleReportCollector* aReporter) {
NS_ENSURE_ARG_POINTER(aReporter);
if (!aChannel) {
SRILOG(("SRICheck::IsEligible, null channel")); return NS_ERROR_SRI_NOT_ELIGIBLE;
}
// Was the sub-resource loaded via CORS? if (aTainting == LoadTainting::CORS) {
SRILOG(("SRICheck::IsEligible, CORS mode")); return NS_OK;
}
// Is the sub-resource same-origin? if (aTainting == LoadTainting::Basic) {
SRILOG(("SRICheck::IsEligible, same-origin")); return NS_OK;
}
SRILOG(("SRICheck::IsEligible, NOT same-origin"));
// the integrity attribute is a list of whitespace-separated hashes // and options so we need to look at them one by one and pick the // strongest (valid) one
nsCWhitespaceTokenizer tokenizer(metadataList);
nsAutoCString token; while (tokenizer.hasMoreTokens()) {
token = tokenizer.nextToken();
// the decoded supplied hash should match our computed binary hash. if (!binaryHash.Equals(mComputedHash)) {
SRILOG(("SRICheckDataVerifier::VerifyHash, hash[%u] did not match",
aHashIndex)); return NS_ERROR_SRI_CORRUPT;
}
if (NS_FAILED(IsEligible(aChannel, tainting, aSourceFileURI, aReporter))) { return NS_ERROR_SRI_NOT_ELIGIBLE;
}
if (mInvalidMetadata) { return NS_OK; // ignore invalid metadata for forward-compatibility
}
for (uint32_t i = 0; i < aMetadata.HashCount(); i++) { if (NS_SUCCEEDED(VerifyHash(aMetadata, i, aSourceFileURI, aReporter))) { return NS_OK; // stop at the first valid hash
}
}
// we expect to always encode an SRI, even if it is empty or incomplete if (aDataLen < EmptyDataSummaryLength()) {
SRILOG(
("SRICheckDataVerifier::DataSummaryLength, encoded length[%u] is too " "small",
aDataLen)); return NS_ERROR_SRI_IMPORT;
}
// decode the content of the buffer
size_t offset = sizeof(mHashType);
decltype(mHashLength) len = 0;
memcpy(&len, &aData[offset], sizeof(mHashLength));
offset += sizeof(mHashLength);
nsresult SRICheckDataVerifier::ImportDataSummary(uint32_t aDataLen, const uint8_t* aData) {
MOZ_ASSERT(!mInvalidMetadata); // mHashType and mHashLength should be valid
MOZ_ASSERT(!mCryptoHash); // EnsureCryptoHash should not have been called
NS_ENSURE_ARG_POINTER(aData); if (mInvalidMetadata) { return NS_OK; // ignoring any data updates, see mInvalidMetadata usage
}
// we expect to always encode an SRI, even if it is empty or incomplete if (aDataLen < DataSummaryLength()) {
SRILOG(
("SRICheckDataVerifier::ImportDataSummary, encoded length[%u] is too " "small",
aDataLen)); return NS_ERROR_SRI_IMPORT;
}
// decode the content of the buffer
size_t offset = 0;
decltype(mHashType) hashType;
memcpy(&hashType, &aData[offset], sizeof(mHashType)); if (hashType != mHashType) {
SRILOG(
("SRICheckDataVerifier::ImportDataSummary, hash type[%d] does not " "match[%d]",
hashType, mHashType)); return NS_ERROR_SRI_UNEXPECTED_HASH_TYPE;
}
offset += sizeof(mHashType);
decltype(mHashLength) hashLength;
memcpy(&hashLength, &aData[offset], sizeof(mHashLength)); if (hashLength != mHashLength) {
SRILOG(
("SRICheckDataVerifier::ImportDataSummary, hash length[%d] does not " "match[%d]",
hashLength, mHashLength)); return NS_ERROR_SRI_UNEXPECTED_HASH_TYPE;
}
offset += sizeof(mHashLength);
// copy the hash to mComputedHash, as-if we had finished streaming the bytes
mComputedHash.Assign(reinterpret_cast<constchar*>(&aData[offset]),
mHashLength);
mCryptoHash = nullptr;
mComplete = true; return NS_OK;
}
nsresult SRICheckDataVerifier::ExportDataSummary(uint32_t aDataLen,
uint8_t* aData) {
MOZ_ASSERT(!mInvalidMetadata); // mHashType and mHashLength should be valid
MOZ_ASSERT(mComplete); // finished streaming
NS_ENSURE_ARG_POINTER(aData);
NS_ENSURE_TRUE(aDataLen >= DataSummaryLength(), NS_ERROR_INVALID_ARG);
// serialize the hash in the buffer
size_t offset = 0;
memcpy(&aData[offset], &mHashType, sizeof(mHashType));
offset += sizeof(mHashType);
memcpy(&aData[offset], &mHashLength, sizeof(mHashLength));
offset += sizeof(mHashLength);
// copy the hash to mComputedHash, as-if we had finished streaming the bytes
nsCharTraits<char>::copy(reinterpret_cast<char*>(&aData[offset]),
mComputedHash.get(), mHashLength); return NS_OK;
}
// serialize an unknown hash in the buffer, to be able to skip it later
size_t offset = 0;
memset(&aData[offset], 0, sizeof(mHashType));
offset += sizeof(mHashType);
memset(&aData[offset], 0, sizeof(mHashLength));
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung ist noch experimentell.