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