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