Matter SDK Coverage Report
Current view: top level - credentials - DeviceAttestationConstructor.cpp (source / functions) Coverage Total Hit
Test: SHA:b879ecb8e99e175eea0a293a888bda853da2b19c Lines: 94.6 % 148 140
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              : #include "DeviceAttestationConstructor.h"
      18              : #include "DeviceAttestationVendorReserved.h"
      19              : 
      20              : #include <lib/core/TLV.h>
      21              : #include <lib/support/CodeUtils.h>
      22              : #include <lib/support/logging/CHIPLogging.h>
      23              : 
      24              : #include <cstdint>
      25              : 
      26              : namespace chip {
      27              : namespace Credentials {
      28              : 
      29              : // context tag positions
      30              : enum AttestationInfoId : uint32_t
      31              : {
      32              :     kCertificationDeclarationTagId = 1,
      33              :     kAttestationNonceTagId         = 2,
      34              :     kTimestampTagId                = 3,
      35              :     kFirmwareInfoTagId             = 4,
      36              : };
      37              : 
      38              : enum OperationalCSRInfoId : uint32_t
      39              : {
      40              :     kCsr             = 1,
      41              :     kCsrNonce        = 2,
      42              :     kVendorReserved1 = 3,
      43              :     kVendorReserved2 = 4,
      44              :     kVendorReserved3 = 5,
      45              : };
      46              : 
      47              : // utility to determine number of Vendor Reserved elements in a bytespan
      48           92 : CHIP_ERROR CountVendorReservedElementsInDA(const ByteSpan & attestationElements, size_t & numOfElements)
      49              : {
      50           92 :     TLV::ContiguousBufferTLVReader tlvReader;
      51           92 :     TLV::TLVType containerType = TLV::kTLVType_Structure;
      52              : 
      53           92 :     tlvReader.Init(attestationElements);
      54           92 :     ReturnErrorOnFailure(tlvReader.Next(containerType, TLV::AnonymousTag()));
      55           92 :     ReturnErrorOnFailure(tlvReader.EnterContainer(containerType));
      56              : 
      57           92 :     size_t count = 0;
      58              :     CHIP_ERROR error;
      59          380 :     while ((error = tlvReader.Next()) == CHIP_NO_ERROR)
      60              :     {
      61          288 :         TLV::Tag tag = tlvReader.GetTag();
      62          288 :         if (TLV::IsProfileTag(tag))
      63              :         {
      64           10 :             count++;
      65              :         }
      66              :     }
      67           92 :     VerifyOrReturnError(error == CHIP_NO_ERROR || error == CHIP_END_OF_TLV, error);
      68              : 
      69           92 :     numOfElements = count;
      70           92 :     return CHIP_NO_ERROR;
      71              : }
      72              : 
      73           93 : CHIP_ERROR DeconstructAttestationElements(const ByteSpan & attestationElements, ByteSpan & certificationDeclaration,
      74              :                                           ByteSpan & attestationNonce, uint32_t & timestamp, ByteSpan & firmwareInfo,
      75              :                                           DeviceAttestationVendorReservedDeconstructor & vendorReserved)
      76              : {
      77           93 :     bool certificationDeclarationExists = false;
      78           93 :     bool attestationNonceExists         = false;
      79           93 :     bool timestampExists                = false;
      80           93 :     bool gotFirstContextTag             = false;
      81           93 :     uint32_t lastContextTagId           = 0;
      82              : 
      83           93 :     TLV::ContiguousBufferTLVReader tlvReader;
      84           93 :     TLV::TLVType containerType = TLV::kTLVType_Structure;
      85              : 
      86           93 :     firmwareInfo = ByteSpan();
      87              : 
      88           93 :     tlvReader.Init(attestationElements);
      89           93 :     ReturnErrorOnFailure(tlvReader.Next(containerType, TLV::AnonymousTag()));
      90           93 :     ReturnErrorOnFailure(tlvReader.EnterContainer(containerType));
      91              : 
      92              :     CHIP_ERROR error;
      93              : 
      94              :     // process context tags first (should be in sorted order)
      95          371 :     while ((error = tlvReader.Next()) == CHIP_NO_ERROR)
      96              :     {
      97          284 :         TLV::Tag tag = tlvReader.GetTag();
      98          284 :         if (!TLV::IsContextTag(tag))
      99              :         {
     100            5 :             break;
     101              :         }
     102              : 
     103              :         // Ensure tag-order and correct first expected tag
     104          279 :         uint32_t contextTagId = TLV::TagNumFromTag(tag);
     105          279 :         if (!gotFirstContextTag)
     106              :         {
     107              :             // First tag must always be Certification Declaration
     108           93 :             VerifyOrReturnError(contextTagId == kCertificationDeclarationTagId, CHIP_ERROR_UNEXPECTED_TLV_ELEMENT);
     109           92 :             gotFirstContextTag = true;
     110              :         }
     111              :         else
     112              :         {
     113              :             // Subsequent tags must always be in order
     114          186 :             VerifyOrReturnError(contextTagId > lastContextTagId, CHIP_ERROR_UNEXPECTED_TLV_ELEMENT);
     115              :         }
     116          278 :         lastContextTagId = contextTagId;
     117              : 
     118          278 :         switch (contextTagId)
     119              :         {
     120           92 :         case kCertificationDeclarationTagId:
     121           92 :             ReturnErrorOnFailure(tlvReader.GetByteView(certificationDeclaration));
     122           92 :             certificationDeclarationExists = true;
     123           92 :             break;
     124           92 :         case kAttestationNonceTagId:
     125           92 :             ReturnErrorOnFailure(tlvReader.GetByteView(attestationNonce));
     126           92 :             attestationNonceExists = true;
     127           92 :             break;
     128           92 :         case kTimestampTagId:
     129           92 :             ReturnErrorOnFailure(tlvReader.Get(timestamp));
     130           92 :             timestampExists = true;
     131           92 :             break;
     132            1 :         case kFirmwareInfoTagId:
     133            1 :             ReturnErrorOnFailure(tlvReader.GetByteView(firmwareInfo));
     134            1 :             break;
     135            1 :         default:
     136              :             // It's OK to have future context tags before vendor specific tags.
     137              :             // We already checked that the tags are in order.
     138            1 :             break;
     139              :         }
     140              :     }
     141              : 
     142           92 :     VerifyOrReturnError(error == CHIP_NO_ERROR || error == CHIP_END_OF_TLV, error);
     143              : 
     144           92 :     const bool allTagsNeededPresent = certificationDeclarationExists && attestationNonceExists && timestampExists;
     145           92 :     VerifyOrReturnError(allTagsNeededPresent, CHIP_ERROR_MISSING_TLV_ELEMENT);
     146              : 
     147           92 :     size_t count = 0;
     148           92 :     ReturnErrorOnFailure(CountVendorReservedElementsInDA(attestationElements, count));
     149           92 :     ReturnErrorOnFailure(vendorReserved.PrepareToReadVendorReservedElements(attestationElements, count));
     150           92 :     return CHIP_NO_ERROR;
     151              : }
     152              : 
     153          157 : CHIP_ERROR ConstructAttestationElements(const ByteSpan & certificationDeclaration, const ByteSpan & attestationNonce,
     154              :                                         uint32_t timestamp, const ByteSpan & firmwareInfo,
     155              :                                         DeviceAttestationVendorReservedConstructor & vendorReserved,
     156              :                                         MutableByteSpan & attestationElements)
     157              : {
     158          157 :     TLV::TLVWriter tlvWriter;
     159          157 :     TLV::TLVType outerContainerType = TLV::kTLVType_NotSpecified;
     160              : 
     161          157 :     VerifyOrReturnError(!certificationDeclaration.empty() && !attestationNonce.empty(), CHIP_ERROR_INVALID_ARGUMENT);
     162          155 :     VerifyOrReturnError(attestationNonce.size() == kExpectedAttestationNonceSize, CHIP_ERROR_INVALID_ARGUMENT);
     163              : 
     164          154 :     tlvWriter.Init(attestationElements.data(), static_cast<uint32_t>(attestationElements.size()));
     165          154 :     outerContainerType = TLV::kTLVType_NotSpecified;
     166          154 :     ReturnErrorOnFailure(tlvWriter.StartContainer(TLV::AnonymousTag(), TLV::kTLVType_Structure, outerContainerType));
     167          154 :     ReturnErrorOnFailure(tlvWriter.Put(TLV::ContextTag(1), certificationDeclaration));
     168          154 :     ReturnErrorOnFailure(tlvWriter.Put(TLV::ContextTag(2), attestationNonce));
     169          154 :     ReturnErrorOnFailure(tlvWriter.Put(TLV::ContextTag(3), timestamp));
     170          154 :     if (!firmwareInfo.empty())
     171              :     {
     172            0 :         ReturnErrorOnFailure(tlvWriter.Put(TLV::ContextTag(4), firmwareInfo));
     173              :     }
     174              : 
     175          154 :     const VendorReservedElement * element = vendorReserved.cbegin();
     176          158 :     while ((element = vendorReserved.Next()) != nullptr)
     177              :     {
     178            4 :         ReturnErrorOnFailure(
     179              :             tlvWriter.Put(TLV::ProfileTag(element->vendorId, element->profileNum, element->tagNum), element->vendorReservedData));
     180              :     }
     181              : 
     182          154 :     ReturnErrorOnFailure(tlvWriter.EndContainer(outerContainerType));
     183          154 :     ReturnErrorOnFailure(tlvWriter.Finalize());
     184          154 :     attestationElements = attestationElements.SubSpan(0, tlvWriter.GetLengthWritten());
     185              : 
     186          154 :     VerifyOrReturnError(attestationElements.size() <= Credentials::kMaxRspLen, CHIP_ERROR_MESSAGE_TOO_LONG);
     187              : 
     188          154 :     return CHIP_NO_ERROR;
     189              : }
     190              : 
     191            1 : CHIP_ERROR ConstructNOCSRElements(const ByteSpan & csr, const ByteSpan & csrNonce, const ByteSpan & vendor_reserved1,
     192              :                                   const ByteSpan & vendor_reserved2, const ByteSpan & vendor_reserved3,
     193              :                                   MutableByteSpan & nocsrElements)
     194              : {
     195            1 :     TLV::TLVWriter tlvWriter;
     196            1 :     TLV::TLVType outerContainerType = TLV::kTLVType_NotSpecified;
     197              : 
     198            1 :     VerifyOrReturnError(!csr.empty() && !csrNonce.empty(), CHIP_ERROR_INVALID_ARGUMENT);
     199            1 :     VerifyOrReturnError(csrNonce.size() == kExpectedAttestationNonceSize, CHIP_ERROR_INVALID_ARGUMENT);
     200              : 
     201            1 :     tlvWriter.Init(nocsrElements.data(), static_cast<uint32_t>(nocsrElements.size()));
     202            1 :     outerContainerType = TLV::kTLVType_NotSpecified;
     203            1 :     ReturnErrorOnFailure(tlvWriter.StartContainer(TLV::AnonymousTag(), TLV::kTLVType_Structure, outerContainerType));
     204            1 :     ReturnErrorOnFailure(tlvWriter.Put(TLV::ContextTag(1), csr));
     205            1 :     ReturnErrorOnFailure(tlvWriter.Put(TLV::ContextTag(2), csrNonce));
     206            1 :     if (!vendor_reserved1.empty())
     207              :     {
     208            1 :         ReturnErrorOnFailure(tlvWriter.Put(TLV::ContextTag(3), vendor_reserved1));
     209              :     }
     210            1 :     if (!vendor_reserved2.empty())
     211              :     {
     212            0 :         ReturnErrorOnFailure(tlvWriter.Put(TLV::ContextTag(4), vendor_reserved2));
     213              :     }
     214            1 :     if (!vendor_reserved3.empty())
     215              :     {
     216            1 :         ReturnErrorOnFailure(tlvWriter.Put(TLV::ContextTag(5), vendor_reserved3));
     217              :     }
     218              : 
     219            1 :     ReturnErrorOnFailure(tlvWriter.EndContainer(outerContainerType));
     220            1 :     ReturnErrorOnFailure(tlvWriter.Finalize());
     221            1 :     nocsrElements = nocsrElements.SubSpan(0, tlvWriter.GetLengthWritten());
     222              : 
     223            1 :     VerifyOrReturnError(nocsrElements.size() <= Credentials::kMaxRspLen, CHIP_ERROR_MESSAGE_TOO_LONG);
     224              : 
     225            1 :     return CHIP_NO_ERROR;
     226              : }
     227              : 
     228            3 : CHIP_ERROR DeconstructNOCSRElements(const ByteSpan & nocsrElements, ByteSpan & csr, ByteSpan & csrNonce,
     229              :                                     ByteSpan & vendor_reserved1, ByteSpan & vendor_reserved2, ByteSpan & vendor_reserved3)
     230              : {
     231            3 :     bool csrExists            = false;
     232            3 :     bool csrNonceExists       = false;
     233            3 :     bool gotFirstContextTag   = false;
     234            3 :     uint32_t lastContextTagId = 0;
     235              : 
     236            3 :     TLV::ContiguousBufferTLVReader tlvReader;
     237            3 :     TLV::TLVType containerType = TLV::kTLVType_Structure;
     238              : 
     239              :     // empty out the optional items initially
     240            3 :     vendor_reserved1 = vendor_reserved2 = vendor_reserved3 = ByteSpan();
     241              : 
     242            3 :     tlvReader.Init(nocsrElements);
     243            3 :     ReturnErrorOnFailure(tlvReader.Next(containerType, TLV::AnonymousTag()));
     244            3 :     ReturnErrorOnFailure(tlvReader.EnterContainer(containerType));
     245              : 
     246              :     CHIP_ERROR error;
     247              : 
     248              :     // process context tags first (should be in sorted order)
     249           15 :     while ((error = tlvReader.Next()) == CHIP_NO_ERROR)
     250              :     {
     251           12 :         TLV::Tag tag = tlvReader.GetTag();
     252           12 :         if (!TLV::IsContextTag(tag))
     253              :         {
     254            0 :             break;
     255              :         }
     256              : 
     257              :         // Ensure tag-order and correct first expected tag
     258           12 :         uint32_t contextTagId = TLV::TagNumFromTag(tag);
     259           12 :         if (!gotFirstContextTag)
     260              :         {
     261              :             // First tag must always be CSR
     262            3 :             VerifyOrReturnError(contextTagId == kCsr, CHIP_ERROR_UNEXPECTED_TLV_ELEMENT);
     263            3 :             gotFirstContextTag = true;
     264              :         }
     265              :         else
     266              :         {
     267              :             // Subsequent tags must always be in order
     268            9 :             VerifyOrReturnError(contextTagId > lastContextTagId, CHIP_ERROR_UNEXPECTED_TLV_ELEMENT);
     269              :         }
     270           12 :         lastContextTagId = contextTagId;
     271              : 
     272           12 :         switch (contextTagId)
     273              :         {
     274            3 :         case kCsr:
     275            3 :             ReturnErrorOnFailure(tlvReader.GetByteView(csr));
     276            3 :             csrExists = true;
     277            3 :             break;
     278            3 :         case kCsrNonce:
     279            3 :             ReturnErrorOnFailure(tlvReader.GetByteView(csrNonce));
     280            3 :             csrNonceExists = true;
     281            3 :             break;
     282            3 :         case kVendorReserved1:
     283            3 :             ReturnErrorOnFailure(tlvReader.Get(vendor_reserved1));
     284            3 :             break;
     285            0 :         case kVendorReserved2:
     286            0 :             ReturnErrorOnFailure(tlvReader.Get(vendor_reserved2));
     287            0 :             break;
     288            3 :         case kVendorReserved3:
     289            3 :             ReturnErrorOnFailure(tlvReader.Get(vendor_reserved3));
     290            3 :             break;
     291            0 :         default:
     292              :             // unrecognized TLV element
     293            0 :             return CHIP_ERROR_INVALID_TLV_ELEMENT;
     294              :         }
     295              :     }
     296              : 
     297            3 :     VerifyOrReturnError(error == CHIP_NO_ERROR || error == CHIP_END_OF_TLV, error);
     298              : 
     299            3 :     const bool allTagsNeededPresent = csrExists && csrNonceExists;
     300            3 :     VerifyOrReturnError(allTagsNeededPresent, CHIP_ERROR_MISSING_TLV_ELEMENT);
     301              : 
     302            3 :     return CHIP_NO_ERROR;
     303              : }
     304              : 
     305              : } // namespace Credentials
     306              : 
     307              : } // namespace chip
        

Generated by: LCOV version 2.0-1