Line data Source code
1 : /*
2 : *
3 : * Copyright (c) 2021-2024 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 <lib/core/CHIPPersistentStorageDelegate.h>
20 : #include <lib/core/DataModelTypes.h>
21 : #include <lib/support/Base85.h>
22 : #include <lib/support/CHIPMemString.h>
23 :
24 : #include <stdio.h>
25 :
26 : namespace chip {
27 :
28 : /**
29 : * Represents a key used for addressing a specific storage element.
30 : *
31 : * May contain generic fixed keys (e.g. "g/fidx") or formatted fabric-specific
32 : * keys ("f/%x/..." where %x is the fabric index).
33 : */
34 : class StorageKeyName
35 : {
36 : public:
37 : StorageKeyName(const StorageKeyName & other) = default;
38 : StorageKeyName & operator=(const StorageKeyName & other) = default;
39 :
40 622732 : ~StorageKeyName() { memset(mKeyNameBuffer, 0, sizeof(mKeyNameBuffer)); }
41 :
42 529018 : const char * KeyName() const { return mKeyNameBuffer; }
43 :
44 131375 : bool IsInitialized() const { return mKeyNameBuffer[0] != 0; }
45 6369 : bool IsUninitialized() const { return mKeyNameBuffer[0] == 0; }
46 6369 : bool operator!() const { return IsUninitialized(); }
47 :
48 277362 : static StorageKeyName FromConst(const char * value)
49 : {
50 277362 : StorageKeyName result;
51 277362 : Platform::CopyString(result.mKeyNameBuffer, value);
52 277362 : return result;
53 : }
54 :
55 251504 : static StorageKeyName ENFORCE_FORMAT(1, 2) Formatted(const char * format, ...)
56 : {
57 251504 : StorageKeyName result;
58 :
59 : va_list args;
60 251504 : va_start(args, format);
61 251504 : vsnprintf(result.mKeyNameBuffer, sizeof(result.mKeyNameBuffer), format, args);
62 251504 : va_end(args);
63 :
64 251504 : return result;
65 : }
66 :
67 : // Explicit 0-filled key. MUST be initialized later
68 93866 : static StorageKeyName Uninitialized()
69 : {
70 93866 : StorageKeyName result;
71 93866 : return result;
72 : }
73 :
74 : private:
75 : // May only be created by the underlying constructor methods
76 622732 : StorageKeyName() {}
77 :
78 : // Contains the storage for the key name because some strings may be formatted.
79 : char mKeyNameBuffer[PersistentStorageDelegate::kKeyLengthMax + 1] = { 0 };
80 : };
81 :
82 : /**
83 : * This is the common key allocation policy for all classes using
84 : * PersistentStorageDelegate storage.
85 : *
86 : * Keys should have the following formats:
87 : *
88 : * * Keys that are not tied to a specific fabric: "g/....".
89 : * * Keys that are tied to a specific fabric: "f/%x/...." where the %x gets
90 : * replaced by the fabric index.
91 : */
92 : class DefaultStorageKeyAllocator
93 : {
94 : private:
95 : DefaultStorageKeyAllocator() = default;
96 :
97 : public:
98 : // Fabric Table
99 1532 : static StorageKeyName FabricIndexInfo() { return StorageKeyName::FromConst("g/fidx"); }
100 2097 : static StorageKeyName FabricNOC(FabricIndex fabric) { return StorageKeyName::Formatted("f/%x/n", fabric); }
101 2048 : static StorageKeyName FabricICAC(FabricIndex fabric) { return StorageKeyName::Formatted("f/%x/i", fabric); }
102 2097 : static StorageKeyName FabricRCAC(FabricIndex fabric) { return StorageKeyName::Formatted("f/%x/r", fabric); }
103 63 : static StorageKeyName FabricVVSC(FabricIndex fabric) { return StorageKeyName::Formatted("f/%x/vvsc", fabric); }
104 74 : static StorageKeyName FabricVidVerificationStatement(FabricIndex fabric)
105 : {
106 74 : return StorageKeyName::Formatted("f/%x/vvs", fabric);
107 : }
108 985 : static StorageKeyName FabricMetadata(FabricIndex fabric) { return StorageKeyName::Formatted("f/%x/m", fabric); }
109 983 : static StorageKeyName FabricOpKey(FabricIndex fabric) { return StorageKeyName::Formatted("f/%x/o", fabric); }
110 :
111 : // Fail-safe handling
112 2418 : static StorageKeyName FabricTableCommitMarkerKey() { return StorageKeyName::FromConst("g/fs/c"); }
113 : static StorageKeyName FailSafeNetworkConfig() { return StorageKeyName::FromConst("g/fs/n"); }
114 :
115 : // LastKnownGoodTime
116 2641 : static StorageKeyName LastKnownGoodTimeKey() { return StorageKeyName::FromConst("g/lkgt"); }
117 :
118 : // Session resumption
119 879 : static StorageKeyName FabricSession(FabricIndex fabric, NodeId nodeId)
120 : {
121 879 : return StorageKeyName::Formatted("f/%x/s/%08" PRIX32 "%08" PRIX32, fabric, static_cast<uint32_t>(nodeId >> 32),
122 879 : static_cast<uint32_t>(nodeId));
123 : }
124 :
125 496 : static StorageKeyName SessionResumptionIndex() { return StorageKeyName::FromConst("g/sri"); }
126 683 : static StorageKeyName SessionResumption(const char * resumptionIdBase64)
127 : {
128 683 : return StorageKeyName::Formatted("g/s/%s", resumptionIdBase64);
129 : }
130 :
131 : // Access Control
132 0 : static StorageKeyName AccessControlAclEntry(FabricIndex fabric, size_t index)
133 : {
134 0 : return StorageKeyName::Formatted("f/%x/ac/0/%x", fabric, static_cast<unsigned>(index));
135 : }
136 :
137 0 : static StorageKeyName AccessControlExtensionEntry(FabricIndex fabric) { return StorageKeyName::Formatted("f/%x/ac/1", fabric); }
138 :
139 : // Group Message Counters
140 944 : static StorageKeyName GroupDataCounter() { return StorageKeyName::FromConst("g/gdc"); }
141 941 : static StorageKeyName GroupControlCounter() { return StorageKeyName::FromConst("g/gcc"); }
142 :
143 : // ICD Check-In Counter
144 : static StorageKeyName ICDCheckInCounter() { return StorageKeyName::FromConst("g/icd/cic"); }
145 :
146 : // Device Information Provider
147 : static StorageKeyName UserLabelLengthKey(EndpointId endpoint) { return StorageKeyName::Formatted("g/userlbl/%x", endpoint); }
148 : static StorageKeyName UserLabelIndexKey(EndpointId endpoint, uint32_t index)
149 : {
150 : return StorageKeyName::Formatted("g/userlbl/%x/%" PRIx32, endpoint, index);
151 : }
152 :
153 : // Group Data Provider
154 :
155 : // List of fabric indices that have endpoint-to-group associations defined.
156 1164 : static StorageKeyName GroupFabricList() { return StorageKeyName::FromConst("g/gfl"); }
157 8288 : static StorageKeyName FabricGroups(chip::FabricIndex fabric) { return StorageKeyName::Formatted("f/%x/g", fabric); }
158 10767 : static StorageKeyName FabricGroup(chip::FabricIndex fabric, chip::GroupId group)
159 : {
160 10767 : return StorageKeyName::Formatted("f/%x/g/%x", fabric, group);
161 : }
162 1793 : static StorageKeyName FabricGroupKey(chip::FabricIndex fabric, uint16_t index)
163 : {
164 1793 : return StorageKeyName::Formatted("f/%x/gk/%x", fabric, index);
165 : }
166 67530 : static StorageKeyName FabricGroupEndpoint(chip::FabricIndex fabric, chip::GroupId group, chip::EndpointId endpoint)
167 : {
168 67530 : return StorageKeyName::Formatted("f/%x/g/%x/e/%x", fabric, group, endpoint);
169 : }
170 874 : static StorageKeyName FabricKeyset(chip::FabricIndex fabric, uint16_t keyset)
171 : {
172 874 : return StorageKeyName::Formatted("f/%x/k/%x", fabric, keyset);
173 : }
174 :
175 1078 : static StorageKeyName AttributeValue(EndpointId endpointId, ClusterId clusterId, AttributeId attributeId)
176 : {
177 : // Needs at most 26 chars: 6 for "g/a///", 4 for the endpoint id, 8 each
178 : // for the cluster and attribute ids.
179 1078 : return StorageKeyName::Formatted("g/a/%x/%" PRIx32 "/%" PRIx32, endpointId, clusterId, attributeId);
180 : }
181 :
182 : // Returns the key for Safely stored attributes.
183 2322 : static StorageKeyName SafeAttributeValue(EndpointId endpointId, ClusterId clusterId, AttributeId attributeId)
184 : {
185 : // Needs at most 26 chars: 6 for "s/a///", 4 for the endpoint id, 8 each
186 : // for the cluster and attribute ids.
187 2322 : return StorageKeyName::Formatted("g/sa/%x/%" PRIx32 "/%" PRIx32, endpointId, clusterId, attributeId);
188 : }
189 :
190 : // TODO: Should store fabric-specific parts of the binding list under keys
191 : // starting with "f/%x/".
192 81 : static StorageKeyName BindingTable() { return StorageKeyName::FromConst("g/bt"); }
193 614 : static StorageKeyName BindingTableEntry(uint8_t index) { return StorageKeyName::Formatted("g/bt/%x", index); }
194 :
195 : // ICD Management
196 :
197 42 : static StorageKeyName ICDManagementTableEntry(chip::FabricIndex fabric, uint16_t index)
198 : {
199 42 : return StorageKeyName::Formatted("f/%x/icd/%x", fabric, index);
200 : }
201 :
202 : // Thread Network Directory
203 :
204 50 : static StorageKeyName ThreadNetworkDirectoryIndex() { return StorageKeyName::FromConst("g/tnd/i"); }
205 49 : static StorageKeyName ThreadNetworkDirectoryDataset(uint64_t extendedPanId)
206 : {
207 : return StorageKeyName::Formatted("g/tnd/n/%08" PRIx32 "%08" PRIx32, // some platforms can't format uint64
208 49 : static_cast<uint32_t>(extendedPanId >> 32), static_cast<uint32_t>(extendedPanId));
209 : }
210 :
211 : // Network Identity Management
212 :
213 65661 : static StorageKeyName NetworkIdentityManagementAdministratorSecret() { return StorageKeyName::FromConst("g/nim/nass"); }
214 :
215 196920 : static StorageKeyName NetworkIdentityManagementNetworkIdentityIndex() { return StorageKeyName::FromConst("g/nim/ni"); }
216 :
217 131227 : static StorageKeyName NetworkIdentityManagementNetworkIdentity(uint16_t niIndex)
218 : {
219 131227 : return StorageKeyName::Formatted("g/nim/n/%04x", niIndex);
220 : }
221 :
222 4223 : static StorageKeyName NetworkIdentityManagementClientIndex() { return StorageKeyName::FromConst("g/nim/ci"); }
223 :
224 6347 : static StorageKeyName NetworkIdentityManagementClient(uint16_t clientIndex)
225 : {
226 6347 : return StorageKeyName::Formatted("g/nim/c/%04x", clientIndex);
227 : }
228 :
229 : // Client identifier mapping: g/nim/@<base85-encoded identifier> = 7 + 25 = 32 chars
230 : // Uses FixedByteSpan<20> directly to avoid pulling in CHIPCert.h for CertificateKeyId.
231 4207 : static StorageKeyName NetworkIdentityManagementClientIdentifierMapping(FixedByteSpan<20> identifier)
232 : {
233 : char base85[Base85EncodedLength(identifier.size())];
234 4207 : SuccessOrDie(BytesToBase85(identifier.data(), identifier.size(), base85, sizeof(base85)));
235 4207 : return StorageKeyName::Formatted("g/nim/@%.*s", static_cast<int>(sizeof(base85)), base85);
236 : }
237 :
238 : // OTA
239 :
240 6 : static StorageKeyName OTADefaultProviders() { return StorageKeyName::FromConst("g/o/dp"); }
241 4 : static StorageKeyName OTACurrentProvider() { return StorageKeyName::FromConst("g/o/cp"); }
242 4 : static StorageKeyName OTAUpdateToken() { return StorageKeyName::FromConst("g/o/ut"); }
243 4 : static StorageKeyName OTACurrentUpdateState() { return StorageKeyName::FromConst("g/o/us"); }
244 4 : static StorageKeyName OTATargetVersion() { return StorageKeyName::FromConst("g/o/tv"); }
245 :
246 : // Event number counter.
247 24 : static StorageKeyName IMEventNumber() { return StorageKeyName::FromConst("g/im/ec"); }
248 :
249 : // Subscription resumption
250 2854 : static StorageKeyName SubscriptionResumption(size_t index)
251 : {
252 2854 : return StorageKeyName::Formatted("g/su/%x", static_cast<unsigned>(index));
253 : }
254 22 : static StorageKeyName SubscriptionResumptionMaxCount() { return StorageKeyName::Formatted("g/sum"); }
255 :
256 : // Number of scenes stored in a given endpoint's scene table, across all fabrics.
257 865 : static StorageKeyName EndpointSceneCountKey(EndpointId endpoint) { return StorageKeyName::Formatted("g/scc/e/%x", endpoint); }
258 :
259 : // Stores the scene count for a fabric for the given endpoint and a map between scene storage ids (<sceneId, groupId>) and
260 : // sceneIndex for a specific Fabric and endpoint.
261 1800 : static StorageKeyName FabricSceneDataKey(FabricIndex fabric, EndpointId endpoint)
262 : {
263 1800 : return StorageKeyName::Formatted("f/%x/e/%x/sc", fabric, endpoint);
264 : }
265 :
266 : // Stores the actual scene data for a given scene on a given endpoint for a particular fabric.
267 : // idx corresponds to the indices read from FabricSceneDataKey.
268 : // SceneIndex
269 458 : static StorageKeyName FabricSceneKey(FabricIndex fabric, EndpointId endpoint, uint16_t idx)
270 : {
271 458 : return StorageKeyName::Formatted("f/%x/e/%x/sc/%x", fabric, endpoint, idx);
272 : }
273 :
274 : // Time synchronization cluster
275 15 : static StorageKeyName TSTrustedTimeSource() { return StorageKeyName::FromConst("g/ts/tts"); }
276 5 : static StorageKeyName TSDefaultNTP() { return StorageKeyName::FromConst("g/ts/dntp"); }
277 17 : static StorageKeyName TSTimeZone() { return StorageKeyName::FromConst("g/ts/tz"); }
278 27 : static StorageKeyName TSDSTOffset() { return StorageKeyName::FromConst("g/ts/dsto"); }
279 :
280 : // FabricICDClientInfoCounter is only used by DefaultICDClientStorage
281 : // Records the number of ClientInfos for a particular fabric
282 144 : static StorageKeyName FabricICDClientInfoCounter(FabricIndex fabric) { return StorageKeyName::Formatted("f/%x/icdc", fabric); }
283 :
284 : // ICDClientInfoKey is only used by DefaultICDClientStorage
285 : // Stores/Loads all ICD clientInfos for a particular fabric
286 84 : static StorageKeyName ICDClientInfoKey(FabricIndex fabric) { return StorageKeyName::Formatted("f/%x/icdk", fabric); }
287 :
288 : // ICDFabricList is only used by DefaultICDClientStorage
289 : // when new fabric is created, this list needs to be updated,
290 : // when client init DefaultICDClientStorage, this table needs to be loaded.
291 31 : static StorageKeyName ICDFabricList() { return StorageKeyName::FromConst("g/icdfl"); }
292 :
293 : // Terms and Conditions Acceptance Key
294 : // Stores the terms and conditions acceptance including terms and conditions revision, TLV encoded
295 11 : static StorageKeyName TermsAndConditionsAcceptance() { return StorageKeyName::FromConst("g/tc"); }
296 :
297 : // TLS Clusters Certs Keys, used by CertificateTableImpl to persist certificates for TLS clusters
298 :
299 : // Number of root certs stored in table for a given endpoint, across all fabrics.
300 16 : static StorageKeyName TlsRootCertEndpointCountKey(EndpointId endpoint)
301 : {
302 16 : return StorageKeyName::Formatted("g/tlsr/e/%x", endpoint);
303 : }
304 :
305 : // Stores information about root certs for the given fabric & endpoint
306 73 : static StorageKeyName TlsRootCertFabricDataKey(FabricIndex fabric, EndpointId endpoint)
307 : {
308 73 : return StorageKeyName::Formatted("f/%x/e/%x/tlsr", fabric, endpoint);
309 : }
310 :
311 : // Stores the root cert payload for the given fabric & endpoint
312 14 : static StorageKeyName TlsRootCertEntityKey(FabricIndex fabric, EndpointId endpoint, uint16_t idx)
313 : {
314 14 : return StorageKeyName::Formatted("f/%x/e/%x/tlsr/%x", fabric, endpoint, idx);
315 : }
316 :
317 : // Number of client certs stored in table for a given endpoint, across all fabrics.
318 12 : static StorageKeyName TlsClientCertEndpointCountKey(EndpointId endpoint)
319 : {
320 12 : return StorageKeyName::Formatted("g/tlsc/e/%x", endpoint);
321 : }
322 :
323 : // Stores information about client certs for the given fabric & endpoint
324 68 : static StorageKeyName TlsClientCertFabricDataKey(FabricIndex fabric, EndpointId endpoint)
325 : {
326 68 : return StorageKeyName::Formatted("f/%x/e/%x/tlsc", fabric, endpoint);
327 : }
328 :
329 : // Stores the client cert payload for the given fabric & endpoint
330 13 : static StorageKeyName TlsClientCertEntityKey(FabricIndex fabric, EndpointId endpoint, uint16_t idx)
331 : {
332 13 : return StorageKeyName::Formatted("f/%x/e/%x/tlsc/%x", fabric, endpoint, idx);
333 : }
334 :
335 : // Stores global data about certificates for the given endpoint, across all fabrics, used by CertificateTableImpl
336 : // Applications can also create their own implementation extending CertificateTable
337 34 : static StorageKeyName TlsEndpointGlobalDataKey(EndpointId endpoint)
338 : {
339 34 : return StorageKeyName::Formatted("g/tlsr/g/%x", endpoint);
340 : }
341 :
342 : // Number of tls endpoints stored in table for a given endpoint, across all fabrics.
343 : static StorageKeyName TlsClientEndpointCountKey(EndpointId endpoint)
344 : {
345 : return StorageKeyName::Formatted("g/tlse/e/%x", endpoint);
346 : }
347 :
348 : // Stores information about TLS endpoints for the given fabric & endpoint
349 : static StorageKeyName TlsClientEndpointFabricDataKey(FabricIndex fabric, EndpointId endpoint)
350 : {
351 : return StorageKeyName::Formatted("f/%x/e/%x/tlse", fabric, endpoint);
352 : }
353 :
354 : // Stores the root cert payload for the given fabric & endpoint
355 : static StorageKeyName TlsClientEndpointEntityKey(FabricIndex fabric, EndpointId endpoint, uint16_t idx)
356 : {
357 : return StorageKeyName::Formatted("f/%x/e/%x/tlse/%x", fabric, endpoint, idx);
358 : }
359 :
360 : // Stores global data about TLS endpoints, across all fabrics, used by TLS Client Management cluster
361 : static StorageKeyName TlsClientEndpointGlobalDataKey(EndpointId endpoint)
362 : {
363 : return StorageKeyName::Formatted("g/tlse/g/%x", endpoint);
364 : }
365 : };
366 :
367 : } // namespace chip
|