Matter SDK Coverage Report
Current view: top level - credentials - DeviceAttestationVendorReserved.h (source / functions) Coverage Total Hit
Test: SHA:b879ecb8e99e175eea0a293a888bda853da2b19c Lines: 57.4 % 54 31
Test Date: 2025-01-17 19:00:11 Functions: 100.0 % 5 5

            Line data    Source code
       1              : /*
       2              :  *
       3              :  *    Copyright (c) 2021 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              : #pragma once
      18              : 
      19              : #include <lib/core/CHIPError.h>
      20              : #include <lib/core/TLV.h>
      21              : #include <lib/support/Span.h>
      22              : 
      23              : #include <cstdint>
      24              : 
      25              : namespace chip {
      26              : namespace Credentials {
      27              : 
      28              : struct VendorReservedElement
      29              : {
      30              :     uint16_t vendorId;
      31              :     uint16_t profileNum;
      32              :     uint32_t tagNum;
      33              :     ByteSpan vendorReservedData;
      34              : };
      35              : 
      36              : // extract elements out of the device attestation bytespan
      37              : class DeviceAttestationVendorReservedDeconstructor
      38              : {
      39              : 
      40              : public:
      41           87 :     DeviceAttestationVendorReservedDeconstructor() {}
      42              : 
      43              :     // Read TLV until first profile tag
      44           87 :     CHIP_ERROR PrepareToReadVendorReservedElements(const ByteSpan & attestationElements, size_t count)
      45              :     {
      46           87 :         mIsInitialized         = false;
      47           87 :         mIsDone                = false;
      48           87 :         mNumVendorReservedData = count;
      49           87 :         mAttestationData       = attestationElements;
      50              : 
      51           87 :         mTlvReader.Init(mAttestationData);
      52           87 :         ReturnErrorOnFailure(mTlvReader.Next(containerType, TLV::AnonymousTag()));
      53           87 :         ReturnErrorOnFailure(mTlvReader.EnterContainer(containerType));
      54              : 
      55              :         // position to first ProfileTag
      56              :         while (true)
      57              :         {
      58          348 :             CHIP_ERROR err = mTlvReader.Next();
      59          348 :             if (err == CHIP_END_OF_TLV)
      60              :             {
      61           86 :                 mIsDone = true;
      62           86 :                 break;
      63              :             }
      64              : 
      65          262 :             ReturnErrorOnFailure(err);
      66              : 
      67          262 :             TLV::Tag tag = mTlvReader.GetTag();
      68          262 :             if (!TLV::IsContextTag(tag))
      69            1 :                 break;
      70          261 :         }
      71              :         // positioned to first non-context tag (vendor reserved data)
      72           87 :         mIsInitialized  = true;
      73           87 :         mIsAtFirstToken = true;
      74           87 :         return CHIP_NO_ERROR;
      75              :     }
      76              : 
      77              :     size_t GetNumberOfElements() const { return mNumVendorReservedData; }
      78              : 
      79              :     /**
      80              :      *  @brief Return next VendorReserved element. PrepareToReadVendorReservedElements must be called first.
      81              :      *
      82              :      *  @param[out] element  Next vendor Reserved element
      83              :      *
      84              :      *  @returns   CHIP_NO_ERROR on success
      85              :      *             CHIP_ERROR_INCORRECT_STATE if PrepareToReadVendorReservedElements hasn't been called first
      86              :      *             CHIP_ERROR_UNEXPECTED_TLV_ELEMENT if we reach non-profile-specific tags or vendorId is zero
      87              :      *             CHIP_END_OF_TLV if not further entries are present
      88              :      */
      89              :     CHIP_ERROR GetNextVendorReservedElement(struct VendorReservedElement & element)
      90              :     {
      91              :         VerifyOrReturnError(mIsInitialized, CHIP_ERROR_UNINITIALIZED);
      92              :         if (mIsDone)
      93              :         {
      94              :             return CHIP_END_OF_TLV;
      95              :         }
      96              : 
      97              :         if (mIsAtFirstToken)
      98              :         {
      99              :             // Already had a Next() done for us by PrepareToReadVendorReservedElements
     100              :             // so we don't Next() since we should be pointing at a vendor-reserved.
     101              :             mIsAtFirstToken = false;
     102              :         }
     103              :         else
     104              :         {
     105              :             CHIP_ERROR error = mTlvReader.Next();
     106              :             if (error == CHIP_END_OF_TLV)
     107              :             {
     108              :                 mIsDone = true;
     109              :             }
     110              :             ReturnErrorOnFailure(error);
     111              :         }
     112              : 
     113              :         TLV::Tag tag = mTlvReader.GetTag();
     114              :         if (!TLV::IsProfileTag(tag))
     115              :         {
     116              :             return CHIP_ERROR_UNEXPECTED_TLV_ELEMENT;
     117              :         }
     118              : 
     119              :         // tag is profile tag
     120              :         element.vendorId   = TLV::VendorIdFromTag(tag);
     121              :         element.profileNum = TLV::ProfileNumFromTag(tag);
     122              :         element.tagNum     = TLV::TagNumFromTag(tag);
     123              : 
     124              :         ReturnErrorOnFailure(mTlvReader.GetByteView(element.vendorReservedData));
     125              : 
     126              :         return CHIP_NO_ERROR;
     127              :     }
     128              : 
     129              : private:
     130              :     size_t mNumVendorReservedData; // number of VendorReserved entries (could be 0)
     131              :     ByteSpan mAttestationData;
     132              :     bool mIsInitialized  = false;
     133              :     bool mIsAtFirstToken = false;
     134              :     bool mIsDone         = false;
     135              :     TLV::ContiguousBufferTLVReader mTlvReader;
     136              :     TLV::TLVType containerType = TLV::kTLVType_Structure;
     137              : };
     138              : 
     139              : class DeviceAttestationVendorReservedConstructor
     140              : {
     141              : public:
     142              :     DeviceAttestationVendorReservedConstructor(struct VendorReservedElement * array, size_t size) : mElements(array), mMaxSize(size)
     143              :     {}
     144              : 
     145              :     typedef const struct VendorReservedElement * const_iterator;
     146              : 
     147          152 :     const_iterator Next()
     148              :     {
     149          152 :         VerifyOrReturnError(mCurrentIndex < mNumEntriesUsed, nullptr);
     150            0 :         return &mElements[mCurrentIndex++];
     151              :     }
     152              : 
     153          152 :     const_iterator cbegin()
     154              :     {
     155              :         // sort the array in place and return the head element.
     156          152 :         do_sorting();
     157          152 :         mCurrentIndex = 0;
     158          152 :         return mElements;
     159              :     }
     160              : 
     161              :     CHIP_ERROR addVendorReservedElement(uint16_t vendorId, uint16_t profileNum, uint32_t tagNum, ByteSpan span)
     162              :     {
     163              :         if (mNumEntriesUsed == mMaxSize)
     164              :             return CHIP_ERROR_NO_MEMORY;
     165              : 
     166              :         mElements[mNumEntriesUsed].tagNum             = tagNum;
     167              :         mElements[mNumEntriesUsed].profileNum         = profileNum;
     168              :         mElements[mNumEntriesUsed].vendorId           = vendorId;
     169              :         mElements[mNumEntriesUsed].vendorReservedData = span;
     170              :         mNumEntriesUsed++;
     171              :         return CHIP_NO_ERROR;
     172              :     }
     173              : 
     174              :     size_t GetNumberOfElements() const { return mNumEntriesUsed; }
     175              : 
     176              : private:
     177              :     /*
     178              :      * Sort according to A.2.4 in the spec.
     179              :      * Mark all sorted entries by setting used flag.
     180              :      * Order is head to tail, sorted by next
     181              :      * Executed when entries are about to be read
     182              :      */
     183          152 :     void do_sorting()
     184              :     {
     185          152 :         size_t starting = 0;
     186              : 
     187          152 :         while (starting < mNumEntriesUsed)
     188              :         {
     189            0 :             uint32_t minVendor = UINT32_MAX;
     190              : 
     191              :             // find lowest vendorId
     192              :             size_t i;
     193            0 :             for (i = starting; i < mNumEntriesUsed; i++)
     194              :             {
     195            0 :                 if (mElements[i].vendorId < minVendor)
     196              :                 {
     197            0 :                     minVendor = mElements[i].vendorId;
     198              :                 }
     199              :             }
     200              : 
     201            0 :             uint32_t minProfile = UINT32_MAX;
     202              :             // find lowest ProfileNum
     203            0 :             for (i = starting; i < mNumEntriesUsed; i++)
     204              :             {
     205            0 :                 if (mElements[i].vendorId == minVendor)
     206              :                 {
     207            0 :                     if (mElements[i].profileNum < minProfile)
     208            0 :                         minProfile = mElements[i].profileNum;
     209              :                 }
     210              :             }
     211              : 
     212              :             // first lowest tagNum for this vendorId/profileNum
     213            0 :             uint64_t minTagNum = UINT64_MAX;
     214            0 :             size_t lowestIndex = SIZE_MAX;
     215            0 :             for (i = starting; i < mNumEntriesUsed; i++)
     216              :             {
     217            0 :                 if (mElements[i].vendorId == minVendor && mElements[i].profileNum == minProfile)
     218              :                 {
     219            0 :                     if (mElements[i].tagNum < minTagNum)
     220              :                     {
     221            0 :                         minTagNum   = mElements[i].tagNum;
     222            0 :                         lowestIndex = i;
     223              :                     }
     224              :                 }
     225              :             }
     226              : 
     227              :             // lowestIndex is the element to move into elements[starting].
     228            0 :             if (lowestIndex != starting)
     229              :             {
     230              :                 //
     231            0 :                 VendorReservedElement tmpElement;
     232              : 
     233            0 :                 tmpElement             = mElements[starting];
     234            0 :                 mElements[starting]    = mElements[lowestIndex];
     235            0 :                 mElements[lowestIndex] = tmpElement;
     236              :             }
     237            0 :             starting++;
     238              :         }
     239          152 :     }
     240              : 
     241              :     VendorReservedElement * mElements;
     242              :     size_t mMaxSize;            // size of elements array
     243              :     size_t mNumEntriesUsed = 0; // elements used
     244              :     size_t mCurrentIndex;       // iterating from [0...maxSize -1]
     245              : };
     246              : 
     247              : } // namespace Credentials
     248              : } // namespace chip
        

Generated by: LCOV version 2.0-1