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