SRICheckDataVerifier::SRICheckDataVerifier(const SRIMetadata& aMetadata, const nsACString& aSourceFileURI, nsIConsoleReportCollector* aReporter) : mCryptoHash(nullptr) , mBytesHashed(0) , mHashLength(0) , mHashType('\0') , mInvalidMetadata(false) , mComplete(false) { MOZ_ASSERT(!aMetadata.IsEmpty()); // should be checked by caller // IntegrityMetadata() checks this and returns "no metadata" if // it's disabled so we should never make it this far MOZ_ASSERT(Preferences::GetBool("security.sri.enable", false)); MOZ_ASSERT(aReporter); if (!aMetadata.IsValid()) { nsTArray<nsString> params; aReporter->AddConsoleReport(nsIScriptError::warningFlag, NS_LITERAL_CSTRING("Sub-resource Integrity"), nsContentUtils::eSECURITY_PROPERTIES, aSourceFileURI, 0, 0, NS_LITERAL_CSTRING("NoValidMetadata"), const_cast<const nsTArray<nsString>&>(params)); mInvalidMetadata = true; return; // ignore invalid metadata for forward-compatibility } aMetadata.GetHashType(&mHashType, &mHashLength); }
SRICheckDataVerifier::SRICheckDataVerifier(const SRIMetadata& aMetadata, const nsIDocument* aDocument) : mCryptoHash(nullptr), mBytesHashed(0), mInvalidMetadata(false), mComplete(false) { MOZ_ASSERT(!aMetadata.IsEmpty()); // should be checked by caller // IntegrityMetadata() checks this and returns "no metadata" if // it's disabled so we should never make it this far MOZ_ASSERT(Preferences::GetBool("security.sri.enable", false)); if (!aMetadata.IsValid()) { nsContentUtils::ReportToConsole(nsIScriptError::warningFlag, NS_LITERAL_CSTRING("Sub-resource Integrity"), aDocument, nsContentUtils::eSECURITY_PROPERTIES, "NoValidMetadata"); mInvalidMetadata = true; return; // ignore invalid metadata for forward-compatibility } uint32_t hashLength; aMetadata.GetHashType(&mHashType, &hashLength); }
nsresult SRICheckDataVerifier::VerifyHash(const SRIMetadata& aMetadata, uint32_t aHashIndex, const nsACString& aSourceFileURI, nsIConsoleReportCollector* aReporter) { NS_ENSURE_ARG_POINTER(aReporter); nsAutoCString base64Hash; aMetadata.GetHash(aHashIndex, &base64Hash); SRILOG(("SRICheckDataVerifier::VerifyHash, hash[%u]=%s", aHashIndex, base64Hash.get())); nsAutoCString binaryHash; if (NS_WARN_IF(NS_FAILED(Base64Decode(base64Hash, binaryHash)))) { nsTArray<nsString> params; aReporter->AddConsoleReport(nsIScriptError::errorFlag, NS_LITERAL_CSTRING("Sub-resource Integrity"), nsContentUtils::eSECURITY_PROPERTIES, aSourceFileURI, 0, 0, NS_LITERAL_CSTRING("InvalidIntegrityBase64"), const_cast<const nsTArray<nsString>&>(params)); return NS_ERROR_SRI_CORRUPT; } uint32_t hashLength; int8_t hashType; aMetadata.GetHashType(&hashType, &hashLength); if (binaryHash.Length() != hashLength) { nsTArray<nsString> params; aReporter->AddConsoleReport(nsIScriptError::errorFlag, NS_LITERAL_CSTRING("Sub-resource Integrity"), nsContentUtils::eSECURITY_PROPERTIES, aSourceFileURI, 0, 0, NS_LITERAL_CSTRING("InvalidIntegrityLength"), const_cast<const nsTArray<nsString>&>(params)); return NS_ERROR_SRI_CORRUPT; } if (MOZ_LOG_TEST(SRILogHelper::GetSriLog(), mozilla::LogLevel::Debug)) { nsAutoCString encodedHash; nsresult rv = Base64Encode(mComputedHash, encodedHash); if (NS_SUCCEEDED(rv)) { SRILOG(("SRICheckDataVerifier::VerifyHash, mComputedHash=%s", encodedHash.get())); } } if (!binaryHash.Equals(mComputedHash)) { SRILOG(("SRICheckDataVerifier::VerifyHash, hash[%u] did not match", aHashIndex)); return NS_ERROR_SRI_CORRUPT; } SRILOG(("SRICheckDataVerifier::VerifyHash, hash[%u] verified successfully", aHashIndex)); return NS_OK; }
/** * Compute the hash of a sub-resource and compare it with the expected * value. */ static nsresult VerifyHash(const SRIMetadata& aMetadata, uint32_t aHashIndex, uint32_t aStringLen, const uint8_t* aString, const nsIDocument* aDocument) { NS_ENSURE_ARG_POINTER(aString); NS_ENSURE_ARG_POINTER(aDocument); nsAutoCString base64Hash; aMetadata.GetHash(aHashIndex, &base64Hash); SRILOG(("SRICheck::VerifyHash, hash[%u]=%s", aHashIndex, base64Hash.get())); nsAutoCString binaryHash; if (NS_WARN_IF(NS_FAILED(Base64Decode(base64Hash, binaryHash)))) { nsContentUtils::ReportToConsole(nsIScriptError::errorFlag, NS_LITERAL_CSTRING("Sub-resource Integrity"), aDocument, nsContentUtils::eSECURITY_PROPERTIES, "InvalidIntegrityBase64"); return NS_ERROR_SRI_CORRUPT; } uint32_t hashLength; int8_t hashType; aMetadata.GetHashType(&hashType, &hashLength); if (binaryHash.Length() != hashLength) { nsContentUtils::ReportToConsole(nsIScriptError::errorFlag, NS_LITERAL_CSTRING("Sub-resource Integrity"), aDocument, nsContentUtils::eSECURITY_PROPERTIES, "InvalidIntegrityLength"); return NS_ERROR_SRI_CORRUPT; } nsresult rv; nsCOMPtr<nsICryptoHash> cryptoHash = do_CreateInstance("@mozilla.org/security/hash;1", &rv); NS_ENSURE_SUCCESS(rv, rv); rv = cryptoHash->Init(hashType); NS_ENSURE_SUCCESS(rv, rv); rv = cryptoHash->Update(aString, aStringLen); NS_ENSURE_SUCCESS(rv, rv); nsAutoCString computedHash; rv = cryptoHash->Finish(false, computedHash); NS_ENSURE_SUCCESS(rv, rv); if (!binaryHash.Equals(computedHash)) { SRILOG(("SRICheck::VerifyHash, hash[%u] did not match", aHashIndex)); return NS_ERROR_SRI_CORRUPT; } SRILOG(("SRICheck::VerifyHash, hash[%u] verified successfully", aHashIndex)); return NS_OK; }