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 <credentials/GroupDataProvider.h>
20 : #include <crypto/SessionKeystore.h>
21 : #include <lib/core/CHIPPersistentStorageDelegate.h>
22 : #include <lib/support/Pool.h>
23 :
24 : namespace chip {
25 : namespace Credentials {
26 :
27 : class GroupDataProviderImpl : public GroupDataProvider
28 : {
29 : public:
30 : static constexpr size_t kIteratorsMax = CHIP_CONFIG_MAX_GROUP_CONCURRENT_ITERATORS;
31 : static constexpr uint16_t kMaxMembershipCount = CHIP_CONFIG_MAX_GROUPCAST_MEMBERSHIP_COUNT;
32 : // Per spec, a single fabric cannot use more than half of the total memberships
33 : static constexpr uint16_t kMaxMembershipPerFabric = kMaxMembershipCount / 2;
34 : static constexpr uint16_t kMaxGroupKeysPerFabric = CHIP_CONFIG_MAX_GROUP_KEYS_PER_FABRIC;
35 :
36 : // TODO Make this configurable. Note: if PGA feature is enabled it SHALL be >= 4. else it SHALL = 1.
37 : static constexpr uint16_t kMaxMcastAddrCount = 4;
38 :
39 54 : GroupDataProviderImpl() : GroupDataProvider(kMaxMembershipPerFabric, kMaxGroupKeysPerFabric) {}
40 5 : GroupDataProviderImpl(uint16_t maxGroupsPerFabric, uint16_t maxGroupKeysPerFabric) :
41 5 : GroupDataProvider(maxGroupsPerFabric, maxGroupKeysPerFabric)
42 5 : {}
43 59 : ~GroupDataProviderImpl() override {}
44 :
45 : /**
46 : * @brief Set the storage implementation used for non-volatile storage of configuration data.
47 : * This method MUST be called before Init().
48 : *
49 : * @param storage Pointer to storage instance to set. Cannot be nullptr, will assert.
50 : */
51 : void SetStorageDelegate(PersistentStorageDelegate * storage);
52 :
53 117 : void SetSessionKeystore(Crypto::SessionKeystore * keystore) { mSessionKeystore = keystore; }
54 39 : Crypto::SessionKeystore * GetSessionKeystore() const { return mSessionKeystore; }
55 :
56 : CHIP_ERROR Init() override;
57 : void Finish() override;
58 6099 : bool IsInitialized() { return (mStorage != nullptr); }
59 :
60 : //
61 : // Group Info
62 : //
63 :
64 : // By id
65 : CHIP_ERROR SetGroupInfo(FabricIndex fabric_index, const GroupInfo & info) override;
66 : CHIP_ERROR GetGroupInfo(FabricIndex fabric_index, GroupId group_id, GroupInfo & info) override;
67 : CHIP_ERROR RemoveGroupInfo(FabricIndex fabric_index, GroupId group_id) override;
68 : // By index
69 : CHIP_ERROR SetGroupInfoAt(FabricIndex fabric_index, size_t index, const GroupInfo & info) override;
70 : CHIP_ERROR GetGroupInfoAt(FabricIndex fabric_index, size_t index, GroupInfo & info) override;
71 : CHIP_ERROR RemoveGroupInfoAt(FabricIndex fabric_index, size_t index) override;
72 : // Endpoints
73 : bool HasEndpoint(FabricIndex fabric_index, GroupId group_id, EndpointId endpoint_id) override;
74 : CHIP_ERROR AddEndpoint(FabricIndex fabric_index, GroupId group_id, EndpointId endpoint_id) override;
75 : CHIP_ERROR RemoveEndpoint(FabricIndex fabric_index, GroupId group_id, EndpointId endpoint_id,
76 : GroupCleanupPolicy cleanupPolicy) override;
77 : CHIP_ERROR RemoveEndpointAllGroups(FabricIndex fabric_index, EndpointId endpoint_id, GroupCleanupPolicy cleanupPolicy) override;
78 : CHIP_ERROR RemoveEndpoint(FabricIndex fabric_index, GroupId group_id, EndpointId endpoint_id) override;
79 : CHIP_ERROR RemoveEndpoint(FabricIndex fabric_index, EndpointId endpoint_id) override;
80 : CHIP_ERROR RemoveEndpoints(FabricIndex fabric_index, GroupId group_id) override;
81 : // Iterators
82 : GroupInfoIterator * IterateGroupInfo(FabricIndex fabric_index) override;
83 : EndpointIterator * IterateEndpoints(FabricIndex fabric_index, std::optional<GroupId> group_id = std::nullopt) override;
84 :
85 : //
86 : // Group-Key map
87 : //
88 :
89 : CHIP_ERROR SetGroupKey(FabricIndex fabric_index, GroupId group_id, KeysetId keyset_id) override;
90 : CHIP_ERROR SetGroupKeyAt(FabricIndex fabric_index, size_t index, const GroupKey & info) override;
91 : CHIP_ERROR GetGroupKeyAt(FabricIndex fabric_index, size_t index, GroupKey & info) override;
92 : CHIP_ERROR RemoveGroupKeyAt(FabricIndex fabric_index, size_t index) override;
93 : CHIP_ERROR RemoveGroupKeys(FabricIndex fabric_index) override;
94 : GroupKeyIterator * IterateGroupKeys(FabricIndex fabric_index) override;
95 :
96 : //
97 : // Key Sets
98 : //
99 :
100 : CHIP_ERROR SetKeySet(FabricIndex fabric_index, const ByteSpan & compressed_fabric_id, const KeySet & keys) override;
101 : CHIP_ERROR GetKeySet(FabricIndex fabric_index, chip::KeysetId keyset_id, KeySet & keys) override;
102 : CHIP_ERROR RemoveKeySet(FabricIndex fabric_index, chip::KeysetId keyset_id) override;
103 : CHIP_ERROR GetGroupKey(FabricIndex fabric_index, GroupId group_id, KeysetId & keyset_id) override;
104 : CHIP_ERROR GetIpkKeySet(FabricIndex fabric_index, KeySet & out_keyset) override;
105 : KeySetIterator * IterateKeySets(FabricIndex fabric_index) override;
106 :
107 : // Fabrics
108 : CHIP_ERROR RemoveFabric(FabricIndex fabric_index) override;
109 :
110 : // Decryption
111 : Crypto::SymmetricKeyContext * GetKeyContext(FabricIndex fabric_index, GroupId group_id) override;
112 : GroupSessionIterator * IterateGroupSessions(uint16_t session_id) override;
113 :
114 : // Groupcast configurations
115 57 : uint16_t getMaxMembershipCount() override { return kMaxMembershipCount; }
116 30 : uint16_t getMaxMcastAddrCount() override { return kMaxMcastAddrCount; }
117 :
118 119 : bool ConsumeAuxAclNotificationNeeded() override
119 : {
120 119 : if (IsGroupcastEnabled())
121 : {
122 119 : bool needed = mAuxAclNotificationNeeded;
123 119 : mAuxAclNotificationNeeded = false;
124 119 : return needed;
125 : }
126 0 : return false;
127 : }
128 :
129 : protected:
130 : class GroupInfoIteratorImpl : public GroupInfoIterator
131 : {
132 : public:
133 : GroupInfoIteratorImpl(GroupDataProviderImpl & provider, FabricIndex fabric_index);
134 : size_t Count() override;
135 : bool Next(GroupInfo & output) override;
136 : void Release() override;
137 :
138 : protected:
139 : GroupDataProviderImpl & mProvider;
140 : FabricIndex mFabric = kUndefinedFabricIndex;
141 : uint16_t mNextId = 0;
142 : size_t mCount = 0;
143 : size_t mTotal = 0;
144 : };
145 :
146 : class GroupKeyIteratorImpl : public GroupKeyIterator
147 : {
148 : public:
149 : GroupKeyIteratorImpl(GroupDataProviderImpl & provider, FabricIndex fabric_index);
150 : size_t Count() override;
151 : bool Next(GroupKey & output) override;
152 : void Release() override;
153 :
154 : protected:
155 : GroupDataProviderImpl & mProvider;
156 : FabricIndex mFabric = kUndefinedFabricIndex;
157 : uint16_t mNextId = 0;
158 : size_t mCount = 0;
159 : size_t mTotal = 0;
160 : };
161 :
162 : class EndpointIteratorImpl : public EndpointIterator
163 : {
164 : public:
165 : EndpointIteratorImpl(GroupDataProviderImpl & provider, FabricIndex fabric_index, std::optional<GroupId> group_id);
166 : size_t Count() override;
167 : bool Next(GroupEndpoint & output) override;
168 : void Release() override;
169 :
170 : protected:
171 : GroupDataProviderImpl & mProvider;
172 : FabricIndex mFabric = kUndefinedFabricIndex;
173 : GroupId mFirstGroup = kUndefinedGroupId;
174 : uint16_t mGroup = 0;
175 : size_t mGroupIndex = 0;
176 : size_t mGroupCount = 0;
177 : uint16_t mEndpoint = 0;
178 : size_t mEndpointIndex = 0;
179 : size_t mEndpointCount = 0;
180 : bool mFirstEndpoint = true;
181 : };
182 :
183 : class GroupKeyContext : public Crypto::SymmetricKeyContext
184 : {
185 : public:
186 9 : GroupKeyContext(GroupDataProviderImpl & provider) : mProvider(provider) {}
187 :
188 4 : GroupKeyContext(GroupDataProviderImpl & provider, const Crypto::Symmetric128BitsKeyByteArray & encryptionKey, uint16_t hash,
189 4 : const Crypto::Symmetric128BitsKeyByteArray & privacyKey) :
190 4 : mProvider(provider)
191 :
192 : {
193 4 : TEMPORARY_RETURN_IGNORED Initialize(encryptionKey, hash, privacyKey);
194 4 : }
195 :
196 13 : CHIP_ERROR Initialize(const Crypto::Symmetric128BitsKeyByteArray & encryptionKey, uint16_t hash,
197 : const Crypto::Symmetric128BitsKeyByteArray & privacyKey)
198 : {
199 13 : ReleaseKeys();
200 13 : mKeyHash = hash;
201 : // TODO: Load group keys to the session keystore upon loading from persistent storage
202 : //
203 : // Group keys should be transformed into a key handle as soon as possible or even
204 : // the key storage should be taken over by SessionKeystore interface, but this looks
205 : // like more work, so let's use the transitional code below for now.
206 :
207 13 : Crypto::SessionKeystore * keystore = mProvider.GetSessionKeystore();
208 13 : ReturnErrorOnFailure(keystore->CreateKey(encryptionKey, mEncryptionKey));
209 13 : return keystore->CreateKey(privacyKey, mPrivacyKey);
210 : }
211 :
212 26 : void ReleaseKeys()
213 : {
214 26 : Crypto::SessionKeystore * keystore = mProvider.GetSessionKeystore();
215 26 : keystore->DestroyKey(mEncryptionKey);
216 26 : keystore->DestroyKey(mPrivacyKey);
217 26 : }
218 :
219 4 : uint16_t GetKeyHash() override { return mKeyHash; }
220 :
221 : CHIP_ERROR MessageEncrypt(const ByteSpan & plaintext, const ByteSpan & aad, const ByteSpan & nonce, MutableByteSpan & mic,
222 : MutableByteSpan & ciphertext) const override;
223 : CHIP_ERROR MessageDecrypt(const ByteSpan & ciphertext, const ByteSpan & aad, const ByteSpan & nonce, const ByteSpan & mic,
224 : MutableByteSpan & plaintext) const override;
225 : CHIP_ERROR PrivacyEncrypt(const ByteSpan & input, const ByteSpan & nonce, MutableByteSpan & output) const override;
226 : CHIP_ERROR PrivacyDecrypt(const ByteSpan & input, const ByteSpan & nonce, MutableByteSpan & output) const override;
227 :
228 : void Release() override;
229 :
230 : protected:
231 : GroupDataProviderImpl & mProvider;
232 : uint16_t mKeyHash = 0;
233 : Crypto::Aes128KeyHandle mEncryptionKey;
234 : Crypto::Aes128KeyHandle mPrivacyKey;
235 : };
236 :
237 : class KeySetIteratorImpl : public KeySetIterator
238 : {
239 : public:
240 : KeySetIteratorImpl(GroupDataProviderImpl & provider, FabricIndex fabric_index);
241 : size_t Count() override;
242 : bool Next(KeySet & output) override;
243 : void Release() override;
244 :
245 : protected:
246 : GroupDataProviderImpl & mProvider;
247 : FabricIndex mFabric = kUndefinedFabricIndex;
248 : uint16_t mNextId = 0;
249 : size_t mCount = 0;
250 : size_t mTotal = 0;
251 : };
252 :
253 : class GroupSessionIteratorImpl : public GroupSessionIterator
254 : {
255 : public:
256 : GroupSessionIteratorImpl(GroupDataProviderImpl & provider, uint16_t session_id);
257 : size_t Count() override;
258 : bool Next(GroupSession & output) override;
259 : void Release() override;
260 :
261 : protected:
262 : GroupDataProviderImpl & mProvider;
263 : uint16_t mSessionId = 0;
264 : FabricIndex mFirstFabric = kUndefinedFabricIndex;
265 : FabricIndex mFabric = kUndefinedFabricIndex;
266 : uint16_t mFabricCount = 0;
267 : uint16_t mFabricTotal = 0;
268 : uint16_t mMapping = 0;
269 : uint16_t mMapCount = 0;
270 : uint16_t mKeyIndex = 0;
271 : uint16_t mKeyCount = 0;
272 : bool mFirstMap = true;
273 : GroupKeyContext mGroupKeyContext;
274 : };
275 :
276 : PersistentStorageDelegate * mStorage = nullptr;
277 : Crypto::SessionKeystore * mSessionKeystore = nullptr;
278 : ObjectPool<GroupInfoIteratorImpl, kIteratorsMax> mGroupInfoIterators;
279 : ObjectPool<GroupKeyIteratorImpl, kIteratorsMax> mGroupKeyIterators;
280 : ObjectPool<EndpointIteratorImpl, kIteratorsMax> mEndpointIterators;
281 : ObjectPool<KeySetIteratorImpl, kIteratorsMax> mKeySetIterators;
282 : ObjectPool<GroupSessionIteratorImpl, kIteratorsMax> mGroupSessionsIterator;
283 : ObjectPool<GroupKeyContext, kIteratorsMax> mGroupKeyContexPool;
284 : bool mAuxAclNotificationNeeded = false;
285 : };
286 :
287 : } // namespace Credentials
288 : } // namespace chip
|