Matter SDK Coverage Report
Current view: top level - credentials - GroupDataProvider.h (source / functions) Coverage Total Hit
Test: SHA:704d97f9c619242ad76fcf75aeabc67802fa72d4 Lines: 100.0 % 95 95
Test Date: 2026-05-18 07:37:39 Functions: 94.7 % 38 36

            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              : #pragma once
      18              : 
      19              : #include <optional>
      20              : #include <stdint.h>
      21              : #include <sys/types.h>
      22              : 
      23              : #include <app/util/basic-types.h>
      24              : #include <crypto/CHIPCryptoPAL.h>
      25              : #include <lib/core/CHIPError.h>
      26              : #include <lib/core/ClusterEnums.h>
      27              : #include <lib/support/CHIPMemString.h>
      28              : #include <lib/support/CommonIterator.h>
      29              : 
      30              : namespace chip {
      31              : namespace Credentials {
      32              : 
      33              : class GroupDataProvider
      34              : {
      35              : public:
      36              :     using SecurityPolicy                                  = app::Clusters::GroupKeyManagement::GroupKeySecurityPolicyEnum;
      37              :     static constexpr KeysetId kIdentityProtectionKeySetId = 0;
      38              :     static constexpr size_t kMaxListeners                 = 2;
      39              : 
      40              :     struct GroupInfo
      41              :     {
      42              :         static constexpr size_t kGroupNameMax = CHIP_CONFIG_MAX_GROUP_NAME_LENGTH;
      43              :         enum class Flags : uint8_t
      44              :         {
      45              :             kHasAuxiliaryACL = 0b00000001,
      46              :             kMcastAddrPolicy = 0b00000010,
      47              :         };
      48              :         static constexpr uint8_t kFlagsDefault = to_underlying(GroupInfo::Flags::kMcastAddrPolicy);
      49              : 
      50              :         // Identifies group within the scope of the given Fabric
      51              :         GroupId group_id = kUndefinedGroupId;
      52              :         // Lastest group name written for a given GroupId on any Endpoint via the Groups cluster
      53              :         char name[kGroupNameMax + 1] = { 0 };
      54              :         uint8_t flags                = kFlagsDefault;
      55              :         uint16_t count               = 0;
      56              : 
      57         2939 :         GroupInfo() { SetName(nullptr); }
      58            6 :         GroupInfo(const GroupInfo & other) { Copy(other); }
      59         2362 :         GroupInfo(const char * groupName) { SetName(groupName); }
      60              :         GroupInfo(const CharSpan & groupName) { SetName(groupName); }
      61         5838 :         GroupInfo(GroupId id, const char * groupName, uint8_t groupFlags = kFlagsDefault) : group_id(id), flags(groupFlags)
      62              :         {
      63         5838 :             SetName(groupName);
      64         5838 :         }
      65           31 :         GroupInfo(GroupId id, const CharSpan & groupName, uint8_t groupFlags = kFlagsDefault) : group_id(id), flags(groupFlags)
      66              :         {
      67           31 :             SetName(groupName);
      68           31 :         }
      69        16030 :         void SetName(const char * groupName)
      70              :         {
      71        16030 :             if (nullptr == groupName)
      72              :             {
      73        10942 :                 name[0] = 0;
      74              :             }
      75              :             else
      76              :             {
      77         5088 :                 Platform::CopyString(name, groupName);
      78              :             }
      79        16030 :         }
      80         8927 :         void SetName(const CharSpan & groupName)
      81              :         {
      82         8927 :             if (nullptr == groupName.data())
      83              :             {
      84         8897 :                 name[0] = 0;
      85              :             }
      86              :             else
      87              :             {
      88           30 :                 Platform::CopyString(name, groupName);
      89              :             }
      90         8927 :         }
      91         4883 :         void Copy(const GroupInfo & other)
      92              :         {
      93         4883 :             if (this != &other)
      94              :             {
      95         4883 :                 group_id = other.group_id;
      96         4883 :                 flags    = other.flags;
      97         4883 :                 SetName(other.name);
      98              :             }
      99         4883 :         }
     100         1122 :         bool HasAuxiliaryACL() const { return (flags & static_cast<uint8_t>(Flags::kHasAuxiliaryACL)); }
     101         4023 :         bool UsePerGroupAddress() const { return (flags & static_cast<uint8_t>(Flags::kMcastAddrPolicy)); }
     102              : 
     103           32 :         bool operator==(const GroupInfo & other) const
     104              :         {
     105           32 :             return (this->group_id == other.group_id) && !strncmp(this->name, other.name, kGroupNameMax);
     106              :         }
     107            1 :         GroupInfo & operator=(const GroupInfo & other)
     108              :         {
     109            1 :             Copy(other);
     110            1 :             return *this;
     111              :         }
     112              :     };
     113              : 
     114              :     struct GroupKey
     115              :     {
     116           68 :         GroupKey() = default;
     117         1045 :         GroupKey(GroupId group, KeysetId keyset) : group_id(group), keyset_id(keyset) {}
     118              :         // Identifies group within the scope of the given Fabric
     119              :         GroupId group_id = kUndefinedGroupId;
     120              :         // Set of group keys that generate operational group keys for use with this group
     121              :         KeysetId keyset_id = 0;
     122           28 :         bool operator==(const GroupKey & other) const
     123              :         {
     124           28 :             return this->group_id == other.group_id && this->keyset_id == other.keyset_id;
     125              :         }
     126              :     };
     127              : 
     128              :     struct GroupEndpoint
     129              :     {
     130         1425 :         GroupEndpoint() = default;
     131         2205 :         GroupEndpoint(GroupId group, EndpointId endpoint) : group_id(group), endpoint_id(endpoint) {}
     132              :         // Identifies group within the scope of the given Fabric
     133              :         GroupId group_id = kUndefinedGroupId;
     134              :         // Endpoint on the Node to which messages to this group may be forwarded
     135              :         EndpointId endpoint_id = kInvalidEndpointId;
     136              : 
     137              :         bool operator==(const GroupEndpoint & other) const
     138              :         {
     139              :             return this->group_id == other.group_id && this->endpoint_id == other.endpoint_id;
     140              :         }
     141              :     };
     142              : 
     143              :     struct GroupSession
     144              :     {
     145           10 :         GroupSession()   = default;
     146              :         GroupId group_id = kUndefinedGroupId;
     147              :         FabricIndex fabric_index;
     148              :         SecurityPolicy security_policy;
     149              :         Crypto::SymmetricKeyContext * keyContext = nullptr;
     150              :     };
     151              : 
     152              :     // An EpochKey is a single key usable to determine an operational group key
     153              :     struct EpochKey
     154              :     {
     155              :         static constexpr size_t kLengthBytes = Crypto::CHIP_CRYPTO_SYMMETRIC_KEY_LENGTH_BYTES;
     156              :         // Validity start time in microseconds since 2000-01-01T00:00:00 UTC ("the Epoch")
     157              :         uint64_t start_time;
     158              :         // Actual key bits. Depending on context, it may be a raw epoch key (as seen within `SetKeySet` calls)
     159              :         // or it may be the derived operational group key (as seen in any other usage).
     160              :         uint8_t key[kLengthBytes];
     161              : 
     162         1773 :         void Clear()
     163              :         {
     164         1773 :             start_time = 0;
     165         1773 :             Crypto::ClearSecretData(&key[0], sizeof(key));
     166         1773 :         }
     167              :     };
     168              : 
     169              :     // A operational group key set, usable by many GroupState mappings
     170              :     struct KeySet
     171              :     {
     172              :         static constexpr size_t kEpochKeysMax = 3;
     173              : 
     174          187 :         KeySet() { ClearKeys(); }
     175          210 :         KeySet(uint16_t id, SecurityPolicy policy_id, uint8_t num_keys) : keyset_id(id), policy(policy_id), num_keys_used(num_keys)
     176              :         {
     177          210 :             ClearKeys();
     178          210 :         }
     179              : 
     180              :         // The actual keys for the group key set
     181              :         EpochKey epoch_keys[kEpochKeysMax];
     182              :         // Logical id provided by the Administrator that configured the entry
     183              :         uint16_t keyset_id = 0;
     184              :         // Security policy to use for groups that use this keyset
     185              :         SecurityPolicy policy = SecurityPolicy::kCacheAndSync;
     186              :         // Number of keys present
     187              :         uint8_t num_keys_used = 0;
     188              : 
     189              :         bool operator==(const KeySet & other) const
     190              :         {
     191              :             VerifyOrReturnError(this->policy == other.policy && this->num_keys_used == other.num_keys_used, false);
     192              :             return !memcmp(this->epoch_keys, other.epoch_keys, this->num_keys_used * sizeof(EpochKey));
     193              :         }
     194              : 
     195          564 :         void ClearKeys()
     196              :         {
     197         2256 :             for (size_t key_idx = 0; key_idx < kEpochKeysMax; ++key_idx)
     198              :             {
     199         1692 :                 epoch_keys[key_idx].Clear();
     200              :             }
     201          564 :         }
     202              :     };
     203              : 
     204              :     /**
     205              :      *  Interface to listen for changes in the Group info.
     206              :      */
     207              :     class GroupListener
     208              :     {
     209              :     public:
     210          173 :         virtual ~GroupListener() = default;
     211              :         /**
     212              :          *  Callback invoked when a new group is added.
     213              :          *
     214              :          *  @param[in] new_group  GroupInfo structure of the new group.
     215              :          */
     216              :         virtual void OnGroupAdded(FabricIndex fabric_index, const GroupInfo & new_group) = 0;
     217              :         /**
     218              :          *  Callback invoked when an existing group is removed.
     219              :          *
     220              :          *  @param[in] old_group  GroupInfo structure of the removed group.
     221              :          */
     222              :         virtual void OnGroupRemoved(FabricIndex fabric_index, const GroupInfo & old_group) = 0;
     223              :         /**
     224              :          *  Callback invoked when an existing group is modified.
     225              :          *  The modifications may be any of the following:
     226              :          *  - Endpoints List modified
     227              :          *  - KeySetID modified
     228              :          *  - Flags modified (kHasAuxiliaryACL or kMcastAddrPolicy)
     229              :          *
     230              :          * Note that this callback is not invoked when the group is added or removed.
     231              :          * Those events are handled by the OnGroupAdded and OnGroupRemoved callbacks respectively.
     232              :          *
     233              :          *  @param[in] modified_group_id  ID of the modified group.
     234              :          */
     235           84 :         virtual void OnGroupModified(FabricIndex fabric_index, const GroupId & modified_group_id){};
     236              :     };
     237              : 
     238              :     using GroupInfoIterator    = CommonIterator<GroupInfo>;
     239              :     using GroupKeyIterator     = CommonIterator<GroupKey>;
     240              :     using EndpointIterator     = CommonIterator<GroupEndpoint>;
     241              :     using KeySetIterator       = CommonIterator<KeySet>;
     242              :     using GroupSessionIterator = CommonIterator<GroupSession>;
     243              : 
     244           97 :     GroupDataProvider(uint16_t maxGroupsPerFabric, uint16_t maxGroupKeysPerFabric) :
     245           97 :         mMaxGroupsPerFabric(maxGroupsPerFabric), mMaxGroupKeysPerFabric(maxGroupKeysPerFabric)
     246           97 :     {}
     247              : 
     248              :     enum class GroupCleanupPolicy
     249              :     {
     250              :         kDeleteGroupIfEmpty, // Default behavior for legacy Groups
     251              :         kKeepGroupIfEmpty    // Required for Groupcast Sender feature
     252              :     };
     253              : 
     254           97 :     virtual ~GroupDataProvider() = default;
     255              : 
     256              :     // Not copyable
     257              :     GroupDataProvider(const GroupDataProvider &)             = delete;
     258              :     GroupDataProvider & operator=(const GroupDataProvider &) = delete;
     259              : 
     260              :     // TODO(#72056): Once groupcast is enabled by default, this should just return mMaxGroupsPerFabric. See GroupDataProviderImpl()
     261              :     // constructor.
     262          730 :     uint16_t GetMaxGroupsPerFabric() const
     263              :     {
     264          730 :         return static_cast<uint16_t>(IsGroupcastEnabled() ? (getMaxMembershipCount() / 2) : mMaxGroupsPerFabric);
     265              :     }
     266            8 :     uint16_t GetMaxGroupKeysPerFabric() const { return mMaxGroupKeysPerFabric; }
     267              : 
     268              :     /**
     269              :      *  Initialize the GroupDataProvider, including possibly any persistent
     270              :      *  data store initialization done by the implementation. Must be called once
     271              :      *  before any other API succeeds.
     272              :      *
     273              :      *  @retval #CHIP_ERROR_INCORRECT_STATE if called when already initialized.
     274              :      *  @retval #CHIP_NO_ERROR on success
     275              :      */
     276              :     virtual CHIP_ERROR Init() = 0;
     277              :     virtual void Finish()     = 0;
     278              : 
     279              :     //
     280              :     // Group Table
     281              :     //
     282              : 
     283              :     // By id
     284              :     virtual CHIP_ERROR SetGroupInfo(FabricIndex fabric_index, const GroupInfo & info)             = 0;
     285              :     virtual CHIP_ERROR GetGroupInfo(FabricIndex fabric_index, GroupId group_id, GroupInfo & info) = 0;
     286              :     virtual CHIP_ERROR RemoveGroupInfo(FabricIndex fabric_index, GroupId group_id)                = 0;
     287              :     // By index
     288              :     virtual CHIP_ERROR SetGroupInfoAt(FabricIndex fabric_index, size_t index, const GroupInfo & info) = 0;
     289              :     virtual CHIP_ERROR GetGroupInfoAt(FabricIndex fabric_index, size_t index, GroupInfo & info)       = 0;
     290              :     virtual CHIP_ERROR RemoveGroupInfoAt(FabricIndex fabric_index, size_t index)                      = 0;
     291              :     // Endpoints
     292              :     virtual bool HasEndpoint(FabricIndex fabric_index, GroupId group_id, EndpointId endpoint_id)          = 0;
     293              :     virtual CHIP_ERROR AddEndpoint(FabricIndex fabric_index, GroupId group_id, EndpointId endpoint_id)    = 0;
     294              :     virtual CHIP_ERROR RemoveEndpoint(FabricIndex fabric_index, GroupId group_id, EndpointId endpoint_id,
     295              :                                       GroupCleanupPolicy cleanupPolicy)                                   = 0;
     296              :     virtual CHIP_ERROR RemoveEndpointAllGroups(FabricIndex fabric_index, EndpointId endpoint_id,
     297              :                                                GroupCleanupPolicy cleanupPolicy)                          = 0;
     298              :     virtual CHIP_ERROR RemoveEndpoint(FabricIndex fabric_index, GroupId group_id, EndpointId endpoint_id) = 0;
     299              :     virtual CHIP_ERROR RemoveEndpoint(FabricIndex fabric_index, EndpointId endpoint_id)                   = 0;
     300              :     virtual CHIP_ERROR RemoveEndpoints(FabricIndex fabric_index, GroupId group_id)                        = 0;
     301              :     // Iterators
     302              :     /**
     303              :      *  Creates an iterator that may be used to obtain the list of groups associated with the given fabric.
     304              :      *  In order to release the allocated memory, the Release() method must be called after the iteration is finished.
     305              :      *  Modifying the group table during the iteration is currently not supported, and may yield unexpected behaviour.
     306              :      *  @retval An instance of EndpointIterator on success
     307              :      *  @retval nullptr if no iterator instances are available.
     308              :      */
     309              :     virtual GroupInfoIterator * IterateGroupInfo(FabricIndex fabric_index) = 0;
     310              :     /**
     311              :      *  Creates an iterator that may be used to obtain the list of (group, endpoint) pairs associated with the given fabric.
     312              :      *  In order to release the allocated memory, the Release() method must be called after the iteration is finished.
     313              :      *  Modifying the group table during the iteration is currently not supported, and may yield unexpected behaviour.
     314              :      *  If you wish to iterate only the endpoints of a particular group id you can provide the optional `group_id` to do so.
     315              :      *  @retval An instance of EndpointIterator on success
     316              :      *  @retval nullptr if no iterator instances are available.
     317              :      */
     318              :     virtual EndpointIterator * IterateEndpoints(FabricIndex fabric_index, std::optional<GroupId> group_id = std::nullopt) = 0;
     319              : 
     320              :     //
     321              :     // Group-Key map
     322              :     //
     323              : 
     324              :     virtual CHIP_ERROR SetGroupKey(FabricIndex fabric_index, GroupId group_id, KeysetId keyset_id)   = 0;
     325              :     virtual CHIP_ERROR SetGroupKeyAt(FabricIndex fabric_index, size_t index, const GroupKey & info)  = 0;
     326              :     virtual CHIP_ERROR GetGroupKey(FabricIndex fabric_index, GroupId group_id, KeysetId & keyset_id) = 0;
     327              :     virtual CHIP_ERROR GetGroupKeyAt(FabricIndex fabric_index, size_t index, GroupKey & info)        = 0;
     328              :     virtual CHIP_ERROR RemoveGroupKeyAt(FabricIndex fabric_index, size_t index)                      = 0;
     329              :     virtual CHIP_ERROR RemoveGroupKeys(FabricIndex fabric_index)                                     = 0;
     330              : 
     331              :     /**
     332              :      *  Creates an iterator that may be used to obtain the list of (group, keyset) pairs associated with the given fabric.
     333              :      *  In order to release the allocated memory, the Release() method must be called after the iteration is finished.
     334              :      *  Modifying the keyset mappings during the iteration is currently not supported, and may yield unexpected behaviour.
     335              :      *  @retval An instance of GroupKeyIterator on success
     336              :      *  @retval nullptr if no iterator instances are available.
     337              :      */
     338              :     virtual GroupKeyIterator * IterateGroupKeys(FabricIndex fabric_index) = 0;
     339              : 
     340              :     //
     341              :     // Key Sets
     342              :     //
     343              : 
     344              :     virtual CHIP_ERROR SetKeySet(FabricIndex fabric_index, const ByteSpan & compressed_fabric_id, const KeySet & keys) = 0;
     345              :     virtual CHIP_ERROR GetKeySet(FabricIndex fabric_index, KeysetId keyset_id, KeySet & keys)                          = 0;
     346              :     virtual CHIP_ERROR RemoveKeySet(FabricIndex fabric_index, KeysetId keyset_id)                                      = 0;
     347              : 
     348              :     /**
     349              :      * @brief Obtain the actual operational Identity Protection Key (IPK) keyset for a given
     350              :      *        fabric. These keys are used by the CASE protocol, and do not participate in
     351              :      *        any direct traffic encryption. Since the identity protection operational keyset
     352              :      *        is used in multiple key derivations and procedures, it cannot be hidden behind a
     353              :      *        SymmetricKeyContext, and must be obtainable by value.
     354              :      *
     355              :      * @param fabric_index - Fabric index for which to get the IPK operational keyset
     356              :      * @param out_keyset - Reference to a KeySet where the IPK keys will be stored on success
     357              :      * @return CHIP_NO_ERROR on success, CHIP_ERROR_NOT_FOUND if the IPK keyset is somehow unavailable
     358              :      *         or another CHIP_ERROR value if an internal storage error occurs.
     359              :      */
     360              :     virtual CHIP_ERROR GetIpkKeySet(FabricIndex fabric_index, KeySet & out_keyset) = 0;
     361              : 
     362              :     /**
     363              :      *  Creates an iterator that may be used to obtain the list of key sets associated with the given fabric.
     364              :      *  In order to release the allocated memory, the Release() method must be called after the iteration is finished.
     365              :      *  Modifying the key sets table during the iteration is currently not supported, and may yield unexpected behaviour.
     366              :      *
     367              :      *  @retval An instance of KeySetIterator on success
     368              :      *  @retval nullptr if no iterator instances are available.
     369              :      */
     370              :     virtual KeySetIterator * IterateKeySets(FabricIndex fabric_index) = 0;
     371              : 
     372              :     // Fabrics
     373              :     virtual CHIP_ERROR RemoveFabric(FabricIndex fabric_index) = 0;
     374              : 
     375              :     // Decryption
     376              :     virtual GroupSessionIterator * IterateGroupSessions(uint16_t session_id)                        = 0;
     377              :     virtual Crypto::SymmetricKeyContext * GetKeyContext(FabricIndex fabric_index, GroupId group_id) = 0;
     378              : 
     379              :     // Listener
     380           35 :     void SetListener(GroupListener * listener)
     381              :     {
     382           53 :         for (size_t i = 0; listener && (i < kMaxListeners); ++i)
     383              :         {
     384           52 :             if (nullptr == mListeners[i])
     385              :             {
     386           34 :                 mListeners[i] = listener;
     387           34 :                 return;
     388              :             }
     389              :         }
     390              :     }
     391           33 :     void RemoveListener(GroupListener * listener)
     392              :     {
     393           51 :         for (size_t i = 0; listener && (i < kMaxListeners); ++i)
     394              :         {
     395           50 :             if (listener == mListeners[i])
     396              :             {
     397           32 :                 mListeners[i] = nullptr;
     398           32 :                 return;
     399              :             }
     400              :         }
     401              :     }
     402              : 
     403           17 :     void SetGroupcastEnabled(bool groupcastVal) { mGroupcastEnabled = groupcastVal; }
     404              : 
     405         2220 :     bool IsGroupcastEnabled() const { return mGroupcastEnabled; }
     406              : 
     407              :     // Groupcast
     408              :     virtual uint16_t getMaxMembershipCount() const = 0;
     409              :     virtual uint16_t getMaxMcastAddrCount() const  = 0;
     410              : 
     411              :     /**
     412              :      * @brief Check if a notification is needed for Auxiliary ACL changes and reset the flag.
     413              :      *
     414              :      * This method returns true if the last set of operations (e.g., SetGroupInfo, RemoveGroupInfo)
     415              :      * somehow changed the Auxiliary ACL status of a group. Calling this method resets the internal flag.
     416              :      *
     417              :      * @return true if a notification is needed, false otherwise.
     418              :      */
     419              :     virtual bool ConsumeAuxAclNotificationNeeded() = 0;
     420              : 
     421              : protected:
     422          314 :     void GroupAdded(FabricIndex fabric_index, const GroupInfo & new_group)
     423              :     {
     424          942 :         for (auto * listener : mListeners)
     425              :         {
     426          628 :             if (listener != nullptr)
     427              :             {
     428          146 :                 listener->OnGroupAdded(fabric_index, new_group);
     429              :             }
     430              :         }
     431          314 :     }
     432           67 :     void GroupRemoved(FabricIndex fabric_index, const GroupInfo & old_group)
     433              :     {
     434          201 :         for (auto * listener : mListeners)
     435              :         {
     436          134 :             if (listener != nullptr)
     437              :             {
     438           68 :                 listener->OnGroupRemoved(fabric_index, old_group);
     439              :             }
     440              :         }
     441           67 :     }
     442         1638 :     void GroupModified(FabricIndex fabric_index, const GroupId & modified_group_id)
     443              :     {
     444         4914 :         for (auto * listener : mListeners)
     445              :         {
     446         3276 :             if (listener != nullptr)
     447              :             {
     448         2280 :                 listener->OnGroupModified(fabric_index, modified_group_id);
     449              :             }
     450              :         }
     451         1638 :     }
     452              :     const uint16_t mMaxGroupsPerFabric;
     453              :     const uint16_t mMaxGroupKeysPerFabric;
     454              :     GroupListener * mListeners[kMaxListeners] = { nullptr };
     455              :     bool mGroupcastEnabled                    = false;
     456              : };
     457              : 
     458              : /**
     459              :  * @brief Utility Set the IPK Epoch key on a GroupDataProvider assuming a single IPK
     460              :  *
     461              :  * This utility replaces having to call `GroupDataProvider::SetKeySet` for the simple situation of a
     462              :  * single IPK for a fabric, if a single epoch key is used. Start time will be set to 0 ("was always valid")
     463              :  *
     464              :  * @param provider - pointer to GroupDataProvider on which to set the IPK
     465              :  * @param fabric_index - fabric index within the GroupDataProvider for which to set the IPK
     466              :  * @param ipk_epoch_span - Span containing the IPK epoch key
     467              :  * @param compressed_fabric_id - Compressed fabric ID associated with the fabric, for key derivation
     468              :  * @return CHIP_NO_ERROR on success, CHIP_ERROR_INVALID_ARGUMENT on any bad argument, other CHIP_ERROR values
     469              :  *         from implementation on other errors
     470              :  */
     471            1 : inline CHIP_ERROR SetSingleIpkEpochKey(GroupDataProvider * provider, FabricIndex fabric_index, const ByteSpan & ipk_epoch_span,
     472              :                                        const ByteSpan & compressed_fabric_id)
     473              : {
     474              :     GroupDataProvider::KeySet ipkKeySet(GroupDataProvider::kIdentityProtectionKeySetId,
     475            1 :                                         GroupDataProvider::SecurityPolicy::kTrustFirst, 1);
     476              : 
     477            1 :     VerifyOrReturnError(provider != nullptr, CHIP_ERROR_INVALID_ARGUMENT);
     478            1 :     VerifyOrReturnError(ipk_epoch_span.size() == sizeof(ipkKeySet.epoch_keys[0].key), CHIP_ERROR_INVALID_ARGUMENT);
     479            1 :     VerifyOrReturnError(compressed_fabric_id.size() == sizeof(uint64_t), CHIP_ERROR_INVALID_ARGUMENT);
     480              : 
     481            1 :     ipkKeySet.epoch_keys[0].start_time = 0;
     482            1 :     memcpy(&ipkKeySet.epoch_keys[0].key, ipk_epoch_span.data(), ipk_epoch_span.size());
     483              : 
     484              :     // Set a single IPK, validate key derivation follows spec
     485            1 :     return provider->SetKeySet(fabric_index, compressed_fabric_id, ipkKeySet);
     486              : }
     487              : 
     488              : /**
     489              :  * Instance getter for the global GroupDataProvider.
     490              :  *
     491              :  * Callers have to externally synchronize usage of this function.
     492              :  *
     493              :  * @return The global Group Data Provider
     494              :  */
     495              : GroupDataProvider * GetGroupDataProvider();
     496              : 
     497              : /**
     498              :  * Instance setter for the global GroupDataProvider.
     499              :  *
     500              :  * Callers have to externally synchronize usage of this function.
     501              :  *
     502              :  * The `provider` can be set to nullptr if the owner is done with it fully.
     503              :  *
     504              :  * @param[in] provider pointer to the Group Data Provider global isntance to use
     505              :  */
     506              : void SetGroupDataProvider(GroupDataProvider * provider);
     507              : 
     508              : } // namespace Credentials
     509              : } // namespace chip
        

Generated by: LCOV version 2.0-1