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

Generated by: LCOV version 2.0-1