Matter SDK Coverage Report
Current view: top level - lib/core - CASEAuthTag.h (source / functions) Coverage Total Hit
Test: SHA:9f95d758cc04a404d4b85a9e3b8cc2551c3562e3 Lines: 85.1 % 67 57
Test Date: 2025-05-17 07:09:34 Functions: 91.7 % 12 11

            Line data    Source code
       1              : /*
       2              :  *
       3              :  *    Copyright (c) 2021-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              : 
      18              : #pragma once
      19              : 
      20              : #include <array>
      21              : 
      22              : #include <lib/core/CHIPConfig.h>
      23              : #include <lib/core/CHIPEncoding.h>
      24              : #include <lib/core/NodeId.h>
      25              : #include <lib/support/CodeUtils.h>
      26              : 
      27              : namespace chip {
      28              : 
      29              : typedef uint32_t CASEAuthTag;
      30              : 
      31              : static constexpr CASEAuthTag kUndefinedCAT     = 0;
      32              : static constexpr NodeId kTagIdentifierMask     = 0x0000'0000'FFFF'0000ULL;
      33              : static constexpr uint32_t kTagIdentifierShift  = 16;
      34              : static constexpr NodeId kTagVersionMask        = 0x0000'0000'0000'FFFFULL;
      35              : static constexpr uint16_t kAdminCATIdentifier  = 0xFFFF;
      36              : static constexpr uint16_t kAnchorCATIdentifier = 0xFFFE;
      37              : 
      38              : // Maximum number of CASE Authenticated Tags (CAT) in the CHIP certificate subject.
      39              : static constexpr size_t kMaxSubjectCATAttributeCount = CHIP_CONFIG_CERT_MAX_RDN_ATTRIBUTES - 2;
      40              : 
      41              : constexpr NodeId NodeIdFromCASEAuthTag(CASEAuthTag aCAT)
      42              : {
      43              :     return kMinCASEAuthTag | aCAT;
      44              : }
      45              : 
      46          364 : constexpr CASEAuthTag CASEAuthTagFromNodeId(NodeId aNodeId)
      47              : {
      48          364 :     return aNodeId & kMaskCASEAuthTag;
      49              : }
      50              : 
      51          196 : constexpr bool IsValidCASEAuthTag(CASEAuthTag aCAT)
      52              : {
      53          196 :     return (aCAT & kTagVersionMask) > 0;
      54              : }
      55              : 
      56          122 : constexpr uint16_t GetCASEAuthTagIdentifier(CASEAuthTag aCAT)
      57              : {
      58          122 :     return static_cast<uint16_t>((aCAT & kTagIdentifierMask) >> kTagIdentifierShift);
      59              : }
      60              : 
      61          354 : constexpr uint16_t GetCASEAuthTagVersion(CASEAuthTag aCAT)
      62              : {
      63          354 :     return static_cast<uint16_t>(aCAT & kTagVersionMask);
      64              : }
      65              : 
      66              : constexpr CASEAuthTag GetAdminCATWithVersion(uint16_t version)
      67              : {
      68              :     return ((static_cast<uint32_t>(kAdminCATIdentifier) << 16) | version);
      69              : }
      70              : 
      71              : constexpr CASEAuthTag GetAnchorCATWithVersion(uint16_t version)
      72              : {
      73              :     return ((static_cast<uint32_t>(kAnchorCATIdentifier) << 16) | version);
      74              : }
      75              : 
      76              : struct CATValues
      77              : {
      78              :     std::array<CASEAuthTag, kMaxSubjectCATAttributeCount> values = { kUndefinedCAT };
      79              : 
      80              :     /* @brief Returns maximum number of CAT values that the array can contain.
      81              :      */
      82          815 :     static constexpr size_t size() { return std::tuple_size<decltype(values)>::value; }
      83              : 
      84              :     /**
      85              :      * @return the number of CATs present in the set (values not equal to kUndefinedCAT)
      86              :      */
      87          106 :     size_t GetNumTagsPresent() const
      88              :     {
      89          106 :         size_t count = 0;
      90          424 :         for (auto cat : values)
      91              :         {
      92          318 :             count += (cat != kUndefinedCAT) ? 1 : 0;
      93              :         }
      94          106 :         return count;
      95              :     }
      96              : 
      97              :     /**
      98              :      * @return true if `tag` is in the set exactly, false otherwise.
      99              :      */
     100            0 :     bool Contains(CASEAuthTag tag) const
     101              :     {
     102            0 :         for (auto candidate : values)
     103              :         {
     104            0 :             if ((candidate != kUndefinedCAT) && (candidate == tag))
     105              :             {
     106            0 :                 return true;
     107              :             }
     108              :         }
     109              : 
     110            0 :         return false;
     111              :     }
     112              : 
     113          148 :     bool AreValid() const
     114              :     {
     115          589 :         for (size_t idx = 0; idx < size(); ++idx)
     116              :         {
     117          442 :             const auto & candidate = values[idx];
     118          442 :             if (candidate == kUndefinedCAT)
     119              :             {
     120          424 :                 continue;
     121              :             }
     122              : 
     123              :             // Every entry that is not empty must have version > 0
     124           18 :             if (!IsValidCASEAuthTag(candidate))
     125              :             {
     126            0 :                 return false;
     127              :             }
     128              :             // Identifiers cannot collide in set (there cannot be more than 1 version of an identifier)
     129           70 :             for (size_t other_idx = 0; other_idx < size(); ++other_idx)
     130              :             {
     131           53 :                 if (idx == other_idx)
     132              :                 {
     133           18 :                     continue;
     134              :                 }
     135           35 :                 if (values[other_idx] == kUndefinedCAT)
     136              :                 {
     137           14 :                     continue;
     138              :                 }
     139              : 
     140           21 :                 uint16_t other_identifier     = GetCASEAuthTagIdentifier(values[other_idx]);
     141           21 :                 uint16_t candidate_identifier = GetCASEAuthTagIdentifier(candidate);
     142           21 :                 if (other_identifier == candidate_identifier)
     143              :                 {
     144            1 :                     return false;
     145              :                 }
     146              :             }
     147              :         }
     148              : 
     149          147 :         return true;
     150              :     }
     151              : 
     152              :     /**
     153              :      * @brief Returns true if this set contains any version of the `identifier`
     154              :      *
     155              :      * @param identifier - CAT identifier to find
     156              :      * @return true if the identifier is in the set, false otherwise
     157              :      */
     158              :     bool ContainsIdentifier(uint16_t identifier) const
     159              :     {
     160              :         for (auto candidate : values)
     161              :         {
     162              :             uint16_t candidate_identifier = GetCASEAuthTagIdentifier(candidate);
     163              :             if ((candidate != kUndefinedCAT) && (identifier == candidate_identifier))
     164              :             {
     165              :                 return true;
     166              :             }
     167              :         }
     168              : 
     169              :         return false;
     170              :     }
     171              : 
     172              :     /* @brief Returns true if subject input checks against one of the CATs in the values array.
     173              :      */
     174           84 :     bool CheckSubjectAgainstCATs(NodeId subject) const
     175              :     {
     176           84 :         VerifyOrReturnError(IsCASEAuthTag(subject), false);
     177           49 :         CASEAuthTag catFromSubject = CASEAuthTagFromNodeId(subject);
     178              : 
     179          171 :         for (auto catFromNoc : values)
     180              :         {
     181           40 :             if ((catFromNoc != kUndefinedCAT) &&
     182           53 :                 (GetCASEAuthTagIdentifier(catFromNoc) == GetCASEAuthTagIdentifier(catFromSubject)) &&
     183          185 :                 (GetCASEAuthTagVersion(catFromSubject) > 0) &&
     184           13 :                 (GetCASEAuthTagVersion(catFromNoc) >= GetCASEAuthTagVersion(catFromSubject)))
     185              :             {
     186           10 :                 return true;
     187              :             }
     188              :         }
     189           39 :         return false;
     190              :     }
     191              : 
     192           53 :     bool operator==(const CATValues & other) const
     193              :     {
     194              :         // Two sets of CATs confer equal permissions if the sets are exactly equal
     195              :         // and the sets are valid.
     196              :         // Ignoring kUndefinedCAT values, evaluate this.
     197           53 :         if (this->GetNumTagsPresent() != other.GetNumTagsPresent())
     198              :         {
     199            0 :             return false;
     200              :         }
     201           53 :         if (!this->AreValid() || !other.AreValid())
     202              :         {
     203            0 :             return false;
     204              :         }
     205          212 :         for (auto cat : this->values)
     206              :         {
     207          159 :             if (cat == kUndefinedCAT)
     208              :             {
     209          159 :                 continue;
     210              :             }
     211              : 
     212            0 :             if (!other.Contains(cat))
     213              :             {
     214            0 :                 return false;
     215              :             }
     216              :         }
     217           53 :         return true;
     218              :     }
     219              :     bool operator!=(const CATValues & other) const { return !(*this == other); }
     220              : 
     221              :     static constexpr size_t kSerializedLength = kMaxSubjectCATAttributeCount * sizeof(CASEAuthTag);
     222              :     typedef uint8_t Serialized[kSerializedLength];
     223              : 
     224          207 :     CHIP_ERROR Serialize(Serialized & outSerialized) const
     225              :     {
     226          207 :         uint8_t * p = outSerialized;
     227          828 :         for (size_t i = 0; i < kMaxSubjectCATAttributeCount; i++)
     228              :         {
     229          621 :             Encoding::LittleEndian::Write32(p, values[i]);
     230              :         }
     231          207 :         return CHIP_NO_ERROR;
     232              :     }
     233              : 
     234          317 :     CHIP_ERROR Deserialize(const Serialized & inSerialized)
     235              :     {
     236          317 :         const uint8_t * p = inSerialized;
     237         1268 :         for (size_t i = 0; i < kMaxSubjectCATAttributeCount; i++)
     238              :         {
     239          951 :             values[i] = Encoding::LittleEndian::Read32(p);
     240              :         }
     241          317 :         return CHIP_NO_ERROR;
     242              :     }
     243              : };
     244              : 
     245              : static constexpr CATValues kUndefinedCATs = { { kUndefinedCAT } };
     246              : 
     247              : } // namespace chip
        

Generated by: LCOV version 2.0-1