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