Fix for x86_64 build fail
[platform/upstream/connectedhomeip.git] / src / platform / ESP32 / GroupKeyStoreImpl.cpp
1 /*
2  *
3  *    Copyright (c) 2020 Project CHIP Authors
4  *    Copyright (c) 2018 Nest Labs, Inc.
5  *    All rights reserved.
6  *
7  *    Licensed under the Apache License, Version 2.0 (the "License");
8  *    you may not use this file except in compliance with the License.
9  *    You may obtain a copy of the License at
10  *
11  *        http://www.apache.org/licenses/LICENSE-2.0
12  *
13  *    Unless required by applicable law or agreed to in writing, software
14  *    distributed under the License is distributed on an "AS IS" BASIS,
15  *    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16  *    See the License for the specific language governing permissions and
17  *    limitations under the License.
18  */
19
20 /**
21  *    @file
22  *          Provides an implementation of the Chip GroupKeyStore interface
23  *          for the ESP32 platform.
24  */
25 /* this file behaves like a config.h, comes first */
26 #include <platform/internal/CHIPDeviceLayerInternal.h>
27
28 #include <platform/ESP32/GroupKeyStoreImpl.h>
29
30 #include "nvs.h"
31 #include "nvs_flash.h"
32
33 using namespace ::chip;
34 using namespace ::nl::Weave::Profiles::Security::AppKeys;
35
36 namespace chip {
37 namespace DeviceLayer {
38 namespace Internal {
39
40 CHIP_ERROR GroupKeyStoreImpl::RetrieveGroupKey(uint32_t keyId, ChipGroupKey & key)
41 {
42     CHIP_ERROR err;
43     size_t keyLen;
44     char keyName[kMaxConfigKeyNameLength + 1];
45     ESP32Config::Key configKey{ kConfigNamespace_ChipConfig, keyName };
46
47     err = FormKeyName(keyId, keyName, sizeof(keyName));
48     SuccessOrExit(err);
49
50     err = ReadConfigValueBin(configKey, key.Key, sizeof(key.Key), keyLen);
51     if (err == CHIP_DEVICE_ERROR_CONFIG_NOT_FOUND)
52     {
53         err = CHIP_ERROR_KEY_NOT_FOUND;
54     }
55     SuccessOrExit(err);
56
57     if (keyId != ChipKeyId::kFabricSecret)
58     {
59         memcpy(&key.StartTime, key.Key + kChipAppGroupKeySize, sizeof(uint32_t));
60         keyLen -= sizeof(uint32_t);
61     }
62
63     key.KeyId  = keyId;
64     key.KeyLen = keyLen;
65
66 exit:
67     return err;
68 }
69
70 CHIP_ERROR GroupKeyStoreImpl::StoreGroupKey(const ChipGroupKey & key)
71 {
72     CHIP_ERROR err;
73     nvs_handle handle;
74     char keyName[kMaxConfigKeyNameLength + 1];
75     uint8_t keyData[ChipGroupKey::MaxKeySize];
76     bool needClose    = false;
77     bool indexUpdated = false;
78
79     err = FormKeyName(key.KeyId, keyName, sizeof(keyName));
80     SuccessOrExit(err);
81
82     err = AddKeyToIndex(key.KeyId, indexUpdated);
83     SuccessOrExit(err);
84
85     err = nvs_open(kConfigNamespace_ChipConfig, NVS_READWRITE, &handle);
86     SuccessOrExit(err);
87     needClose = true;
88
89     memcpy(keyData, key.Key, ChipGroupKey::MaxKeySize);
90     if (key.KeyId != ChipKeyId::kFabricSecret)
91     {
92         memcpy(keyData + kChipAppGroupKeySize, (const void *) &key.StartTime, sizeof(uint32_t));
93     }
94
95 #if CHIP_PROGRESS_LOGGING
96     if (ChipKeyId::IsAppEpochKey(key.KeyId))
97     {
98         ChipLogProgress(DeviceLayer, "GroupKeyStore: storing epoch key %s/%s (key len %" PRId8 ", start time %" PRIu32 ")",
99                         kConfigNamespace_ChipConfig, keyName, key.KeyLen, key.StartTime);
100     }
101     else if (ChipKeyId::IsAppGroupMasterKey(key.KeyId))
102     {
103         ChipLogProgress(DeviceLayer, "GroupKeyStore: storing app master key %s/%s (key len %" PRId8 ", global id 0x%" PRIX32 ")",
104                         kConfigNamespace_ChipConfig, keyName, key.KeyLen, key.GlobalId);
105     }
106     else
107     {
108         const char * keyType = (ChipKeyId::IsAppRootKey(key.KeyId)) ? "root" : "general";
109         ChipLogProgress(DeviceLayer, "GroupKeyStore: storing %s key %s/%s (key len %" PRId8 ")", keyType,
110                         kConfigNamespace_ChipConfig, keyName, key.KeyLen);
111     }
112 #endif // CHIP_PROGRESS_LOGGING
113
114     err = nvs_set_blob(handle, keyName, keyData, ChipGroupKey::MaxKeySize);
115     SuccessOrExit(err);
116
117     if (indexUpdated)
118     {
119         err = WriteKeyIndex(handle);
120         SuccessOrExit(err);
121     }
122
123     // Commit the value to the persistent store.
124     err = nvs_commit(handle);
125     SuccessOrExit(err);
126
127 exit:
128     if (needClose)
129     {
130         nvs_close(handle);
131     }
132     if (err != CHIP_NO_ERROR && indexUpdated)
133     {
134         mNumKeys--;
135     }
136     ClearSecretData(keyData, sizeof(keyData));
137     return err;
138 }
139
140 CHIP_ERROR GroupKeyStoreImpl::DeleteGroupKey(uint32_t keyId)
141 {
142     return DeleteKeyOrKeys(keyId, ChipKeyId::kType_None);
143 }
144
145 CHIP_ERROR GroupKeyStoreImpl::DeleteGroupKeysOfAType(uint32_t keyType)
146 {
147     return DeleteKeyOrKeys(ChipKeyId::kNone, keyType);
148 }
149
150 CHIP_ERROR GroupKeyStoreImpl::EnumerateGroupKeys(uint32_t keyType, uint32_t * keyIds, uint8_t keyIdsArraySize, uint8_t & keyCount)
151 {
152     keyCount = 0;
153
154     for (uint8_t i = 0; i < mNumKeys && keyCount < keyIdsArraySize; i++)
155     {
156         if (keyType == ChipKeyId::kType_None || ChipKeyId::GetType(mKeyIndex[i]) == keyType)
157         {
158             keyIds[keyCount++] = mKeyIndex[i];
159         }
160     }
161
162     return CHIP_NO_ERROR;
163 }
164
165 CHIP_ERROR GroupKeyStoreImpl::Clear(void)
166 {
167     return DeleteKeyOrKeys(ChipKeyId::kNone, ChipKeyId::kType_None);
168 }
169
170 CHIP_ERROR GroupKeyStoreImpl::RetrieveLastUsedEpochKeyId(void)
171 {
172     CHIP_ERROR err;
173
174     err = ReadConfigValue(kConfigKey_LastUsedEpochKeyId, LastUsedEpochKeyId);
175     if (err == CHIP_DEVICE_ERROR_CONFIG_NOT_FOUND)
176     {
177         LastUsedEpochKeyId = ChipKeyId::kNone;
178         err                = CHIP_NO_ERROR;
179     }
180     return err;
181 }
182
183 CHIP_ERROR GroupKeyStoreImpl::StoreLastUsedEpochKeyId(void)
184 {
185     return WriteConfigValue(kConfigKey_LastUsedEpochKeyId, LastUsedEpochKeyId);
186 }
187
188 CHIP_ERROR GroupKeyStoreImpl::Init()
189 {
190     CHIP_ERROR err;
191     size_t indexSizeBytes;
192
193     err = ReadConfigValueBin(kConfigKey_GroupKeyIndex, (uint8_t *) mKeyIndex, sizeof(mKeyIndex), indexSizeBytes);
194     if (err == CHIP_DEVICE_ERROR_CONFIG_NOT_FOUND)
195     {
196         err            = CHIP_NO_ERROR;
197         indexSizeBytes = 0;
198     }
199     SuccessOrExit(err);
200
201     mNumKeys = indexSizeBytes / sizeof(uint32_t);
202
203 exit:
204     return err;
205 }
206
207 CHIP_ERROR GroupKeyStoreImpl::AddKeyToIndex(uint32_t keyId, bool & indexUpdated)
208 {
209     CHIP_ERROR err = CHIP_NO_ERROR;
210
211     indexUpdated = false;
212
213     for (uint8_t i = 0; i < mNumKeys; i++)
214     {
215         if (mKeyIndex[i] == keyId)
216         {
217             ExitNow(err = CHIP_NO_ERROR);
218         }
219     }
220
221     VerifyOrExit(mNumKeys < kMaxGroupKeys, err = CHIP_ERROR_TOO_MANY_KEYS);
222
223     mKeyIndex[mNumKeys++] = keyId;
224     indexUpdated          = true;
225
226 exit:
227     return err;
228 }
229
230 CHIP_ERROR GroupKeyStoreImpl::WriteKeyIndex(nvs_handle handle)
231 {
232     ChipLogProgress(DeviceLayer, "GroupKeyStore: writing key index %s/%s (num keys %" PRIu8 ")", kConfigKey_GroupKeyIndex.Namespace,
233                     kConfigKey_GroupKeyIndex.Name, mNumKeys);
234     return nvs_set_blob(handle, kConfigKey_GroupKeyIndex.Name, mKeyIndex, mNumKeys * sizeof(uint32_t));
235 }
236
237 CHIP_ERROR GroupKeyStoreImpl::DeleteKeyOrKeys(uint32_t targetKeyId, uint32_t targetKeyType)
238 {
239     CHIP_ERROR err = CHIP_NO_ERROR;
240     nvs_handle handle;
241     char keyName[kMaxConfigKeyNameLength + 1];
242     bool needClose = false;
243
244     for (uint8_t i = 0; i < mNumKeys;)
245     {
246         uint32_t curKeyId = mKeyIndex[i];
247
248         if ((targetKeyId == ChipKeyId::kNone && targetKeyType == ChipKeyId::kType_None) || curKeyId == targetKeyId ||
249             ChipKeyId::GetType(curKeyId) == targetKeyType)
250         {
251             if (!needClose)
252             {
253                 err = nvs_open(kConfigNamespace_ChipConfig, NVS_READWRITE, &handle);
254                 SuccessOrExit(err);
255                 needClose = true;
256             }
257
258             err = FormKeyName(curKeyId, keyName, sizeof(keyName));
259             SuccessOrExit(err);
260
261             err = nvs_erase_key(handle, keyName);
262 #if CHIP_PROGRESS_LOGGING
263             if (err == ESP_OK)
264             {
265                 const char * keyType;
266                 if (ChipKeyId::IsAppRootKey(curKeyId))
267                 {
268                     keyType = "root";
269                 }
270                 else if (ChipKeyId::IsAppGroupMasterKey(curKeyId))
271                 {
272                     keyType = "app master";
273                 }
274                 else if (ChipKeyId::IsAppEpochKey(curKeyId))
275                 {
276                     keyType = "epoch";
277                 }
278                 else
279                 {
280                     keyType = "general";
281                 }
282                 ChipLogProgress(DeviceLayer, "GroupKeyStore: erasing %s key %s/%s", keyType, kConfigNamespace_ChipConfig, keyName);
283             }
284             else
285 #endif // CHIP_PROGRESS_LOGGING
286                 if (err == ESP_ERR_NVS_NOT_FOUND)
287             {
288                 err = CHIP_NO_ERROR;
289             }
290             SuccessOrExit(err);
291
292             mNumKeys--;
293
294             memmove(&mKeyIndex[i], &mKeyIndex[i + 1], (mNumKeys - i) * sizeof(uint32_t));
295         }
296         else
297         {
298             i++;
299         }
300     }
301
302     if (needClose)
303     {
304         err = WriteKeyIndex(handle);
305         SuccessOrExit(err);
306
307         // Commit to the persistent store.
308         err = nvs_commit(handle);
309         SuccessOrExit(err);
310     }
311
312 exit:
313     if (needClose)
314     {
315         nvs_close(handle);
316     }
317     return err;
318 }
319
320 CHIP_ERROR GroupKeyStoreImpl::FormKeyName(uint32_t keyId, char * buf, size_t bufSize)
321 {
322     CHIP_ERROR err = CHIP_NO_ERROR;
323
324     VerifyOrExit(bufSize >= kMaxConfigKeyNameLength, err = CHIP_ERROR_BUFFER_TOO_SMALL);
325
326     if (keyId == ChipKeyId::kFabricSecret)
327     {
328         strcpy(buf, kConfigKey_FabricSecret.Name);
329     }
330     else
331     {
332         snprintf(buf, bufSize, "%s%08" PRIX32, kGroupKeyNamePrefix, keyId);
333     }
334
335 exit:
336     return err;
337 }
338
339 } // namespace Internal
340 } // namespace DeviceLayer
341 } // namespace chip