Matter SDK Coverage Report
Current view: top level - lib/core - OTAImageHeader.cpp (source / functions) Coverage Total Hit
Test: SHA:b879ecb8e99e175eea0a293a888bda853da2b19c Lines: 100.0 % 73 73
Test Date: 2025-01-17 19:00:11 Functions: 100.0 % 6 6

            Line data    Source code
       1              : /*
       2              :  *
       3              :  *    Copyright (c) 2022 Project CHIP Authors
       4              :  *
       5              :  *    Licensed under the Apache License, Version 2.0 (the "License");
       6              :  *    you may not use this file except in compliance with the License.
       7              :  *    You may obtain a copy of the License at
       8              :  *
       9              :  *        http://www.apache.org/licenses/LICENSE-2.0
      10              :  *
      11              :  *    Unless required by applicable law or agreed to in writing, software
      12              :  *    distributed under the License is distributed on an "AS IS" BASIS,
      13              :  *    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
      14              :  *    See the License for the specific language governing permissions and
      15              :  *    limitations under the License.
      16              :  */
      17              : #include <lib/core/OTAImageHeader.h>
      18              : 
      19              : #include <lib/core/CHIPError.h>
      20              : #include <lib/core/Optional.h>
      21              : #include <lib/core/TLVReader.h>
      22              : #include <lib/core/TLVTags.h>
      23              : #include <lib/core/TLVTypes.h>
      24              : #include <lib/support/BufferReader.h>
      25              : #include <lib/support/CodeUtils.h>
      26              : #include <lib/support/ScopedBuffer.h>
      27              : #include <lib/support/Span.h>
      28              : 
      29              : #include <string.h>
      30              : 
      31              : namespace chip {
      32              : 
      33              : namespace {
      34              : 
      35              : enum class Tag : uint8_t
      36              : {
      37              :     kVendorId              = 0,
      38              :     kProductId             = 1,
      39              :     kSoftwareVersion       = 2,
      40              :     kSoftwareVersionString = 3,
      41              :     kPayloadSize           = 4,
      42              :     kMinApplicableVersion  = 5,
      43              :     kMaxApplicableVersion  = 6,
      44              :     kReleaseNotesURL       = 7,
      45              :     kImageDigestType       = 8,
      46              :     kImageDigest           = 9,
      47              : };
      48              : 
      49              : /// Length of the fixed portion of the Matter OTA image header: FileIdentifier (4B), TotalSize (8B) and HeaderSize (4B)
      50              : constexpr uint32_t kFixedHeaderSize = 16;
      51              : 
      52              : /// Maximum supported Matter OTA image header size
      53              : constexpr uint32_t kMaxHeaderSize = 1024;
      54              : 
      55              : /// Maximum size of the software version string
      56              : constexpr size_t kMaxSoftwareVersionStringSize = 64;
      57              : 
      58              : /// Maximum size of the release notes URL
      59              : constexpr size_t kMaxReleaseNotesURLSize = 256;
      60              : 
      61              : } // namespace
      62              : 
      63            9 : void OTAImageHeaderParser::Init()
      64              : {
      65            9 :     mState         = State::kInitialized;
      66            9 :     mBufferOffset  = 0;
      67            9 :     mHeaderTlvSize = 0;
      68            9 :     mBuffer.Alloc(kFixedHeaderSize);
      69            9 : }
      70              : 
      71            2 : void OTAImageHeaderParser::Clear()
      72              : {
      73            2 :     mState         = State::kNotInitialized;
      74            2 :     mBufferOffset  = 0;
      75            2 :     mHeaderTlvSize = 0;
      76            2 :     mBuffer.Free();
      77            2 : }
      78              : 
      79          112 : CHIP_ERROR OTAImageHeaderParser::AccumulateAndDecode(ByteSpan & buffer, OTAImageHeader & header)
      80              : {
      81          112 :     CHIP_ERROR error = CHIP_NO_ERROR;
      82              : 
      83          112 :     if (mState == State::kInitialized)
      84              :     {
      85           24 :         Append(buffer, kFixedHeaderSize - mBufferOffset);
      86           24 :         error = DecodeFixed();
      87              :     }
      88              : 
      89          112 :     if (mState == State::kTlv)
      90              :     {
      91           95 :         Append(buffer, mHeaderTlvSize - mBufferOffset);
      92           95 :         error = DecodeTlv(header);
      93              :     }
      94              : 
      95          112 :     if (error != CHIP_NO_ERROR && error != CHIP_ERROR_BUFFER_TOO_SMALL)
      96              :     {
      97            2 :         Clear();
      98              :     }
      99              : 
     100          112 :     return error;
     101              : }
     102              : 
     103          119 : void OTAImageHeaderParser::Append(ByteSpan & buffer, uint32_t numBytes)
     104              : {
     105          119 :     numBytes = std::min(numBytes, static_cast<uint32_t>(buffer.size()));
     106          119 :     memcpy(&mBuffer[mBufferOffset], buffer.data(), numBytes);
     107          119 :     mBufferOffset += numBytes;
     108          119 :     buffer = buffer.SubSpan(numBytes);
     109          119 : }
     110              : 
     111           24 : CHIP_ERROR OTAImageHeaderParser::DecodeFixed()
     112              : {
     113           24 :     VerifyOrReturnError(mBufferOffset >= kFixedHeaderSize, CHIP_ERROR_BUFFER_TOO_SMALL);
     114              : 
     115            8 :     Encoding::LittleEndian::Reader reader(mBuffer.Get(), mBufferOffset);
     116              :     uint32_t fileIdentifier;
     117              :     uint64_t totalSize;
     118            8 :     ReturnErrorOnFailure(reader.Read32(&fileIdentifier).Read64(&totalSize).Read32(&mHeaderTlvSize).StatusCode());
     119            8 :     VerifyOrReturnError(fileIdentifier == kOTAImageFileIdentifier, CHIP_ERROR_INVALID_FILE_IDENTIFIER);
     120              :     // Safety check against malicious headers.
     121            7 :     VerifyOrReturnError(mHeaderTlvSize <= kMaxHeaderSize, CHIP_ERROR_NO_MEMORY);
     122            7 :     VerifyOrReturnError(mBuffer.Alloc(mHeaderTlvSize), CHIP_ERROR_NO_MEMORY);
     123              : 
     124            7 :     mState        = State::kTlv;
     125            7 :     mBufferOffset = 0;
     126              : 
     127            7 :     return CHIP_NO_ERROR;
     128              : }
     129              : 
     130           95 : CHIP_ERROR OTAImageHeaderParser::DecodeTlv(OTAImageHeader & header)
     131              : {
     132           95 :     VerifyOrReturnError(mBufferOffset >= mHeaderTlvSize, CHIP_ERROR_BUFFER_TOO_SMALL);
     133              : 
     134            6 :     TLV::TLVReader tlvReader;
     135            6 :     tlvReader.Init(mBuffer.Get(), mBufferOffset);
     136            6 :     ReturnErrorOnFailure(tlvReader.Next(TLV::TLVType::kTLVType_Structure, TLV::AnonymousTag()));
     137              : 
     138              :     TLV::TLVType outerType;
     139            6 :     ReturnErrorOnFailure(tlvReader.EnterContainer(outerType));
     140              : 
     141            6 :     ReturnErrorOnFailure(tlvReader.Next(TLV::ContextTag(Tag::kVendorId)));
     142            5 :     ReturnErrorOnFailure(tlvReader.Get(header.mVendorId));
     143            5 :     ReturnErrorOnFailure(tlvReader.Next(TLV::ContextTag(Tag::kProductId)));
     144            5 :     ReturnErrorOnFailure(tlvReader.Get(header.mProductId));
     145            5 :     ReturnErrorOnFailure(tlvReader.Next(TLV::ContextTag(Tag::kSoftwareVersion)));
     146            5 :     ReturnErrorOnFailure(tlvReader.Get(header.mSoftwareVersion));
     147            5 :     ReturnErrorOnFailure(tlvReader.Next(TLV::ContextTag(Tag::kSoftwareVersionString)));
     148            5 :     ReturnErrorOnFailure(tlvReader.Get(header.mSoftwareVersionString));
     149            5 :     VerifyOrReturnError(header.mSoftwareVersionString.size() <= kMaxSoftwareVersionStringSize, CHIP_ERROR_INVALID_STRING_LENGTH);
     150            5 :     ReturnErrorOnFailure(tlvReader.Next(TLV::ContextTag(Tag::kPayloadSize)));
     151            5 :     ReturnErrorOnFailure(tlvReader.Get(header.mPayloadSize));
     152            5 :     ReturnErrorOnFailure(tlvReader.Next());
     153              : 
     154            5 :     if (tlvReader.GetTag() == TLV::ContextTag(Tag::kMinApplicableVersion))
     155              :     {
     156            4 :         ReturnErrorOnFailure(tlvReader.Get(header.mMinApplicableVersion.Emplace()));
     157            4 :         ReturnErrorOnFailure(tlvReader.Next());
     158              :     }
     159              : 
     160            5 :     if (tlvReader.GetTag() == TLV::ContextTag(Tag::kMaxApplicableVersion))
     161              :     {
     162            4 :         ReturnErrorOnFailure(tlvReader.Get(header.mMaxApplicableVersion.Emplace()));
     163            4 :         ReturnErrorOnFailure(tlvReader.Next());
     164              :     }
     165              : 
     166            5 :     if (tlvReader.GetTag() == TLV::ContextTag(Tag::kReleaseNotesURL))
     167              :     {
     168            4 :         ReturnErrorOnFailure(tlvReader.Get(header.mReleaseNotesURL));
     169            4 :         VerifyOrReturnError(header.mReleaseNotesURL.size() <= kMaxReleaseNotesURLSize, CHIP_ERROR_INVALID_STRING_LENGTH);
     170            4 :         ReturnErrorOnFailure(tlvReader.Next());
     171              :     }
     172              : 
     173            5 :     ReturnErrorOnFailure(tlvReader.Expect(TLV::ContextTag(Tag::kImageDigestType)));
     174            5 :     ReturnErrorOnFailure(tlvReader.Get(header.mImageDigestType));
     175            5 :     ReturnErrorOnFailure(tlvReader.Next(TLV::ContextTag(Tag::kImageDigest)));
     176            5 :     ReturnErrorOnFailure(tlvReader.Get(header.mImageDigest));
     177              : 
     178            5 :     ReturnErrorOnFailure(tlvReader.ExitContainer(outerType));
     179              : 
     180            5 :     return CHIP_NO_ERROR;
     181              : }
     182              : 
     183              : } // namespace chip
        

Generated by: LCOV version 2.0-1