Apply Upstream code (2021-03-15)
[platform/upstream/connectedhomeip.git] / src / include / platform / internal / GenericConfigurationManagerImpl.cpp
1 /*
2  *
3  *    Copyright (c) 2020-2021 Project CHIP Authors
4  *    Copyright (c) 2019-2020 Google LLC.
5  *    Copyright (c) 2018 Nest Labs, Inc.
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  *          Contains non-inline method definitions for the
23  *          GenericConfigurationManagerImpl<> template.
24  */
25
26 #ifndef GENERIC_CONFIGURATION_MANAGER_IMPL_CPP
27 #define GENERIC_CONFIGURATION_MANAGER_IMPL_CPP
28
29 #include <ble/CHIPBleServiceData.h>
30 #include <core/CHIPConfig.h>
31 #include <platform/internal/CHIPDeviceLayerInternal.h>
32 #include <platform/internal/GenericConfigurationManagerImpl.h>
33 #include <support/Base64.h>
34 #include <support/CHIPMem.h>
35 #include <support/CodeUtils.h>
36 #include <support/ScopedBuffer.h>
37
38 #if CHIP_DEVICE_CONFIG_ENABLE_THREAD
39 #include <platform/ThreadStackManager.h>
40 #endif
41
42 #if CHIP_DEVICE_CONFIG_LOG_PROVISIONING_HASH
43 #include <crypto/CHIPCryptoPAL.h>
44 #endif
45
46 namespace chip {
47 namespace DeviceLayer {
48 namespace Internal {
49
50 template <class ImplClass>
51 CHIP_ERROR GenericConfigurationManagerImpl<ImplClass>::_Init()
52 {
53     // Cache flags indicating whether the device is currently service provisioned, is a member of a fabric,
54     // is paired to an account, and/or provisioned with operational credentials.
55     mFlags.ClearAll()
56         .Set(Flags::kIsServiceProvisioned, Impl()->ConfigValueExists(ImplClass::kConfigKey_ServiceConfig))
57         .Set(Flags::kIsMemberOfFabric, Impl()->ConfigValueExists(ImplClass::kConfigKey_FabricId))
58         .Set(Flags::kIsPairedToAccount, Impl()->ConfigValueExists(ImplClass::kConfigKey_PairedAccountId))
59         .Set(Flags::kOperationalDeviceCredentialsProvisioned,
60              Impl()->ConfigValueExists(ImplClass::kConfigKey_OperationalDeviceCert));
61
62 #if CHIP_ENABLE_ROTATING_DEVICE_ID
63     mLifetimePersistedCounter.Init(CHIP_CONFIG_LIFETIIME_PERSISTED_COUNTER_KEY);
64 #endif
65
66     return CHIP_NO_ERROR;
67 }
68
69 template <class ImplClass>
70 CHIP_ERROR GenericConfigurationManagerImpl<ImplClass>::_ConfigureChipStack()
71 {
72     CHIP_ERROR err = CHIP_NO_ERROR;
73
74 #if CHIP_CONFIG_ENABLE_FABRIC_STATE
75     size_t pairingCodeLen;
76
77     static char sPairingCodeBuf[ConfigurationManager::kMaxPairingCodeLength + 1];
78
79     // Configure the CHIP FabricState object with the local node id.
80     err = Impl()->_GetDeviceId(FabricState.LocalNodeId);
81     SuccessOrExit(err);
82
83     // Configure the FabricState object with the pairing code string, if present.
84     err = Impl()->_GetPairingCode(sPairingCodeBuf, sizeof(sPairingCodeBuf), pairingCodeLen);
85     if (err != CHIP_DEVICE_ERROR_CONFIG_NOT_FOUND)
86     {
87         SuccessOrExit(err);
88         FabricState.PairingCode = sPairingCodeBuf;
89     }
90
91     // If the device is a member of a CHIP fabric, configure the FabricState object with the fabric id.
92     err = Impl()->_GetFabricId(FabricState.FabricId);
93     if (err == CHIP_DEVICE_ERROR_CONFIG_NOT_FOUND)
94     {
95         FabricState.FabricId = kFabricIdNotSpecified;
96         err                  = CHIP_NO_ERROR;
97     }
98     SuccessOrExit(err);
99 #endif // CHIP_CONFIG_ENABLE_FABRIC_STATE
100
101 #if CHIP_PROGRESS_LOGGING
102
103     Impl()->_LogDeviceConfig();
104
105 #if CHIP_DEVICE_CONFIG_LOG_PROVISIONING_HASH
106     {
107         uint8_t provHash[chip::Crypto::kSHA256_Hash_Length];
108         char provHashBase64[BASE64_ENCODED_LEN(sizeof(provHash)) + 1];
109         err = Impl()->_ComputeProvisioningHash(provHash, sizeof(provHash));
110         if (err == CHIP_NO_ERROR)
111         {
112             Base64Encode(provHash, sizeof(provHash), provHashBase64);
113             provHashBase64[sizeof(provHashBase64) - 1] = '\0';
114             ChipLogProgress(DeviceLayer, "CHIP Provisioning Hash: %s", provHashBase64);
115         }
116         else
117         {
118             ChipLogError(DeviceLayer, "Error generating CHIP Provisioning Hash: %s", chip::ErrorStr(err));
119             err = CHIP_NO_ERROR;
120         }
121     }
122 #endif // CHIP_DEVICE_CONFIG_LOG_PROVISIONING_HASH
123
124 #endif // CHIP_PROGRESS_LOGGING
125
126     SuccessOrExit(err);
127
128 exit:
129     return err;
130 }
131
132 template <class ImplClass>
133 CHIP_ERROR GenericConfigurationManagerImpl<ImplClass>::_GetFirmwareRevision(char * buf, size_t bufSize, size_t & outLen)
134 {
135 #ifdef CHIP_DEVICE_CONFIG_DEVICE_FIRMWARE_REVISION
136     if (CHIP_DEVICE_CONFIG_DEVICE_FIRMWARE_REVISION[0] != 0)
137     {
138         outLen = min(bufSize, sizeof(CHIP_DEVICE_CONFIG_DEVICE_FIRMWARE_REVISION) - 1);
139         memcpy(buf, CHIP_DEVICE_CONFIG_DEVICE_FIRMWARE_REVISION, outLen);
140         return CHIP_NO_ERROR;
141     }
142 #endif // CHIP_DEVICE_CONFIG_DEVICE_FIRMWARE_REVISION
143
144     outLen = 0;
145     return CHIP_DEVICE_ERROR_CONFIG_NOT_FOUND;
146 }
147
148 template <class ImplClass>
149 CHIP_ERROR GenericConfigurationManagerImpl<ImplClass>::_GetFirmwareBuildTime(uint16_t & year, uint8_t & month, uint8_t & dayOfMonth,
150                                                                              uint8_t & hour, uint8_t & minute, uint8_t & second)
151 {
152     CHIP_ERROR err = CHIP_NO_ERROR;
153
154     err = ParseCompilerDateStr(CHIP_DEVICE_CONFIG_FIRWMARE_BUILD_DATE, year, month, dayOfMonth);
155     SuccessOrExit(err);
156
157     err = Parse24HourTimeStr(CHIP_DEVICE_CONFIG_FIRMWARE_BUILD_TIME, hour, minute, second);
158     SuccessOrExit(err);
159
160 exit:
161     return err;
162 }
163
164 template <class ImplClass>
165 CHIP_ERROR GenericConfigurationManagerImpl<ImplClass>::_GetManufacturerDeviceId(uint64_t & deviceId)
166 {
167     CHIP_ERROR err;
168
169     err = Impl()->ReadConfigValue(ImplClass::kConfigKey_MfrDeviceId, deviceId);
170
171 #if CHIP_DEVICE_CONFIG_ENABLE_TEST_DEVICE_IDENTITY
172     if (err == CHIP_DEVICE_ERROR_CONFIG_NOT_FOUND || err == CHIP_ERROR_KEY_NOT_FOUND)
173     {
174         deviceId = TestDeviceId;
175         err      = CHIP_NO_ERROR;
176     }
177 #endif
178
179     return err;
180 }
181
182 template <class ImplClass>
183 CHIP_ERROR GenericConfigurationManagerImpl<ImplClass>::_StoreManufacturerDeviceId(uint64_t deviceId)
184 {
185     return Impl()->WriteConfigValue(ImplClass::kConfigKey_MfrDeviceId, deviceId);
186 }
187
188 template <class ImplClass>
189 CHIP_ERROR GenericConfigurationManagerImpl<ImplClass>::_GetSerialNumber(char * buf, size_t bufSize, size_t & serialNumLen)
190 {
191     CHIP_ERROR err;
192
193     err = Impl()->ReadConfigValueStr(ImplClass::kConfigKey_SerialNum, buf, bufSize, serialNumLen);
194 #ifdef CHIP_DEVICE_CONFIG_TEST_SERIAL_NUMBER
195     if (CHIP_DEVICE_CONFIG_TEST_SERIAL_NUMBER[0] != 0 && err == CHIP_DEVICE_ERROR_CONFIG_NOT_FOUND)
196     {
197         VerifyOrExit(sizeof(CHIP_DEVICE_CONFIG_TEST_SERIAL_NUMBER) <= bufSize, err = CHIP_ERROR_BUFFER_TOO_SMALL);
198         memcpy(buf, CHIP_DEVICE_CONFIG_TEST_SERIAL_NUMBER, sizeof(CHIP_DEVICE_CONFIG_TEST_SERIAL_NUMBER));
199         serialNumLen = sizeof(CHIP_DEVICE_CONFIG_TEST_SERIAL_NUMBER) - 1;
200         err          = CHIP_NO_ERROR;
201     }
202 #endif // CHIP_DEVICE_CONFIG_TEST_SERIAL_NUMBER
203     SuccessOrExit(err);
204
205 exit:
206     return err;
207 }
208
209 template <class ImplClass>
210 CHIP_ERROR GenericConfigurationManagerImpl<ImplClass>::_StoreSerialNumber(const char * serialNum, size_t serialNumLen)
211 {
212     return Impl()->WriteConfigValueStr(ImplClass::kConfigKey_SerialNum, serialNum, serialNumLen);
213 }
214
215 template <class ImplClass>
216 CHIP_ERROR GenericConfigurationManagerImpl<ImplClass>::_GetPrimaryWiFiMACAddress(uint8_t * buf)
217 {
218     return CHIP_DEVICE_ERROR_CONFIG_NOT_FOUND;
219 }
220
221 template <class ImplClass>
222 CHIP_ERROR GenericConfigurationManagerImpl<ImplClass>::_StorePrimaryWiFiMACAddress(const uint8_t * buf)
223 {
224     return CHIP_ERROR_UNSUPPORTED_CHIP_FEATURE;
225 }
226
227 template <class ImplClass>
228 CHIP_ERROR GenericConfigurationManagerImpl<ImplClass>::_GetPrimary802154MACAddress(uint8_t * buf)
229 {
230 #if CHIP_DEVICE_CONFIG_ENABLE_THREAD
231     return ThreadStackManager().GetPrimary802154MACAddress(buf);
232 #else
233     return CHIP_DEVICE_ERROR_CONFIG_NOT_FOUND;
234 #endif // CHIP_DEVICE_CONFIG_ENABLE_THREAD
235 }
236
237 template <class ImplClass>
238 CHIP_ERROR GenericConfigurationManagerImpl<ImplClass>::_StorePrimary802154MACAddress(const uint8_t * buf)
239 {
240     return CHIP_ERROR_UNSUPPORTED_CHIP_FEATURE;
241 }
242
243 template <class ImplClass>
244 inline CHIP_ERROR GenericConfigurationManagerImpl<ImplClass>::_GetProductRevision(uint16_t & productRev)
245 {
246     CHIP_ERROR err;
247     uint32_t val;
248
249     err = Impl()->ReadConfigValue(ImplClass::kConfigKey_ProductRevision, val);
250     if (err == CHIP_DEVICE_ERROR_CONFIG_NOT_FOUND)
251     {
252         productRev = static_cast<uint16_t>(CHIP_DEVICE_CONFIG_DEFAULT_DEVICE_PRODUCT_REVISION);
253         err        = CHIP_NO_ERROR;
254     }
255     else
256     {
257         productRev = static_cast<uint16_t>(val);
258     }
259
260     return err;
261 }
262
263 template <class ImplClass>
264 inline CHIP_ERROR GenericConfigurationManagerImpl<ImplClass>::_StoreProductRevision(uint16_t productRev)
265 {
266     return Impl()->WriteConfigValue(ImplClass::kConfigKey_ProductRevision, static_cast<uint32_t>(productRev));
267 }
268
269 template <class ImplClass>
270 CHIP_ERROR GenericConfigurationManagerImpl<ImplClass>::_GetManufacturingDate(uint16_t & year, uint8_t & month, uint8_t & dayOfMonth)
271 {
272     CHIP_ERROR err;
273     enum
274     {
275         kDateStringLength = 10 // YYYY-MM-DD
276     };
277     char dateStr[kDateStringLength + 1];
278     size_t dateLen;
279     char * parseEnd;
280
281     err = Impl()->ReadConfigValueStr(ImplClass::kConfigKey_ManufacturingDate, dateStr, sizeof(dateStr), dateLen);
282     SuccessOrExit(err);
283
284     VerifyOrExit(dateLen == kDateStringLength, err = CHIP_ERROR_INVALID_ARGUMENT);
285
286     // Cast does not lose information, because we then check that we only parsed
287     // 4 digits, so our number can't be bigger than 9999.
288     year = static_cast<uint16_t>(strtoul(dateStr, &parseEnd, 10));
289     VerifyOrExit(parseEnd == dateStr + 4, err = CHIP_ERROR_INVALID_ARGUMENT);
290
291     // Cast does not lose information, because we then check that we only parsed
292     // 2 digits, so our number can't be bigger than 99.
293     month = static_cast<uint8_t>(strtoul(dateStr + 5, &parseEnd, 10));
294     VerifyOrExit(parseEnd == dateStr + 7, err = CHIP_ERROR_INVALID_ARGUMENT);
295
296     // Cast does not lose information, because we then check that we only parsed
297     // 2 digits, so our number can't be bigger than 99.
298     dayOfMonth = static_cast<uint8_t>(strtoul(dateStr + 8, &parseEnd, 10));
299     VerifyOrExit(parseEnd == dateStr + 10, err = CHIP_ERROR_INVALID_ARGUMENT);
300
301 exit:
302     if (err != CHIP_NO_ERROR && err != CHIP_DEVICE_ERROR_CONFIG_NOT_FOUND)
303     {
304         ChipLogError(DeviceLayer, "Invalid manufacturing date: %s", dateStr);
305     }
306     return err;
307 }
308
309 template <class ImplClass>
310 CHIP_ERROR GenericConfigurationManagerImpl<ImplClass>::_StoreManufacturingDate(const char * mfgDate, size_t mfgDateLen)
311 {
312     return Impl()->WriteConfigValueStr(ImplClass::kConfigKey_ManufacturingDate, mfgDate, mfgDateLen);
313 }
314
315 template <class ImplClass>
316 CHIP_ERROR GenericConfigurationManagerImpl<ImplClass>::_GetManufacturerDeviceCertificate(uint8_t * buf, size_t bufSize,
317                                                                                          size_t & certLen)
318 {
319     CHIP_ERROR err;
320
321     err = Impl()->ReadConfigValueBin(ImplClass::kConfigKey_MfrDeviceCert, buf, bufSize, certLen);
322
323 #if CHIP_DEVICE_CONFIG_ENABLE_TEST_DEVICE_IDENTITY
324
325     if (err == CHIP_DEVICE_ERROR_CONFIG_NOT_FOUND)
326     {
327         certLen = TestDeviceCertLength;
328         VerifyOrExit(buf != NULL, err = CHIP_NO_ERROR);
329         VerifyOrExit(TestDeviceCertLength <= bufSize, err = CHIP_ERROR_BUFFER_TOO_SMALL);
330         memcpy(buf, TestDeviceCert, TestDeviceCertLength);
331         err = CHIP_NO_ERROR;
332     }
333
334 #endif // CHIP_DEVICE_CONFIG_ENABLE_TEST_DEVICE_IDENTITY
335
336     SuccessOrExit(err);
337
338 exit:
339     return err;
340 }
341
342 template <class ImplClass>
343 CHIP_ERROR GenericConfigurationManagerImpl<ImplClass>::_StoreManufacturerDeviceCertificate(const uint8_t * cert, size_t certLen)
344 {
345     return Impl()->WriteConfigValueBin(ImplClass::kConfigKey_MfrDeviceCert, cert, certLen);
346 }
347
348 template <class ImplClass>
349 CHIP_ERROR GenericConfigurationManagerImpl<ImplClass>::_GetManufacturerDeviceIntermediateCACerts(uint8_t * buf, size_t bufSize,
350                                                                                                  size_t & certsLen)
351 {
352     CHIP_ERROR err;
353
354     err = Impl()->ReadConfigValueBin(ImplClass::kConfigKey_MfrDeviceICACerts, buf, bufSize, certsLen);
355
356 #if CHIP_DEVICE_CONFIG_ENABLE_TEST_DEVICE_IDENTITY
357
358     if (err == CHIP_DEVICE_ERROR_CONFIG_NOT_FOUND)
359     {
360         certsLen = TestDeviceIntermediateCACertLength;
361         VerifyOrExit(buf != NULL, err = CHIP_NO_ERROR);
362         VerifyOrExit(TestDeviceIntermediateCACertLength <= bufSize, err = CHIP_ERROR_BUFFER_TOO_SMALL);
363         memcpy(buf, TestDeviceIntermediateCACert, TestDeviceIntermediateCACertLength);
364         err = CHIP_NO_ERROR;
365     }
366
367 #endif // CHIP_DEVICE_CONFIG_ENABLE_TEST_DEVICE_IDENTITY
368
369     SuccessOrExit(err);
370
371 exit:
372     return err;
373 }
374
375 template <class ImplClass>
376 CHIP_ERROR GenericConfigurationManagerImpl<ImplClass>::_StoreManufacturerDeviceIntermediateCACerts(const uint8_t * certs,
377                                                                                                    size_t certsLen)
378 {
379     return Impl()->WriteConfigValueBin(ImplClass::kConfigKey_MfrDeviceICACerts, certs, certsLen);
380 }
381
382 template <class ImplClass>
383 CHIP_ERROR GenericConfigurationManagerImpl<ImplClass>::_GetManufacturerDevicePrivateKey(uint8_t * buf, size_t bufSize,
384                                                                                         size_t & keyLen)
385 {
386     CHIP_ERROR err;
387
388     err = Impl()->ReadConfigValueBin(ImplClass::kConfigKey_MfrDevicePrivateKey, buf, bufSize, keyLen);
389
390 #if CHIP_DEVICE_CONFIG_ENABLE_TEST_DEVICE_IDENTITY
391
392     if (err == CHIP_DEVICE_ERROR_CONFIG_NOT_FOUND)
393     {
394         keyLen = TestDevicePrivateKeyLength;
395         VerifyOrExit(buf != NULL, err = CHIP_NO_ERROR);
396         VerifyOrExit(TestDevicePrivateKeyLength <= bufSize, err = CHIP_ERROR_BUFFER_TOO_SMALL);
397         memcpy(buf, TestDevicePrivateKey, TestDevicePrivateKeyLength);
398         err = CHIP_NO_ERROR;
399     }
400
401 #endif // CHIP_DEVICE_CONFIG_ENABLE_TEST_DEVICE_IDENTITY
402
403     SuccessOrExit(err);
404
405 exit:
406     return err;
407 }
408
409 template <class ImplClass>
410 CHIP_ERROR GenericConfigurationManagerImpl<ImplClass>::_StoreManufacturerDevicePrivateKey(const uint8_t * key, size_t keyLen)
411 {
412     return Impl()->WriteConfigValueBin(ImplClass::kConfigKey_MfrDevicePrivateKey, key, keyLen);
413 }
414
415 template <class ImplClass>
416 CHIP_ERROR GenericConfigurationManagerImpl<ImplClass>::_GetDeviceId(uint64_t & deviceId)
417 {
418     CHIP_ERROR err;
419
420 #if CHIP_DEVICE_CONFIG_ENABLE_JUST_IN_TIME_PROVISIONING
421     if (!UseManufacturerCredentialsAsOperational())
422     {
423         err = Impl()->ReadConfigValue(ImplClass::kConfigKey_OperationalDeviceId, deviceId);
424     }
425     else
426 #endif
427     {
428         err = Impl()->_GetManufacturerDeviceId(deviceId);
429     }
430
431     return err;
432 }
433
434 template <class ImplClass>
435 CHIP_ERROR GenericConfigurationManagerImpl<ImplClass>::_GetDeviceCertificate(uint8_t * buf, size_t bufSize, size_t & certLen)
436 {
437     CHIP_ERROR err;
438
439 #if CHIP_DEVICE_CONFIG_ENABLE_JUST_IN_TIME_PROVISIONING
440     if (!UseManufacturerCredentialsAsOperational())
441     {
442         err = Impl()->ReadConfigValueBin(ImplClass::kConfigKey_OperationalDeviceCert, buf, bufSize, certLen);
443     }
444     else
445 #endif
446     {
447         err = Impl()->_GetManufacturerDeviceCertificate(buf, bufSize, certLen);
448     }
449
450     return err;
451 }
452
453 template <class ImplClass>
454 CHIP_ERROR GenericConfigurationManagerImpl<ImplClass>::_GetDeviceIntermediateCACerts(uint8_t * buf, size_t bufSize,
455                                                                                      size_t & certsLen)
456 {
457     CHIP_ERROR err;
458
459 #if CHIP_DEVICE_CONFIG_ENABLE_JUST_IN_TIME_PROVISIONING
460     if (!UseManufacturerCredentialsAsOperational())
461     {
462         err = Impl()->ReadConfigValueBin(ImplClass::kConfigKey_OperationalDeviceICACerts, buf, bufSize, certsLen);
463     }
464     else
465 #endif
466     {
467         err = Impl()->_GetManufacturerDeviceIntermediateCACerts(buf, bufSize, certsLen);
468     }
469
470     return err;
471 }
472
473 template <class ImplClass>
474 CHIP_ERROR GenericConfigurationManagerImpl<ImplClass>::_GetDevicePrivateKey(uint8_t * buf, size_t bufSize, size_t & keyLen)
475 {
476     CHIP_ERROR err;
477
478 #if CHIP_DEVICE_CONFIG_ENABLE_JUST_IN_TIME_PROVISIONING
479     if (!UseManufacturerCredentialsAsOperational())
480     {
481         err = Impl()->ReadConfigValueBin(ImplClass::kConfigKey_OperationalDevicePrivateKey, buf, bufSize, keyLen);
482     }
483     else
484 #endif
485     {
486         err = Impl()->_GetManufacturerDevicePrivateKey(buf, bufSize, keyLen);
487     }
488
489     return err;
490 }
491
492 #if CHIP_DEVICE_CONFIG_ENABLE_JUST_IN_TIME_PROVISIONING
493
494 template <class ImplClass>
495 CHIP_ERROR GenericConfigurationManagerImpl<ImplClass>::_StoreDeviceId(uint64_t deviceId)
496 {
497     return Impl()->WriteConfigValue(ImplClass::kConfigKey_OperationalDeviceId, deviceId);
498 }
499
500 template <class ImplClass>
501 CHIP_ERROR GenericConfigurationManagerImpl<ImplClass>::_StoreDeviceCertificate(const uint8_t * cert, size_t certLen)
502 {
503     return Impl()->WriteConfigValueBin(ImplClass::kConfigKey_OperationalDeviceCert, cert, certLen);
504 }
505
506 template <class ImplClass>
507 CHIP_ERROR GenericConfigurationManagerImpl<ImplClass>::_StoreDeviceIntermediateCACerts(const uint8_t * certs, size_t certsLen)
508 {
509     return Impl()->WriteConfigValueBin(ImplClass::kConfigKey_OperationalDeviceICACerts, certs, certsLen);
510 }
511
512 template <class ImplClass>
513 CHIP_ERROR GenericConfigurationManagerImpl<ImplClass>::_StoreDevicePrivateKey(const uint8_t * key, size_t keyLen)
514 {
515     return Impl()->WriteConfigValueBin(ImplClass::kConfigKey_OperationalDevicePrivateKey, key, keyLen);
516 }
517
518 template <class ImplClass>
519 CHIP_ERROR GenericConfigurationManagerImpl<ImplClass>::_ClearOperationalDeviceCredentials(void)
520 {
521     Impl()->ClearConfigValue(ImplClass::kConfigKey_OperationalDeviceId);
522     Impl()->ClearConfigValue(ImplClass::kConfigKey_OperationalDeviceCert);
523     Impl()->ClearConfigValue(ImplClass::kConfigKey_OperationalDeviceICACerts);
524     Impl()->ClearConfigValue(ImplClass::kConfigKey_OperationalDevicePrivateKey);
525
526     mFlags.Clear(Flags::kOperationalDeviceCredentialsProvisioned);
527
528     return CHIP_NO_ERROR;
529 }
530
531 template <class ImplClass>
532 bool GenericConfigurationManagerImpl<ImplClass>::_OperationalDeviceCredentialsProvisioned()
533 {
534     return mFlags.Has(Flags::kOperationalDeviceCredentialsProvisioned);
535 }
536
537 template <class ImplClass>
538 bool GenericConfigurationManagerImpl<ImplClass>::UseManufacturerCredentialsAsOperational()
539 {
540     return mFlags.Has(Flags::kUseManufacturerCredentialsAsOperational);
541 }
542
543 template <class ImplClass>
544 void GenericConfigurationManagerImpl<ImplClass>::_UseManufacturerCredentialsAsOperational(bool val)
545 {
546     mFlags.Set(Flags::kUseManufacturerCredentialsAsOperational, val);
547 }
548
549 #endif // CHIP_DEVICE_CONFIG_ENABLE_JUST_IN_TIME_PROVISIONING
550
551 template <class ImplClass>
552 CHIP_ERROR GenericConfigurationManagerImpl<ImplClass>::_GetSetupPinCode(uint32_t & setupPinCode)
553 {
554     CHIP_ERROR err;
555
556     err = Impl()->ReadConfigValue(ImplClass::kConfigKey_SetupPinCode, setupPinCode);
557 #if defined(CHIP_DEVICE_CONFIG_USE_TEST_SETUP_PIN_CODE) && CHIP_DEVICE_CONFIG_USE_TEST_SETUP_PIN_CODE
558     if (err == CHIP_DEVICE_ERROR_CONFIG_NOT_FOUND)
559     {
560         setupPinCode = CHIP_DEVICE_CONFIG_USE_TEST_SETUP_PIN_CODE;
561         err          = CHIP_NO_ERROR;
562     }
563 #endif // defined(CHIP_DEVICE_CONFIG_USE_TEST_SETUP_PIN_CODE) && CHIP_DEVICE_CONFIG_USE_TEST_SETUP_PIN_CODE
564     SuccessOrExit(err);
565
566 exit:
567     return err;
568 }
569
570 template <class ImplClass>
571 CHIP_ERROR GenericConfigurationManagerImpl<ImplClass>::_StoreSetupPinCode(uint32_t setupPinCode)
572 {
573     return Impl()->WriteConfigValue(ImplClass::kConfigKey_SetupPinCode, setupPinCode);
574 }
575
576 template <class ImplClass>
577 CHIP_ERROR GenericConfigurationManagerImpl<ImplClass>::_GetSetupDiscriminator(uint16_t & setupDiscriminator)
578 {
579     CHIP_ERROR err;
580     uint32_t val;
581
582     err = Impl()->ReadConfigValue(ImplClass::kConfigKey_SetupDiscriminator, val);
583 #if defined(CHIP_DEVICE_CONFIG_USE_TEST_SETUP_DISCRIMINATOR) && CHIP_DEVICE_CONFIG_USE_TEST_SETUP_DISCRIMINATOR
584     if (err == CHIP_DEVICE_ERROR_CONFIG_NOT_FOUND)
585     {
586         val = CHIP_DEVICE_CONFIG_USE_TEST_SETUP_DISCRIMINATOR;
587         err = CHIP_NO_ERROR;
588     }
589 #endif // defined(CHIP_DEVICE_CONFIG_USE_TEST_SETUP_DISCRIMINATOR) && CHIP_DEVICE_CONFIG_USE_TEST_SETUP_DISCRIMINATOR
590     SuccessOrExit(err);
591
592     setupDiscriminator = static_cast<uint16_t>(val);
593
594 exit:
595     return err;
596 }
597
598 template <class ImplClass>
599 CHIP_ERROR GenericConfigurationManagerImpl<ImplClass>::_StoreSetupDiscriminator(uint16_t setupDiscriminator)
600 {
601     return Impl()->WriteConfigValue(ImplClass::kConfigKey_SetupDiscriminator, static_cast<uint32_t>(setupDiscriminator));
602 }
603
604 template <class ImplClass>
605 CHIP_ERROR GenericConfigurationManagerImpl<ImplClass>::_GetFabricId(uint64_t & fabricId)
606 {
607     CHIP_ERROR err = Impl()->ReadConfigValue(ImplClass::kConfigKey_FabricId, fabricId);
608
609 #if CHIP_DEVICE_CONFIG_ENABLE_TEST_DEVICE_IDENTITY
610     if (err == CHIP_DEVICE_ERROR_CONFIG_NOT_FOUND || err == CHIP_ERROR_KEY_NOT_FOUND)
611     {
612         fabricId = TestFabricId;
613         err      = CHIP_NO_ERROR;
614     }
615 #endif // CHIP_DEVICE_CONFIG_ENABLE_TEST_DEVICE_IDENTITY
616     return err;
617 }
618
619 template <class ImplClass>
620 CHIP_ERROR GenericConfigurationManagerImpl<ImplClass>::_StoreFabricId(uint64_t fabricId)
621 {
622     CHIP_ERROR err = CHIP_NO_ERROR;
623
624 #if CHIP_CONFIG_ENABLE_FABRIC_STATE
625     if (fabricId != kFabricIdNotSpecified)
626     {
627         err = Impl()->WriteConfigValue(ImplClass::kConfigKey_FabricId, fabricId);
628         SuccessOrExit(err);
629         mFlags.Set(Flags::kIsMemberOfFabric);
630     }
631     else
632     {
633         mFlags.Clear(Flags::kIsMemberOfFabric);
634         err = Impl()->ClearConfigValue(ImplClass::kConfigKey_FabricId);
635         SuccessOrExit(err);
636     }
637
638 exit:
639 #endif
640
641     return err;
642 }
643
644 template <class ImplClass>
645 CHIP_ERROR GenericConfigurationManagerImpl<ImplClass>::_GetServiceId(uint64_t & serviceId)
646 {
647     return Impl()->ReadConfigValue(ImplClass::kConfigKey_ServiceId, serviceId);
648 }
649
650 template <class ImplClass>
651 CHIP_ERROR GenericConfigurationManagerImpl<ImplClass>::_GetServiceConfig(uint8_t * buf, size_t bufSize, size_t & serviceConfigLen)
652 {
653     return Impl()->ReadConfigValueBin(ImplClass::kConfigKey_ServiceConfig, buf, bufSize, serviceConfigLen);
654 }
655
656 template <class ImplClass>
657 CHIP_ERROR GenericConfigurationManagerImpl<ImplClass>::_StoreServiceConfig(const uint8_t * serviceConfig, size_t serviceConfigLen)
658 {
659     return Impl()->WriteConfigValueBin(ImplClass::kConfigKey_ServiceConfig, serviceConfig, serviceConfigLen);
660 }
661
662 #if CHIP_ENABLE_ROTATING_DEVICE_ID
663 template <class ImplClass>
664 CHIP_ERROR GenericConfigurationManagerImpl<ImplClass>::_GetLifetimeCounter(uint16_t & lifetimeCounter)
665 {
666     lifetimeCounter = static_cast<uint16_t>(mLifetimePersistedCounter.GetValue());
667     return CHIP_NO_ERROR;
668 }
669
670 template <class ImplClass>
671 CHIP_ERROR GenericConfigurationManagerImpl<ImplClass>::_IncrementLifetimeCounter()
672 {
673     return mLifetimePersistedCounter.Advance();
674 }
675 #endif
676
677 template <class ImplClass>
678 CHIP_ERROR GenericConfigurationManagerImpl<ImplClass>::_GetPairedAccountId(char * buf, size_t bufSize, size_t & accountIdLen)
679 {
680     return Impl()->ReadConfigValueStr(ImplClass::kConfigKey_PairedAccountId, buf, bufSize, accountIdLen);
681 }
682
683 template <class ImplClass>
684 CHIP_ERROR GenericConfigurationManagerImpl<ImplClass>::_StorePairedAccountId(const char * accountId, size_t accountIdLen)
685 {
686     CHIP_ERROR err;
687
688     err = Impl()->WriteConfigValueStr(ImplClass::kConfigKey_PairedAccountId, accountId, accountIdLen);
689     SuccessOrExit(err);
690
691     mFlags.Set(Flags::kIsPairedToAccount, (accountId != nullptr && accountIdLen != 0));
692
693 exit:
694     return err;
695 }
696
697 template <class ImplClass>
698 CHIP_ERROR GenericConfigurationManagerImpl<ImplClass>::_StoreServiceProvisioningData(uint64_t serviceId,
699                                                                                      const uint8_t * serviceConfig,
700                                                                                      size_t serviceConfigLen,
701                                                                                      const char * accountId, size_t accountIdLen)
702 {
703     CHIP_ERROR err;
704
705     err = Impl()->WriteConfigValue(ImplClass::kConfigKey_ServiceId, serviceId);
706     SuccessOrExit(err);
707
708     err = _StoreServiceConfig(serviceConfig, serviceConfigLen);
709     SuccessOrExit(err);
710
711     err = _StorePairedAccountId(accountId, accountIdLen);
712     SuccessOrExit(err);
713
714     mFlags.Set(Flags::kIsServiceProvisioned);
715     mFlags.Set(Flags::kIsPairedToAccount, (accountId != nullptr && accountIdLen != 0));
716
717 exit:
718     if (err != CHIP_NO_ERROR)
719     {
720         Impl()->ClearConfigValue(ImplClass::kConfigKey_ServiceId);
721         Impl()->ClearConfigValue(ImplClass::kConfigKey_ServiceConfig);
722         Impl()->ClearConfigValue(ImplClass::kConfigKey_PairedAccountId);
723         mFlags.Clear(Flags::kIsServiceProvisioned);
724         mFlags.Clear(Flags::kIsPairedToAccount);
725     }
726     return err;
727 }
728
729 template <class ImplClass>
730 CHIP_ERROR GenericConfigurationManagerImpl<ImplClass>::_ClearServiceProvisioningData()
731 {
732     Impl()->ClearConfigValue(ImplClass::kConfigKey_ServiceId);
733     Impl()->ClearConfigValue(ImplClass::kConfigKey_ServiceConfig);
734     Impl()->ClearConfigValue(ImplClass::kConfigKey_PairedAccountId);
735
736     // TODO: Move these behaviors out of configuration manager.
737
738     // If necessary, post an event alerting other subsystems to the change in
739     // the account pairing state.
740     if (_IsPairedToAccount())
741     {
742         ChipDeviceEvent event;
743         event.Type                                   = DeviceEventType::kAccountPairingChange;
744         event.AccountPairingChange.IsPairedToAccount = false;
745         PlatformMgr().PostEvent(&event);
746     }
747
748     // If necessary, post an event alerting other subsystems to the change in
749     // the service provisioning state.
750     if (_IsServiceProvisioned())
751     {
752         ChipDeviceEvent event;
753         event.Type                                           = DeviceEventType::kServiceProvisioningChange;
754         event.ServiceProvisioningChange.IsServiceProvisioned = false;
755         event.ServiceProvisioningChange.ServiceConfigUpdated = false;
756         PlatformMgr().PostEvent(&event);
757     }
758
759     mFlags.Clear(Flags::kIsServiceProvisioned);
760     mFlags.Clear(Flags::kIsPairedToAccount);
761
762     return CHIP_NO_ERROR;
763 }
764
765 template <class ImplClass>
766 CHIP_ERROR GenericConfigurationManagerImpl<ImplClass>::_GetFailSafeArmed(bool & val)
767 {
768     return Impl()->ReadConfigValue(ImplClass::kConfigKey_FailSafeArmed, val);
769 }
770
771 template <class ImplClass>
772 CHIP_ERROR GenericConfigurationManagerImpl<ImplClass>::_SetFailSafeArmed(bool val)
773 {
774     return Impl()->WriteConfigValue(ImplClass::kConfigKey_FailSafeArmed, val);
775 }
776
777 template <class ImplClass>
778 CHIP_ERROR GenericConfigurationManagerImpl<ImplClass>::_GetQRCodeString(char * buf, size_t bufSize)
779 {
780     return CHIP_ERROR_NOT_IMPLEMENTED;
781 }
782
783 template <class ImplClass>
784 CHIP_ERROR GenericConfigurationManagerImpl<ImplClass>::_GetWiFiAPSSID(char * buf, size_t bufSize)
785 {
786     CHIP_ERROR err;
787
788 #ifdef CHIP_DEVICE_CONFIG_WIFI_AP_SSID_PREFIX
789
790     uint8_t mac[6];
791
792     VerifyOrExit(bufSize >= sizeof(CHIP_DEVICE_CONFIG_WIFI_AP_SSID_PREFIX) + 4, err = CHIP_ERROR_BUFFER_TOO_SMALL);
793
794     err = Impl()->_GetPrimaryWiFiMACAddress(mac);
795     SuccessOrExit(err);
796
797     snprintf(buf, bufSize, "%s%02X%02X", CHIP_DEVICE_CONFIG_WIFI_AP_SSID_PREFIX, mac[4], mac[5]);
798     buf[bufSize - 1] = 0;
799
800 #else // CHIP_DEVICE_CONFIG_WIFI_AP_SSID_PREFIX
801
802     ExitNow(err = CHIP_DEVICE_ERROR_CONFIG_NOT_FOUND);
803
804 #endif // CHIP_DEVICE_CONFIG_WIFI_AP_SSID_PREFIX
805
806 exit:
807     return err;
808 }
809
810 template <class ImplClass>
811 CHIP_ERROR
812 GenericConfigurationManagerImpl<ImplClass>::_GetBLEDeviceIdentificationInfo(Ble::ChipBLEDeviceIdentificationInfo & deviceIdInfo)
813 {
814     CHIP_ERROR err;
815     uint16_t id;
816     uint16_t discriminator;
817
818     deviceIdInfo.Init();
819
820     err = Impl()->_GetVendorId(id);
821     SuccessOrExit(err);
822     deviceIdInfo.SetVendorId(id);
823
824     err = Impl()->_GetProductId(id);
825     SuccessOrExit(err);
826     deviceIdInfo.SetProductId(id);
827
828     err = Impl()->_GetSetupDiscriminator(discriminator);
829     SuccessOrExit(err);
830     deviceIdInfo.SetDeviceDiscriminator(discriminator);
831
832     // TODO: Update when CHIP service/fabric provision is implemented
833 #if CHIP_DEVICE_CONFIG_ENABLE_THREAD
834     deviceIdInfo.PairingStatus = ThreadStackMgr().IsThreadAttached()
835         ? Ble::ChipBLEDeviceIdentificationInfo::kPairingStatus_Paired
836         : Ble::ChipBLEDeviceIdentificationInfo::kPairingStatus_Unpaired;
837 #elif CHIP_DEVICE_CONFIG_ENABLE_WIFI_STATION
838     deviceIdInfo.PairingStatus = ConnectivityMgr().IsWiFiStationConnected()
839         ? Ble::ChipBLEDeviceIdentificationInfo::kPairingStatus_Paired
840         : Ble::ChipBLEDeviceIdentificationInfo::kPairingStatus_Unpaired;
841 #else
842     deviceIdInfo.PairingStatus = Impl()->_IsPairedToAccount() ? Ble::ChipBLEDeviceIdentificationInfo::kPairingStatus_Paired
843                                                               : Ble::ChipBLEDeviceIdentificationInfo::kPairingStatus_Unpaired;
844 #endif
845
846 exit:
847     return err;
848 }
849
850 template <class ImplClass>
851 bool GenericConfigurationManagerImpl<ImplClass>::_IsServiceProvisioned()
852 {
853     return mFlags.Has(Flags::kIsServiceProvisioned);
854 }
855
856 template <class ImplClass>
857 bool GenericConfigurationManagerImpl<ImplClass>::_IsMemberOfFabric()
858 {
859     return mFlags.Has(Flags::kIsMemberOfFabric);
860 }
861
862 template <class ImplClass>
863 bool GenericConfigurationManagerImpl<ImplClass>::_IsPairedToAccount()
864 {
865     return mFlags.Has(Flags::kIsPairedToAccount);
866 }
867
868 template <class ImplClass>
869 bool GenericConfigurationManagerImpl<ImplClass>::_IsFullyProvisioned()
870 {
871 #if CHIP_BYPASS_RENDEZVOUS
872     return true;
873 #else // CHIP_BYPASS_RENDEZVOUS
874
875     return
876 #if CHIP_DEVICE_CONFIG_ENABLE_WIFI_STATION
877         ConnectivityMgr().IsWiFiStationProvisioned() &&
878 #endif
879 #if CHIP_DEVICE_CONFIG_ENABLE_THREAD
880         ConnectivityMgr().IsThreadProvisioned() &&
881 #endif
882 #if CHIP_DEVICE_CONFIG_ENABLE_JUST_IN_TIME_PROVISIONING
883         (!UseManufacturerCredentialsAsOperational() && _OperationalDeviceCredentialsProvisioned()) &&
884 #endif
885         // TODO: Add checks regarding fabric membership (IsMemberOfFabric()) and account pairing (IsPairedToAccount()),
886         // when functionalities will be implemented.
887         true;
888 #endif // CHIP_BYPASS_RENDEZVOUS
889 }
890
891 template <class ImplClass>
892 CHIP_ERROR GenericConfigurationManagerImpl<ImplClass>::_ComputeProvisioningHash(uint8_t * hashBuf, size_t hashBufSize)
893 {
894     CHIP_ERROR err = CHIP_NO_ERROR;
895
896 #if CHIP_DEVICE_CONFIG_LOG_PROVISIONING_HASH
897     using HashAlgo = chip::Crypto::Hash_SHA256_stream;
898
899     HashAlgo hash;
900     chip::Platform::ScopedMemoryBuffer dataBuf;
901     size_t dataBufSize;
902     constexpr uint16_t kLenFieldLen = 4; // 4 hex characters
903
904     VerifyOrExit(hashBufSize >= chip::Crypto::kSHA256_Hash_Length, err = CHIP_ERROR_BUFFER_TOO_SMALL);
905
906     // Compute a hash of the device's provisioning data.  The generated hash value confirms to the form
907     // described in the CHIP Chip: Factory Provisioning Specification.
908     //
909     // A CHIP provisioning hash is a SHA-256 hash of an ASCII string with the following format:
910     //
911     //     DDDDddddddddddddddddCCCCcccc…ccccIIIIiiii…iiiiKKKKkkkk…kkkkPPPPpppppp
912     //
913     // Where:
914     //     dddddddddddddddd is the CHIP node id for the device, encoded as a string of 16 uppercase hex digits.
915     //     cccc…cccc is the device CHIP certificate, in base-64 format.
916     //     iiii…iiii is the device intermediate CA certificates, in base-64 format (if provisioned).
917     //     kkkk…kkkk is the device private key, in base-64 format.
918     //     pppppp is the device pairing code, as ASCII characters.
919     //     DDDD is the length of the dddddddddddddddd field (the device id), represented as 4 uppercase hex digits.
920     //         Because the device id is always the same size, this field is always '0010'.
921     //     CCCC is the length of the cccc…cccc field (the device certificate), represented as 4 uppercase hex digits.
922     //     IIII is the length of the iiii…iiii field (the device intermediate CA certificates), represented as 4 uppercase hex
923     //     digits. KKKK is the length of the kkkk…kkkk field (the device private key), represented as 4 uppercase hex digits. PPPP
924     //     is the length of the pppppp field (the device pairing code), represented as 4 uppercase hex digits.
925
926     hash.Begin();
927
928     // Hash the device id
929     {
930         uint64_t deviceId;
931         constexpr uint16_t kDeviceIdLen = 16;           // 16 hex characters
932         char inputBuf[kLenFieldLen + kDeviceIdLen + 1]; // +1 for terminator
933
934         err = Impl()->_GetManufacturerDeviceId(deviceId);
935         SuccessOrExit(err);
936
937         snprintf(inputBuf, sizeof(inputBuf), "0010%016" PRIX64, deviceId);
938
939         hash.AddData((uint8_t *) inputBuf, kLenFieldLen + kDeviceIdLen);
940     }
941
942     // Hash the device certificate
943     {
944         size_t certLen;
945
946         // Determine the length of the device certificate.
947         err = Impl()->_GetManufacturerDeviceCertificate((uint8_t *) NULL, 0, certLen);
948         SuccessOrExit(err);
949
950         // Create a temporary buffer to hold the certificate.  (This will also be used for
951         // the private key).
952         dataBufSize = certLen;
953         VerifyOrExit(dataBuf.Alloc(dataBufSize), err = CHIP_ERROR_NO_MEMORY);
954
955         // Read the certificate.
956         err = Impl()->_GetManufacturerDeviceCertificate(dataBuf.Ptr<uint8_t>(), certLen, certLen);
957         SuccessOrExit(err);
958     }
959
960     // Hash the device intermediate CA certificates
961     if (Impl()->ConfigValueExists(ImplClass::kConfigKey_MfrDeviceICACerts))
962     {
963         size_t certsLen;
964
965         // Determine the length of the device intermediate CA certificates.
966         err = Impl()->_GetManufacturerDeviceIntermediateCACerts((uint8_t *) NULL, 0, certsLen);
967         SuccessOrExit(err);
968
969         // Allocate larger buffer to hold the intermediate CA certificates.
970         // (This will also be used for the private key).
971         if (certsLen > dataBufSize)
972         {
973             dataBufSize = certsLen;
974             VerifyOrExit(dataBuf.Alloc(dataBufSize), err = CHIP_ERROR_NO_MEMORY);
975         }
976
977         // Read the device intermediate CA certificates.
978         err = Impl()->_GetManufacturerDeviceIntermediateCACerts(dataBuf.Ptr<uint8_t>(), certsLen, certsLen);
979         SuccessOrExit(err);
980     }
981
982     // Hash the device private key
983     {
984         size_t keyLen;
985
986         // Determine the length of the device private key.
987         err = Impl()->_GetManufacturerDevicePrivateKey((uint8_t *) NULL, 0, keyLen);
988         SuccessOrExit(err);
989
990         // Read the private key.  (Note that we presume the buffer allocated to hold the certificate
991         // is big enough to hold the private key.  _GetDevicePrivateKey() will return an error in the
992         // unlikely event that this is not the case.)
993         err = Impl()->_GetManufacturerDevicePrivateKey(dataBuf.Ptr<uint8_t>(), dataBufSize, keyLen);
994         SuccessOrExit(err);
995     }
996
997     // Hash the device pairing code.  If the device does not have a pairing code, hash a zero-length value.
998     {
999         char pairingCode[ConfigurationManager::kMaxPairingCodeLength + 1]; // +1 for terminator
1000         char lenStr[kLenFieldLen + 1];                                     // +1 for terminator
1001         size_t pairingCodeLen;
1002
1003         err = Impl()->_GetPairingCode(pairingCode, sizeof(pairingCode), pairingCodeLen);
1004         if (err == CHIP_DEVICE_ERROR_CONFIG_NOT_FOUND)
1005         {
1006             pairingCodeLen = 0;
1007             err            = CHIP_NO_ERROR;
1008         }
1009         SuccessOrExit(err);
1010
1011         snprintf(lenStr, sizeof(lenStr), "%04" PRIX16, (uint16_t) pairingCodeLen);
1012
1013         hash.AddData((uint8_t *) lenStr, kLenFieldLen);
1014         hash.AddData((uint8_t *) pairingCode, pairingCodeLen);
1015     }
1016
1017     hash.Finish(hashBuf);
1018
1019 exit:
1020     if (dataBuf)
1021     {
1022         chip::Crypto::ClearSecretData(dataBuf.Ptr(), dataBufSize);
1023     }
1024 #endif // CHIP_DEVICE_CONFIG_LOG_PROVISIONING_HASH
1025
1026     return err;
1027 }
1028
1029 #if !defined(NDEBUG)
1030 template <class ImplClass>
1031 CHIP_ERROR GenericConfigurationManagerImpl<ImplClass>::_RunUnitTests()
1032 {
1033     ChipLogProgress(DeviceLayer, "Running configuration unit test");
1034     Impl()->RunConfigUnitTest();
1035
1036     return CHIP_NO_ERROR;
1037 }
1038 #endif
1039
1040 template <class ImplClass>
1041 void GenericConfigurationManagerImpl<ImplClass>::_LogDeviceConfig()
1042 {
1043     CHIP_ERROR err;
1044
1045     ChipLogProgress(DeviceLayer, "Device Configuration:");
1046
1047 #if CHIP_CONFIG_ENABLE_FABRIC_STATE
1048     ChipLogProgress(DeviceLayer, "  Device Id: %016" PRIX64, FabricState.LocalNodeId);
1049 #endif
1050
1051     {
1052         char serialNum[ConfigurationManager::kMaxSerialNumberLength + 1];
1053         size_t serialNumLen;
1054         err = Impl()->_GetSerialNumber(serialNum, sizeof(serialNum), serialNumLen);
1055         ChipLogProgress(DeviceLayer, "  Serial Number: %s", (err == CHIP_NO_ERROR) ? serialNum : "(not set)");
1056     }
1057
1058     {
1059         uint16_t vendorId;
1060         if (Impl()->_GetVendorId(vendorId) != CHIP_NO_ERROR)
1061         {
1062             vendorId = 0;
1063         }
1064         ChipLogProgress(DeviceLayer, "  Vendor Id: %" PRIu16 " (0x%" PRIX16 ")", vendorId, vendorId);
1065     }
1066
1067     {
1068         uint16_t productId;
1069         if (Impl()->_GetProductId(productId) != CHIP_NO_ERROR)
1070         {
1071             productId = 0;
1072         }
1073         ChipLogProgress(DeviceLayer, "  Product Id: %" PRIu16 " (0x%" PRIX16 ")", productId, productId);
1074     }
1075
1076     {
1077         uint16_t productRev;
1078         if (Impl()->_GetProductRevision(productRev) != CHIP_NO_ERROR)
1079         {
1080             productRev = 0;
1081         }
1082         ChipLogProgress(DeviceLayer, "  Product Revision: %" PRIu16, productRev);
1083     }
1084
1085     {
1086         uint32_t setupPINCode;
1087         if (Impl()->_GetSetupPinCode(setupPINCode) != CHIP_NO_ERROR)
1088         {
1089             setupPINCode = 0;
1090         }
1091         ChipLogProgress(DeviceLayer, "  Setup Pin Code: %" PRIu32 "", setupPINCode);
1092     }
1093
1094     {
1095         uint16_t setupDiscriminator;
1096         if (Impl()->_GetSetupDiscriminator(setupDiscriminator) != CHIP_NO_ERROR)
1097         {
1098             setupDiscriminator = 0;
1099         }
1100         ChipLogProgress(DeviceLayer, "  Setup Discriminator: %" PRIu16 " (0x%" PRIX16 ")", setupDiscriminator, setupDiscriminator);
1101     }
1102
1103     {
1104         uint16_t year;
1105         uint8_t month, dayOfMonth;
1106         err = Impl()->_GetManufacturingDate(year, month, dayOfMonth);
1107         if (err == CHIP_NO_ERROR)
1108         {
1109             ChipLogProgress(DeviceLayer, "  Manufacturing Date: %04" PRIu16 "/%02" PRIu8 "/%02" PRIu8, year, month, dayOfMonth);
1110         }
1111         else
1112         {
1113             ChipLogProgress(DeviceLayer, "  Manufacturing Date: (not set)");
1114         }
1115     }
1116
1117 #if CHIP_CONFIG_ENABLE_FABRIC_STATE
1118     if (FabricState.FabricId != kFabricIdNotSpecified)
1119     {
1120         ChipLogProgress(DeviceLayer, "  Fabric Id: %016" PRIX64, FabricState.FabricId);
1121     }
1122     else
1123     {
1124         ChipLogProgress(DeviceLayer, "  Fabric Id: (none)");
1125     }
1126
1127     ChipLogProgress(DeviceLayer, "  Pairing Code: %s", (FabricState.PairingCode != NULL) ? FabricState.PairingCode : "(none)");
1128 #endif // CHIP_CONFIG_ENABLE_FABRIC_STATE
1129 }
1130
1131 // Fully instantiate the generic implementation class in whatever compilation unit includes this file.
1132 template class GenericConfigurationManagerImpl<ConfigurationManagerImpl>;
1133
1134 } // namespace Internal
1135 } // namespace DeviceLayer
1136 } // namespace chip
1137
1138 #endif // GENERIC_CONFIGURATION_MANAGER_IMPL_CPP