LCOV - code coverage report
Current view: top level - dom/security - SRICheck.cpp (source / functions) Hit Total Coverage
Test: output.info Lines: 23 277 8.3 %
Date: 2017-07-14 16:53:18 Functions: 3 15 20.0 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
       2             : /* vim: set ts=8 sts=2 et sw=2 tw=80: */
       3             : /* This Source Code Form is subject to the terms of the Mozilla Public
       4             :  * License, v. 2.0. If a copy of the MPL was not distributed with this
       5             :  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
       6             : 
       7             : #include "SRICheck.h"
       8             : 
       9             : #include "mozilla/Base64.h"
      10             : #include "mozilla/LoadTainting.h"
      11             : #include "mozilla/Logging.h"
      12             : #include "mozilla/Preferences.h"
      13             : #include "mozilla/SizePrintfMacros.h"
      14             : #include "mozilla/dom/SRILogHelper.h"
      15             : #include "mozilla/dom/SRIMetadata.h"
      16             : #include "nsContentUtils.h"
      17             : #include "nsIChannel.h"
      18             : #include "nsIConsoleReportCollector.h"
      19             : #include "nsIProtocolHandler.h"
      20             : #include "nsIScriptError.h"
      21             : #include "nsIIncrementalStreamLoader.h"
      22             : #include "nsIUnicharStreamLoader.h"
      23             : #include "nsIURI.h"
      24             : #include "nsNetUtil.h"
      25             : #include "nsWhitespaceTokenizer.h"
      26             : 
      27             : #define SRIVERBOSE(args)                                                       \
      28             :   MOZ_LOG(SRILogHelper::GetSriLog(), mozilla::LogLevel::Verbose, args)
      29             : #define SRILOG(args)                                                           \
      30             :   MOZ_LOG(SRILogHelper::GetSriLog(), mozilla::LogLevel::Debug, args)
      31             : #define SRIERROR(args)                                                         \
      32             :   MOZ_LOG(SRILogHelper::GetSriLog(), mozilla::LogLevel::Error, args)
      33             : 
      34             : namespace mozilla {
      35             : namespace dom {
      36             : 
      37             : /**
      38             :  * Returns whether or not the sub-resource about to be loaded is eligible
      39             :  * for integrity checks. If it's not, the checks will be skipped and the
      40             :  * sub-resource will be loaded.
      41             :  */
      42             : static nsresult
      43           0 : IsEligible(nsIChannel* aChannel, mozilla::LoadTainting aTainting,
      44             :            const nsACString& aSourceFileURI,
      45             :            nsIConsoleReportCollector* aReporter)
      46             : {
      47           0 :   NS_ENSURE_ARG_POINTER(aReporter);
      48             : 
      49           0 :   if (!aChannel) {
      50           0 :     SRILOG(("SRICheck::IsEligible, null channel"));
      51           0 :     return NS_ERROR_SRI_NOT_ELIGIBLE;
      52             :   }
      53             : 
      54             :   // Was the sub-resource loaded via CORS?
      55           0 :   if (aTainting == LoadTainting::CORS) {
      56           0 :     SRILOG(("SRICheck::IsEligible, CORS mode"));
      57           0 :     return NS_OK;
      58             :   }
      59             : 
      60           0 :   nsCOMPtr<nsIURI> finalURI;
      61           0 :   nsresult rv = NS_GetFinalChannelURI(aChannel, getter_AddRefs(finalURI));
      62           0 :   NS_ENSURE_SUCCESS(rv, rv);
      63           0 :   nsCOMPtr<nsIURI> originalURI;
      64           0 :   rv = aChannel->GetOriginalURI(getter_AddRefs(originalURI));
      65           0 :   NS_ENSURE_SUCCESS(rv, rv);
      66           0 :   nsAutoCString requestSpec;
      67           0 :   rv = originalURI->GetSpec(requestSpec);
      68           0 :   NS_ENSURE_SUCCESS(rv, rv);
      69             : 
      70           0 :   if (MOZ_LOG_TEST(SRILogHelper::GetSriLog(), mozilla::LogLevel::Debug)) {
      71           0 :     SRILOG(("SRICheck::IsEligible, requestURI=%s; finalURI=%s",
      72             :             requestSpec.get(),
      73             :             finalURI ? finalURI->GetSpecOrDefault().get() : ""));
      74             :   }
      75             : 
      76             :   // Is the sub-resource same-origin?
      77           0 :   if (aTainting == LoadTainting::Basic) {
      78           0 :     SRILOG(("SRICheck::IsEligible, same-origin"));
      79           0 :     return NS_OK;
      80             :   }
      81           0 :   SRILOG(("SRICheck::IsEligible, NOT same origin"));
      82             : 
      83           0 :   NS_ConvertUTF8toUTF16 requestSpecUTF16(requestSpec);
      84           0 :   nsTArray<nsString> params;
      85           0 :   params.AppendElement(requestSpecUTF16);
      86           0 :   aReporter->AddConsoleReport(nsIScriptError::errorFlag,
      87           0 :                               NS_LITERAL_CSTRING("Sub-resource Integrity"),
      88             :                               nsContentUtils::eSECURITY_PROPERTIES,
      89             :                               aSourceFileURI, 0, 0,
      90           0 :                               NS_LITERAL_CSTRING("IneligibleResource"),
      91           0 :                               const_cast<const nsTArray<nsString>&>(params));
      92           0 :   return NS_ERROR_SRI_NOT_ELIGIBLE;
      93             : }
      94             : 
      95             : /* static */ nsresult
      96           0 : SRICheck::IntegrityMetadata(const nsAString& aMetadataList,
      97             :                             const nsACString& aSourceFileURI,
      98             :                             nsIConsoleReportCollector* aReporter,
      99             :                             SRIMetadata* outMetadata)
     100             : {
     101           0 :   NS_ENSURE_ARG_POINTER(outMetadata);
     102           0 :   NS_ENSURE_ARG_POINTER(aReporter);
     103           0 :   MOZ_ASSERT(outMetadata->IsEmpty()); // caller must pass empty metadata
     104             : 
     105           0 :   if (!Preferences::GetBool("security.sri.enable", false)) {
     106           0 :     SRILOG(("SRICheck::IntegrityMetadata, sri is disabled (pref)"));
     107           0 :     return NS_ERROR_SRI_DISABLED;
     108             :   }
     109             : 
     110             :   // put a reasonable bound on the length of the metadata
     111           0 :   NS_LossyConvertUTF16toASCII metadataList(aMetadataList);
     112           0 :   if (metadataList.Length() > SRICheck::MAX_METADATA_LENGTH) {
     113           0 :     metadataList.Truncate(SRICheck::MAX_METADATA_LENGTH);
     114             :   }
     115           0 :   SRILOG(("SRICheck::IntegrityMetadata, metadataList=%s", metadataList.get()));
     116           0 :   MOZ_ASSERT(metadataList.Length() <= aMetadataList.Length());
     117             : 
     118             :   // the integrity attribute is a list of whitespace-separated hashes
     119             :   // and options so we need to look at them one by one and pick the
     120             :   // strongest (valid) one
     121           0 :   nsCWhitespaceTokenizer tokenizer(metadataList);
     122           0 :   nsAutoCString token;
     123           0 :   for (uint32_t i=0; tokenizer.hasMoreTokens() &&
     124             :          i < SRICheck::MAX_METADATA_TOKENS; ++i) {
     125           0 :     token = tokenizer.nextToken();
     126             : 
     127           0 :     SRIMetadata metadata(token);
     128           0 :     if (metadata.IsMalformed()) {
     129           0 :       NS_ConvertUTF8toUTF16 tokenUTF16(token);
     130           0 :       nsTArray<nsString> params;
     131           0 :       params.AppendElement(tokenUTF16);
     132           0 :       aReporter->AddConsoleReport(nsIScriptError::warningFlag,
     133           0 :                                   NS_LITERAL_CSTRING("Sub-resource Integrity"),
     134             :                                   nsContentUtils::eSECURITY_PROPERTIES,
     135             :                                   aSourceFileURI, 0, 0,
     136           0 :                                   NS_LITERAL_CSTRING("MalformedIntegrityHash"),
     137           0 :                                   const_cast<const nsTArray<nsString>&>(params));
     138           0 :     } else if (!metadata.IsAlgorithmSupported()) {
     139           0 :       nsAutoCString alg;
     140           0 :       metadata.GetAlgorithm(&alg);
     141           0 :       NS_ConvertUTF8toUTF16 algUTF16(alg);
     142           0 :       nsTArray<nsString> params;
     143           0 :       params.AppendElement(algUTF16);
     144           0 :       aReporter->AddConsoleReport(nsIScriptError::warningFlag,
     145           0 :                                   NS_LITERAL_CSTRING("Sub-resource Integrity"),
     146             :                                   nsContentUtils::eSECURITY_PROPERTIES,
     147             :                                   aSourceFileURI, 0, 0,
     148           0 :                                   NS_LITERAL_CSTRING("UnsupportedHashAlg"),
     149           0 :                                   const_cast<const nsTArray<nsString>&>(params));
     150             :     }
     151             : 
     152           0 :     nsAutoCString alg1, alg2;
     153           0 :     if (MOZ_LOG_TEST(SRILogHelper::GetSriLog(), mozilla::LogLevel::Debug)) {
     154           0 :       outMetadata->GetAlgorithm(&alg1);
     155           0 :       metadata.GetAlgorithm(&alg2);
     156             :     }
     157           0 :     if (*outMetadata == metadata) {
     158           0 :       SRILOG(("SRICheck::IntegrityMetadata, alg '%s' is the same as '%s'",
     159             :               alg1.get(), alg2.get()));
     160           0 :       *outMetadata += metadata; // add new hash to strongest metadata
     161           0 :     } else if (*outMetadata < metadata) {
     162           0 :       SRILOG(("SRICheck::IntegrityMetadata, alg '%s' is weaker than '%s'",
     163             :               alg1.get(), alg2.get()));
     164           0 :       *outMetadata = metadata; // replace strongest metadata with current
     165             :     }
     166             :   }
     167             : 
     168           0 :   outMetadata->mIntegrityString = aMetadataList;
     169             : 
     170           0 :   if (MOZ_LOG_TEST(SRILogHelper::GetSriLog(), mozilla::LogLevel::Debug)) {
     171           0 :     if (outMetadata->IsValid()) {
     172           0 :       nsAutoCString alg;
     173           0 :       outMetadata->GetAlgorithm(&alg);
     174           0 :       SRILOG(("SRICheck::IntegrityMetadata, using a '%s' hash", alg.get()));
     175           0 :     } else if (outMetadata->IsEmpty()) {
     176           0 :       SRILOG(("SRICheck::IntegrityMetadata, no metadata"));
     177             :     } else {
     178           0 :       SRILOG(("SRICheck::IntegrityMetadata, no valid metadata found"));
     179             :     }
     180             :   }
     181           0 :   return NS_OK;
     182             : }
     183             : 
     184             : /* static */ nsresult
     185           0 : SRICheck::VerifyIntegrity(const SRIMetadata& aMetadata,
     186             :                           nsIUnicharStreamLoader* aLoader,
     187             :                           const nsAString& aString,
     188             :                           const nsACString& aSourceFileURI,
     189             :                           nsIConsoleReportCollector* aReporter)
     190             : {
     191           0 :   NS_ENSURE_ARG_POINTER(aLoader);
     192           0 :   NS_ENSURE_ARG_POINTER(aReporter);
     193             : 
     194           0 :   nsCOMPtr<nsIChannel> channel;
     195           0 :   aLoader->GetChannel(getter_AddRefs(channel));
     196             : 
     197           0 :   if (MOZ_LOG_TEST(SRILogHelper::GetSriLog(), mozilla::LogLevel::Debug)) {
     198           0 :     nsAutoCString requestURL;
     199           0 :     nsCOMPtr<nsIURI> originalURI;
     200           0 :     if (channel &&
     201           0 :         NS_SUCCEEDED(channel->GetOriginalURI(getter_AddRefs(originalURI))) &&
     202           0 :         originalURI) {
     203           0 :       originalURI->GetAsciiSpec(requestURL);
     204             :     }
     205           0 :     SRILOG(("SRICheck::VerifyIntegrity (unichar stream)"));
     206             :   }
     207             : 
     208           0 :   SRICheckDataVerifier verifier(aMetadata, aSourceFileURI, aReporter);
     209             :   nsresult rv;
     210           0 :   nsDependentCString rawBuffer;
     211           0 :   rv = aLoader->GetRawBuffer(rawBuffer);
     212           0 :   NS_ENSURE_SUCCESS(rv, rv);
     213           0 :   rv = verifier.Update(rawBuffer.Length(), (const uint8_t*)rawBuffer.get());
     214           0 :   NS_ENSURE_SUCCESS(rv, rv);
     215             : 
     216           0 :   return verifier.Verify(aMetadata, channel, aSourceFileURI, aReporter);
     217             : }
     218             : 
     219             : //////////////////////////////////////////////////////////////
     220             : //
     221             : //////////////////////////////////////////////////////////////
     222           0 : SRICheckDataVerifier::SRICheckDataVerifier(const SRIMetadata& aMetadata,
     223             :                                            const nsACString& aSourceFileURI,
     224           0 :                                            nsIConsoleReportCollector* aReporter)
     225             :   : mCryptoHash(nullptr),
     226             :     mBytesHashed(0),
     227             :     mInvalidMetadata(false),
     228           0 :     mComplete(false)
     229             : {
     230           0 :   MOZ_ASSERT(!aMetadata.IsEmpty()); // should be checked by caller
     231             : 
     232             :   // IntegrityMetadata() checks this and returns "no metadata" if
     233             :   // it's disabled so we should never make it this far
     234           0 :   MOZ_ASSERT(Preferences::GetBool("security.sri.enable", false));
     235           0 :   MOZ_ASSERT(aReporter);
     236             : 
     237           0 :   if (!aMetadata.IsValid()) {
     238           0 :     nsTArray<nsString> params;
     239           0 :     aReporter->AddConsoleReport(nsIScriptError::warningFlag,
     240           0 :                                 NS_LITERAL_CSTRING("Sub-resource Integrity"),
     241             :                                 nsContentUtils::eSECURITY_PROPERTIES,
     242             :                                 aSourceFileURI, 0, 0,
     243           0 :                                 NS_LITERAL_CSTRING("NoValidMetadata"),
     244           0 :                                 const_cast<const nsTArray<nsString>&>(params));
     245           0 :     mInvalidMetadata = true;
     246           0 :     return; // ignore invalid metadata for forward-compatibility
     247             :   }
     248             : 
     249           0 :   aMetadata.GetHashType(&mHashType, &mHashLength);
     250             : }
     251             : 
     252             : nsresult
     253           0 : SRICheckDataVerifier::EnsureCryptoHash()
     254             : {
     255           0 :   MOZ_ASSERT(!mInvalidMetadata);
     256             : 
     257           0 :   if (mCryptoHash) {
     258           0 :     return NS_OK;
     259             :   }
     260             : 
     261             :   nsresult rv;
     262             :   nsCOMPtr<nsICryptoHash> cryptoHash =
     263           0 :     do_CreateInstance("@mozilla.org/security/hash;1", &rv);
     264           0 :   NS_ENSURE_SUCCESS(rv, rv);
     265           0 :   rv = cryptoHash->Init(mHashType);
     266           0 :   NS_ENSURE_SUCCESS(rv, rv);
     267             : 
     268           0 :   mCryptoHash = cryptoHash;
     269           0 :   return NS_OK;
     270             : }
     271             : 
     272             : nsresult
     273           0 : SRICheckDataVerifier::Update(uint32_t aStringLen, const uint8_t* aString)
     274             : {
     275           0 :   NS_ENSURE_ARG_POINTER(aString);
     276           0 :   if (mInvalidMetadata) {
     277           0 :     return NS_OK; // ignoring any data updates, see mInvalidMetadata usage
     278             :   }
     279             : 
     280             :   nsresult rv;
     281           0 :   rv = EnsureCryptoHash();
     282           0 :   NS_ENSURE_SUCCESS(rv, rv);
     283             : 
     284           0 :   mBytesHashed += aStringLen;
     285             : 
     286           0 :   return mCryptoHash->Update(aString, aStringLen);
     287             : }
     288             : 
     289             : nsresult
     290           0 : SRICheckDataVerifier::Finish()
     291             : {
     292           0 :   if (mInvalidMetadata || mComplete) {
     293           0 :     return NS_OK; // already finished or invalid metadata
     294             :   }
     295             : 
     296             :   nsresult rv;
     297           0 :   rv = EnsureCryptoHash(); // we need computed hash even for 0-length data
     298           0 :   NS_ENSURE_SUCCESS(rv, rv);
     299             : 
     300           0 :   rv = mCryptoHash->Finish(false, mComputedHash);
     301           0 :   mCryptoHash = nullptr;
     302           0 :   mComplete = true;
     303           0 :   return rv;
     304             : }
     305             : 
     306             : nsresult
     307           0 : SRICheckDataVerifier::VerifyHash(const SRIMetadata& aMetadata,
     308             :                                  uint32_t aHashIndex,
     309             :                                  const nsACString& aSourceFileURI,
     310             :                                  nsIConsoleReportCollector* aReporter)
     311             : {
     312           0 :   NS_ENSURE_ARG_POINTER(aReporter);
     313             : 
     314           0 :   nsAutoCString base64Hash;
     315           0 :   aMetadata.GetHash(aHashIndex, &base64Hash);
     316           0 :   SRILOG(("SRICheckDataVerifier::VerifyHash, hash[%u]=%s", aHashIndex, base64Hash.get()));
     317             : 
     318           0 :   nsAutoCString binaryHash;
     319           0 :   if (NS_WARN_IF(NS_FAILED(Base64Decode(base64Hash, binaryHash)))) {
     320           0 :     nsTArray<nsString> params;
     321           0 :     aReporter->AddConsoleReport(nsIScriptError::errorFlag,
     322           0 :                                 NS_LITERAL_CSTRING("Sub-resource Integrity"),
     323             :                                 nsContentUtils::eSECURITY_PROPERTIES,
     324             :                                 aSourceFileURI, 0, 0,
     325           0 :                                 NS_LITERAL_CSTRING("InvalidIntegrityBase64"),
     326           0 :                                 const_cast<const nsTArray<nsString>&>(params));
     327           0 :     return NS_ERROR_SRI_CORRUPT;
     328             :   }
     329             : 
     330             :   uint32_t hashLength;
     331             :   int8_t hashType;
     332           0 :   aMetadata.GetHashType(&hashType, &hashLength);
     333           0 :   if (binaryHash.Length() != hashLength) {
     334           0 :     nsTArray<nsString> params;
     335           0 :     aReporter->AddConsoleReport(nsIScriptError::errorFlag,
     336           0 :                                 NS_LITERAL_CSTRING("Sub-resource Integrity"),
     337             :                                 nsContentUtils::eSECURITY_PROPERTIES,
     338             :                                 aSourceFileURI, 0, 0,
     339           0 :                                 NS_LITERAL_CSTRING("InvalidIntegrityLength"),
     340           0 :                                 const_cast<const nsTArray<nsString>&>(params));
     341           0 :     return NS_ERROR_SRI_CORRUPT;
     342             :   }
     343             : 
     344           0 :   if (MOZ_LOG_TEST(SRILogHelper::GetSriLog(), mozilla::LogLevel::Debug)) {
     345           0 :     nsAutoCString encodedHash;
     346           0 :     nsresult rv = Base64Encode(mComputedHash, encodedHash);
     347           0 :     if (NS_SUCCEEDED(rv)) {
     348           0 :       SRILOG(("SRICheckDataVerifier::VerifyHash, mComputedHash=%s",
     349             :               encodedHash.get()));
     350             :     }
     351             :   }
     352             : 
     353           0 :   if (!binaryHash.Equals(mComputedHash)) {
     354           0 :     SRILOG(("SRICheckDataVerifier::VerifyHash, hash[%u] did not match", aHashIndex));
     355           0 :     return NS_ERROR_SRI_CORRUPT;
     356             :   }
     357             : 
     358           0 :   SRILOG(("SRICheckDataVerifier::VerifyHash, hash[%u] verified successfully", aHashIndex));
     359           0 :   return NS_OK;
     360             : }
     361             : 
     362             : nsresult
     363           0 : SRICheckDataVerifier::Verify(const SRIMetadata& aMetadata,
     364             :                              nsIChannel* aChannel,
     365             :                              const nsACString& aSourceFileURI,
     366             :                              nsIConsoleReportCollector* aReporter)
     367             : {
     368           0 :   NS_ENSURE_ARG_POINTER(aReporter);
     369             : 
     370           0 :   if (MOZ_LOG_TEST(SRILogHelper::GetSriLog(), mozilla::LogLevel::Debug)) {
     371           0 :     nsAutoCString requestURL;
     372           0 :     nsCOMPtr<nsIRequest> request;
     373           0 :     request = do_QueryInterface(aChannel);
     374           0 :     request->GetName(requestURL);
     375           0 :     SRILOG(("SRICheckDataVerifier::Verify, url=%s (length=%" PRIuSIZE ")",
     376             :             requestURL.get(), mBytesHashed));
     377             :   }
     378             : 
     379           0 :   nsresult rv = Finish();
     380           0 :   NS_ENSURE_SUCCESS(rv, rv);
     381             : 
     382           0 :   nsCOMPtr<nsILoadInfo> loadInfo = aChannel->GetLoadInfo();
     383           0 :   NS_ENSURE_TRUE(loadInfo, NS_ERROR_FAILURE);
     384           0 :   LoadTainting tainting = loadInfo->GetTainting();
     385             : 
     386           0 :   if (NS_FAILED(IsEligible(aChannel, tainting, aSourceFileURI, aReporter))) {
     387           0 :     return NS_ERROR_SRI_NOT_ELIGIBLE;
     388             :   }
     389             : 
     390           0 :   if (mInvalidMetadata) {
     391           0 :     return NS_OK; // ignore invalid metadata for forward-compatibility
     392             :   }
     393             : 
     394           0 :   for (uint32_t i = 0; i < aMetadata.HashCount(); i++) {
     395           0 :     if (NS_SUCCEEDED(VerifyHash(aMetadata, i, aSourceFileURI, aReporter))) {
     396           0 :       return NS_OK; // stop at the first valid hash
     397             :     }
     398             :   }
     399             : 
     400           0 :   nsAutoCString alg;
     401           0 :   aMetadata.GetAlgorithm(&alg);
     402           0 :   NS_ConvertUTF8toUTF16 algUTF16(alg);
     403           0 :   nsTArray<nsString> params;
     404           0 :   params.AppendElement(algUTF16);
     405           0 :   aReporter->AddConsoleReport(nsIScriptError::errorFlag,
     406           0 :                               NS_LITERAL_CSTRING("Sub-resource Integrity"),
     407             :                               nsContentUtils::eSECURITY_PROPERTIES,
     408             :                               aSourceFileURI, 0, 0,
     409           0 :                               NS_LITERAL_CSTRING("IntegrityMismatch"),
     410           0 :                               const_cast<const nsTArray<nsString>&>(params));
     411           0 :   return NS_ERROR_SRI_CORRUPT;
     412             : }
     413             : 
     414             : uint32_t
     415           0 : SRICheckDataVerifier::DataSummaryLength()
     416             : {
     417           0 :   MOZ_ASSERT(!mInvalidMetadata);
     418           0 :   return sizeof(mHashType) + sizeof(mHashLength) + mHashLength;
     419             : }
     420             : 
     421             : uint32_t
     422          12 : SRICheckDataVerifier::EmptyDataSummaryLength()
     423             : {
     424          12 :   return sizeof(int8_t) + sizeof(uint32_t);
     425             : }
     426             : 
     427             : nsresult
     428           4 : SRICheckDataVerifier::DataSummaryLength(uint32_t aDataLen, const uint8_t* aData, uint32_t* length)
     429             : {
     430           4 :   *length = 0;
     431           4 :   NS_ENSURE_ARG_POINTER(aData);
     432             : 
     433             :   // we expect to always encode an SRI, even if it is empty or incomplete
     434           4 :   if (aDataLen < EmptyDataSummaryLength()) {
     435           0 :     SRILOG(("SRICheckDataVerifier::DataSummaryLength, encoded length[%u] is too small", aDataLen));
     436           0 :     return NS_ERROR_SRI_IMPORT;
     437             :   }
     438             : 
     439             :   // decode the content of the buffer
     440           4 :   size_t offset = sizeof(mHashType);
     441           4 :   size_t len = *reinterpret_cast<const decltype(mHashLength)*>(&aData[offset]);
     442           4 :   offset += sizeof(mHashLength);
     443             : 
     444           4 :   SRIVERBOSE(("SRICheckDataVerifier::DataSummaryLength, header {%x, %x, %x, %x, %x, ...}",
     445             :               aData[0], aData[1], aData[2], aData[3], aData[4]));
     446             : 
     447           4 :   if (offset + len > aDataLen) {
     448           0 :     SRILOG(("SRICheckDataVerifier::DataSummaryLength, encoded length[%u] overflow the buffer size", aDataLen));
     449           0 :     SRIVERBOSE(("SRICheckDataVerifier::DataSummaryLength, offset[%u], len[%u]",
     450             :                 uint32_t(offset), uint32_t(len)));
     451           0 :     return NS_ERROR_SRI_IMPORT;
     452             :   }
     453           4 :   *length = uint32_t(offset + len);
     454           4 :   return NS_OK;
     455             : }
     456             : 
     457             : nsresult
     458           0 : SRICheckDataVerifier::ImportDataSummary(uint32_t aDataLen, const uint8_t* aData)
     459             : {
     460           0 :   MOZ_ASSERT(!mInvalidMetadata); // mHashType and mHashLength should be valid
     461           0 :   MOZ_ASSERT(!mCryptoHash); // EnsureCryptoHash should not have been called
     462           0 :   NS_ENSURE_ARG_POINTER(aData);
     463           0 :   if (mInvalidMetadata) {
     464           0 :     return NS_OK; // ignoring any data updates, see mInvalidMetadata usage
     465             :   }
     466             : 
     467             :   // we expect to always encode an SRI, even if it is empty or incomplete
     468           0 :   if (aDataLen < DataSummaryLength()) {
     469           0 :     SRILOG(("SRICheckDataVerifier::ImportDataSummary, encoded length[%u] is too small", aDataLen));
     470           0 :     return NS_ERROR_SRI_IMPORT;
     471             :   }
     472             : 
     473           0 :   SRIVERBOSE(("SRICheckDataVerifier::ImportDataSummary, header {%x, %x, %x, %x, %x, ...}",
     474             :               aData[0], aData[1], aData[2], aData[3], aData[4]));
     475             : 
     476             :   // decode the content of the buffer
     477           0 :   size_t offset = 0;
     478           0 :   if (*reinterpret_cast<const decltype(mHashType)*>(&aData[offset]) != mHashType) {
     479           0 :     SRILOG(("SRICheckDataVerifier::ImportDataSummary, hash type[%d] does not match[%d]",
     480             :             *reinterpret_cast<const decltype(mHashType)*>(&aData[offset]),
     481             :              mHashType));
     482           0 :     return NS_ERROR_SRI_UNEXPECTED_HASH_TYPE;
     483             :   }
     484           0 :   offset += sizeof(mHashType);
     485             : 
     486           0 :   if (*reinterpret_cast<const decltype(mHashLength)*>(&aData[offset]) != mHashLength) {
     487           0 :     SRILOG(("SRICheckDataVerifier::ImportDataSummary, hash length[%d] does not match[%d]",
     488             :             *reinterpret_cast<const decltype(mHashLength)*>(&aData[offset]),
     489             :              mHashLength));
     490           0 :     return NS_ERROR_SRI_UNEXPECTED_HASH_TYPE;
     491             :   }
     492           0 :   offset += sizeof(mHashLength);
     493             : 
     494             :   // copy the hash to mComputedHash, as-if we had finished streaming the bytes
     495           0 :   mComputedHash.Assign(reinterpret_cast<const char*>(&aData[offset]), mHashLength);
     496           0 :   mCryptoHash = nullptr;
     497           0 :   mComplete = true;
     498           0 :   return NS_OK;
     499             : }
     500             : 
     501             : nsresult
     502           0 : SRICheckDataVerifier::ExportDataSummary(uint32_t aDataLen, uint8_t* aData)
     503             : {
     504           0 :   MOZ_ASSERT(!mInvalidMetadata); // mHashType and mHashLength should be valid
     505           0 :   MOZ_ASSERT(mComplete); // finished streaming
     506           0 :   NS_ENSURE_ARG_POINTER(aData);
     507           0 :   NS_ENSURE_TRUE(aDataLen >= DataSummaryLength(), NS_ERROR_INVALID_ARG);
     508             : 
     509             :   // serialize the hash in the buffer
     510           0 :   size_t offset = 0;
     511           0 :   *reinterpret_cast<decltype(mHashType)*>(&aData[offset]) = mHashType;
     512           0 :   offset += sizeof(mHashType);
     513           0 :   *reinterpret_cast<decltype(mHashLength)*>(&aData[offset]) = mHashLength;
     514           0 :   offset += sizeof(mHashLength);
     515             : 
     516           0 :   SRIVERBOSE(("SRICheckDataVerifier::ExportDataSummary, header {%x, %x, %x, %x, %x, ...}",
     517             :               aData[0], aData[1], aData[2], aData[3], aData[4]));
     518             : 
     519             :   // copy the hash to mComputedHash, as-if we had finished streaming the bytes
     520           0 :   nsCharTraits<char>::copy(reinterpret_cast<char*>(&aData[offset]),
     521           0 :                            mComputedHash.get(), mHashLength);
     522           0 :   return NS_OK;
     523             : }
     524             : 
     525             : nsresult
     526           4 : SRICheckDataVerifier::ExportEmptyDataSummary(uint32_t aDataLen, uint8_t* aData)
     527             : {
     528           4 :   NS_ENSURE_ARG_POINTER(aData);
     529           4 :   NS_ENSURE_TRUE(aDataLen >= EmptyDataSummaryLength(), NS_ERROR_INVALID_ARG);
     530             : 
     531             :   // serialize an unknown hash in the buffer, to be able to skip it later
     532           4 :   size_t offset = 0;
     533           4 :   *reinterpret_cast<decltype(mHashType)*>(&aData[offset]) = 0;
     534           4 :   offset += sizeof(mHashType);
     535           4 :   *reinterpret_cast<decltype(mHashLength)*>(&aData[offset]) = 0;
     536           4 :   offset += sizeof(mHashLength);
     537             : 
     538           4 :   SRIVERBOSE(("SRICheckDataVerifier::ExportEmptyDataSummary, header {%x, %x, %x, %x, %x, ...}",
     539             :               aData[0], aData[1], aData[2], aData[3], aData[4]));
     540             : 
     541           4 :   return NS_OK;
     542             : }
     543             : 
     544             : } // namespace dom
     545             : } // namespace mozilla

Generated by: LCOV version 1.13