3 * Copyright (c) 2020-2021 Project CHIP Authors
4 * Copyright (c) 2019-2020 Google LLC.
5 * Copyright (c) 2018 Nest Labs, Inc.
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
11 * http://www.apache.org/licenses/LICENSE-2.0
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.
22 * Contains non-inline method definitions for the
23 * GenericConfigurationManagerImpl<> template.
26 #ifndef GENERIC_CONFIGURATION_MANAGER_IMPL_CPP
27 #define GENERIC_CONFIGURATION_MANAGER_IMPL_CPP
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>
38 #if CHIP_DEVICE_CONFIG_ENABLE_THREAD
39 #include <platform/ThreadStackManager.h>
42 #if CHIP_DEVICE_CONFIG_LOG_PROVISIONING_HASH
43 #include <crypto/CHIPCryptoPAL.h>
47 namespace DeviceLayer {
50 template <class ImplClass>
51 CHIP_ERROR GenericConfigurationManagerImpl<ImplClass>::_Init()
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.
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));
62 #if CHIP_ENABLE_ROTATING_DEVICE_ID
63 mLifetimePersistedCounter.Init(CHIP_CONFIG_LIFETIIME_PERSISTED_COUNTER_KEY);
69 template <class ImplClass>
70 CHIP_ERROR GenericConfigurationManagerImpl<ImplClass>::_ConfigureChipStack()
72 CHIP_ERROR err = CHIP_NO_ERROR;
74 #if CHIP_CONFIG_ENABLE_FABRIC_STATE
75 size_t pairingCodeLen;
77 static char sPairingCodeBuf[ConfigurationManager::kMaxPairingCodeLength + 1];
79 // Configure the CHIP FabricState object with the local node id.
80 err = Impl()->_GetDeviceId(FabricState.LocalNodeId);
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)
88 FabricState.PairingCode = sPairingCodeBuf;
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)
95 FabricState.FabricId = kFabricIdNotSpecified;
99 #endif // CHIP_CONFIG_ENABLE_FABRIC_STATE
101 #if CHIP_PROGRESS_LOGGING
103 Impl()->_LogDeviceConfig();
105 #if CHIP_DEVICE_CONFIG_LOG_PROVISIONING_HASH
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)
112 Base64Encode(provHash, sizeof(provHash), provHashBase64);
113 provHashBase64[sizeof(provHashBase64) - 1] = '\0';
114 ChipLogProgress(DeviceLayer, "CHIP Provisioning Hash: %s", provHashBase64);
118 ChipLogError(DeviceLayer, "Error generating CHIP Provisioning Hash: %s", chip::ErrorStr(err));
122 #endif // CHIP_DEVICE_CONFIG_LOG_PROVISIONING_HASH
124 #endif // CHIP_PROGRESS_LOGGING
132 template <class ImplClass>
133 CHIP_ERROR GenericConfigurationManagerImpl<ImplClass>::_GetFirmwareRevision(char * buf, size_t bufSize, size_t & outLen)
135 #ifdef CHIP_DEVICE_CONFIG_DEVICE_FIRMWARE_REVISION
136 if (CHIP_DEVICE_CONFIG_DEVICE_FIRMWARE_REVISION[0] != 0)
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;
142 #endif // CHIP_DEVICE_CONFIG_DEVICE_FIRMWARE_REVISION
145 return CHIP_DEVICE_ERROR_CONFIG_NOT_FOUND;
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)
152 CHIP_ERROR err = CHIP_NO_ERROR;
154 err = ParseCompilerDateStr(CHIP_DEVICE_CONFIG_FIRWMARE_BUILD_DATE, year, month, dayOfMonth);
157 err = Parse24HourTimeStr(CHIP_DEVICE_CONFIG_FIRMWARE_BUILD_TIME, hour, minute, second);
164 template <class ImplClass>
165 CHIP_ERROR GenericConfigurationManagerImpl<ImplClass>::_GetManufacturerDeviceId(uint64_t & deviceId)
169 err = Impl()->ReadConfigValue(ImplClass::kConfigKey_MfrDeviceId, deviceId);
171 #if CHIP_DEVICE_CONFIG_ENABLE_TEST_DEVICE_IDENTITY
172 if (err == CHIP_DEVICE_ERROR_CONFIG_NOT_FOUND || err == CHIP_ERROR_KEY_NOT_FOUND)
174 deviceId = TestDeviceId;
182 template <class ImplClass>
183 CHIP_ERROR GenericConfigurationManagerImpl<ImplClass>::_StoreManufacturerDeviceId(uint64_t deviceId)
185 return Impl()->WriteConfigValue(ImplClass::kConfigKey_MfrDeviceId, deviceId);
188 template <class ImplClass>
189 CHIP_ERROR GenericConfigurationManagerImpl<ImplClass>::_GetSerialNumber(char * buf, size_t bufSize, size_t & serialNumLen)
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)
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;
202 #endif // CHIP_DEVICE_CONFIG_TEST_SERIAL_NUMBER
209 template <class ImplClass>
210 CHIP_ERROR GenericConfigurationManagerImpl<ImplClass>::_StoreSerialNumber(const char * serialNum, size_t serialNumLen)
212 return Impl()->WriteConfigValueStr(ImplClass::kConfigKey_SerialNum, serialNum, serialNumLen);
215 template <class ImplClass>
216 CHIP_ERROR GenericConfigurationManagerImpl<ImplClass>::_GetPrimaryWiFiMACAddress(uint8_t * buf)
218 return CHIP_DEVICE_ERROR_CONFIG_NOT_FOUND;
221 template <class ImplClass>
222 CHIP_ERROR GenericConfigurationManagerImpl<ImplClass>::_StorePrimaryWiFiMACAddress(const uint8_t * buf)
224 return CHIP_ERROR_UNSUPPORTED_CHIP_FEATURE;
227 template <class ImplClass>
228 CHIP_ERROR GenericConfigurationManagerImpl<ImplClass>::_GetPrimary802154MACAddress(uint8_t * buf)
230 #if CHIP_DEVICE_CONFIG_ENABLE_THREAD
231 return ThreadStackManager().GetPrimary802154MACAddress(buf);
233 return CHIP_DEVICE_ERROR_CONFIG_NOT_FOUND;
234 #endif // CHIP_DEVICE_CONFIG_ENABLE_THREAD
237 template <class ImplClass>
238 CHIP_ERROR GenericConfigurationManagerImpl<ImplClass>::_StorePrimary802154MACAddress(const uint8_t * buf)
240 return CHIP_ERROR_UNSUPPORTED_CHIP_FEATURE;
243 template <class ImplClass>
244 inline CHIP_ERROR GenericConfigurationManagerImpl<ImplClass>::_GetProductRevision(uint16_t & productRev)
249 err = Impl()->ReadConfigValue(ImplClass::kConfigKey_ProductRevision, val);
250 if (err == CHIP_DEVICE_ERROR_CONFIG_NOT_FOUND)
252 productRev = static_cast<uint16_t>(CHIP_DEVICE_CONFIG_DEFAULT_DEVICE_PRODUCT_REVISION);
257 productRev = static_cast<uint16_t>(val);
263 template <class ImplClass>
264 inline CHIP_ERROR GenericConfigurationManagerImpl<ImplClass>::_StoreProductRevision(uint16_t productRev)
266 return Impl()->WriteConfigValue(ImplClass::kConfigKey_ProductRevision, static_cast<uint32_t>(productRev));
269 template <class ImplClass>
270 CHIP_ERROR GenericConfigurationManagerImpl<ImplClass>::_GetManufacturingDate(uint16_t & year, uint8_t & month, uint8_t & dayOfMonth)
275 kDateStringLength = 10 // YYYY-MM-DD
277 char dateStr[kDateStringLength + 1];
281 err = Impl()->ReadConfigValueStr(ImplClass::kConfigKey_ManufacturingDate, dateStr, sizeof(dateStr), dateLen);
284 VerifyOrExit(dateLen == kDateStringLength, err = CHIP_ERROR_INVALID_ARGUMENT);
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);
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);
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);
302 if (err != CHIP_NO_ERROR && err != CHIP_DEVICE_ERROR_CONFIG_NOT_FOUND)
304 ChipLogError(DeviceLayer, "Invalid manufacturing date: %s", dateStr);
309 template <class ImplClass>
310 CHIP_ERROR GenericConfigurationManagerImpl<ImplClass>::_StoreManufacturingDate(const char * mfgDate, size_t mfgDateLen)
312 return Impl()->WriteConfigValueStr(ImplClass::kConfigKey_ManufacturingDate, mfgDate, mfgDateLen);
315 template <class ImplClass>
316 CHIP_ERROR GenericConfigurationManagerImpl<ImplClass>::_GetManufacturerDeviceCertificate(uint8_t * buf, size_t bufSize,
321 err = Impl()->ReadConfigValueBin(ImplClass::kConfigKey_MfrDeviceCert, buf, bufSize, certLen);
323 #if CHIP_DEVICE_CONFIG_ENABLE_TEST_DEVICE_IDENTITY
325 if (err == CHIP_DEVICE_ERROR_CONFIG_NOT_FOUND)
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);
334 #endif // CHIP_DEVICE_CONFIG_ENABLE_TEST_DEVICE_IDENTITY
342 template <class ImplClass>
343 CHIP_ERROR GenericConfigurationManagerImpl<ImplClass>::_StoreManufacturerDeviceCertificate(const uint8_t * cert, size_t certLen)
345 return Impl()->WriteConfigValueBin(ImplClass::kConfigKey_MfrDeviceCert, cert, certLen);
348 template <class ImplClass>
349 CHIP_ERROR GenericConfigurationManagerImpl<ImplClass>::_GetManufacturerDeviceIntermediateCACerts(uint8_t * buf, size_t bufSize,
354 err = Impl()->ReadConfigValueBin(ImplClass::kConfigKey_MfrDeviceICACerts, buf, bufSize, certsLen);
356 #if CHIP_DEVICE_CONFIG_ENABLE_TEST_DEVICE_IDENTITY
358 if (err == CHIP_DEVICE_ERROR_CONFIG_NOT_FOUND)
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);
367 #endif // CHIP_DEVICE_CONFIG_ENABLE_TEST_DEVICE_IDENTITY
375 template <class ImplClass>
376 CHIP_ERROR GenericConfigurationManagerImpl<ImplClass>::_StoreManufacturerDeviceIntermediateCACerts(const uint8_t * certs,
379 return Impl()->WriteConfigValueBin(ImplClass::kConfigKey_MfrDeviceICACerts, certs, certsLen);
382 template <class ImplClass>
383 CHIP_ERROR GenericConfigurationManagerImpl<ImplClass>::_GetManufacturerDevicePrivateKey(uint8_t * buf, size_t bufSize,
388 err = Impl()->ReadConfigValueBin(ImplClass::kConfigKey_MfrDevicePrivateKey, buf, bufSize, keyLen);
390 #if CHIP_DEVICE_CONFIG_ENABLE_TEST_DEVICE_IDENTITY
392 if (err == CHIP_DEVICE_ERROR_CONFIG_NOT_FOUND)
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);
401 #endif // CHIP_DEVICE_CONFIG_ENABLE_TEST_DEVICE_IDENTITY
409 template <class ImplClass>
410 CHIP_ERROR GenericConfigurationManagerImpl<ImplClass>::_StoreManufacturerDevicePrivateKey(const uint8_t * key, size_t keyLen)
412 return Impl()->WriteConfigValueBin(ImplClass::kConfigKey_MfrDevicePrivateKey, key, keyLen);
415 template <class ImplClass>
416 CHIP_ERROR GenericConfigurationManagerImpl<ImplClass>::_GetDeviceId(uint64_t & deviceId)
420 #if CHIP_DEVICE_CONFIG_ENABLE_JUST_IN_TIME_PROVISIONING
421 if (!UseManufacturerCredentialsAsOperational())
423 err = Impl()->ReadConfigValue(ImplClass::kConfigKey_OperationalDeviceId, deviceId);
428 err = Impl()->_GetManufacturerDeviceId(deviceId);
434 template <class ImplClass>
435 CHIP_ERROR GenericConfigurationManagerImpl<ImplClass>::_GetDeviceCertificate(uint8_t * buf, size_t bufSize, size_t & certLen)
439 #if CHIP_DEVICE_CONFIG_ENABLE_JUST_IN_TIME_PROVISIONING
440 if (!UseManufacturerCredentialsAsOperational())
442 err = Impl()->ReadConfigValueBin(ImplClass::kConfigKey_OperationalDeviceCert, buf, bufSize, certLen);
447 err = Impl()->_GetManufacturerDeviceCertificate(buf, bufSize, certLen);
453 template <class ImplClass>
454 CHIP_ERROR GenericConfigurationManagerImpl<ImplClass>::_GetDeviceIntermediateCACerts(uint8_t * buf, size_t bufSize,
459 #if CHIP_DEVICE_CONFIG_ENABLE_JUST_IN_TIME_PROVISIONING
460 if (!UseManufacturerCredentialsAsOperational())
462 err = Impl()->ReadConfigValueBin(ImplClass::kConfigKey_OperationalDeviceICACerts, buf, bufSize, certsLen);
467 err = Impl()->_GetManufacturerDeviceIntermediateCACerts(buf, bufSize, certsLen);
473 template <class ImplClass>
474 CHIP_ERROR GenericConfigurationManagerImpl<ImplClass>::_GetDevicePrivateKey(uint8_t * buf, size_t bufSize, size_t & keyLen)
478 #if CHIP_DEVICE_CONFIG_ENABLE_JUST_IN_TIME_PROVISIONING
479 if (!UseManufacturerCredentialsAsOperational())
481 err = Impl()->ReadConfigValueBin(ImplClass::kConfigKey_OperationalDevicePrivateKey, buf, bufSize, keyLen);
486 err = Impl()->_GetManufacturerDevicePrivateKey(buf, bufSize, keyLen);
492 #if CHIP_DEVICE_CONFIG_ENABLE_JUST_IN_TIME_PROVISIONING
494 template <class ImplClass>
495 CHIP_ERROR GenericConfigurationManagerImpl<ImplClass>::_StoreDeviceId(uint64_t deviceId)
497 return Impl()->WriteConfigValue(ImplClass::kConfigKey_OperationalDeviceId, deviceId);
500 template <class ImplClass>
501 CHIP_ERROR GenericConfigurationManagerImpl<ImplClass>::_StoreDeviceCertificate(const uint8_t * cert, size_t certLen)
503 return Impl()->WriteConfigValueBin(ImplClass::kConfigKey_OperationalDeviceCert, cert, certLen);
506 template <class ImplClass>
507 CHIP_ERROR GenericConfigurationManagerImpl<ImplClass>::_StoreDeviceIntermediateCACerts(const uint8_t * certs, size_t certsLen)
509 return Impl()->WriteConfigValueBin(ImplClass::kConfigKey_OperationalDeviceICACerts, certs, certsLen);
512 template <class ImplClass>
513 CHIP_ERROR GenericConfigurationManagerImpl<ImplClass>::_StoreDevicePrivateKey(const uint8_t * key, size_t keyLen)
515 return Impl()->WriteConfigValueBin(ImplClass::kConfigKey_OperationalDevicePrivateKey, key, keyLen);
518 template <class ImplClass>
519 CHIP_ERROR GenericConfigurationManagerImpl<ImplClass>::_ClearOperationalDeviceCredentials(void)
521 Impl()->ClearConfigValue(ImplClass::kConfigKey_OperationalDeviceId);
522 Impl()->ClearConfigValue(ImplClass::kConfigKey_OperationalDeviceCert);
523 Impl()->ClearConfigValue(ImplClass::kConfigKey_OperationalDeviceICACerts);
524 Impl()->ClearConfigValue(ImplClass::kConfigKey_OperationalDevicePrivateKey);
526 mFlags.Clear(Flags::kOperationalDeviceCredentialsProvisioned);
528 return CHIP_NO_ERROR;
531 template <class ImplClass>
532 bool GenericConfigurationManagerImpl<ImplClass>::_OperationalDeviceCredentialsProvisioned()
534 return mFlags.Has(Flags::kOperationalDeviceCredentialsProvisioned);
537 template <class ImplClass>
538 bool GenericConfigurationManagerImpl<ImplClass>::UseManufacturerCredentialsAsOperational()
540 return mFlags.Has(Flags::kUseManufacturerCredentialsAsOperational);
543 template <class ImplClass>
544 void GenericConfigurationManagerImpl<ImplClass>::_UseManufacturerCredentialsAsOperational(bool val)
546 mFlags.Set(Flags::kUseManufacturerCredentialsAsOperational, val);
549 #endif // CHIP_DEVICE_CONFIG_ENABLE_JUST_IN_TIME_PROVISIONING
551 template <class ImplClass>
552 CHIP_ERROR GenericConfigurationManagerImpl<ImplClass>::_GetSetupPinCode(uint32_t & setupPinCode)
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)
560 setupPinCode = CHIP_DEVICE_CONFIG_USE_TEST_SETUP_PIN_CODE;
563 #endif // defined(CHIP_DEVICE_CONFIG_USE_TEST_SETUP_PIN_CODE) && CHIP_DEVICE_CONFIG_USE_TEST_SETUP_PIN_CODE
570 template <class ImplClass>
571 CHIP_ERROR GenericConfigurationManagerImpl<ImplClass>::_StoreSetupPinCode(uint32_t setupPinCode)
573 return Impl()->WriteConfigValue(ImplClass::kConfigKey_SetupPinCode, setupPinCode);
576 template <class ImplClass>
577 CHIP_ERROR GenericConfigurationManagerImpl<ImplClass>::_GetSetupDiscriminator(uint16_t & setupDiscriminator)
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)
586 val = CHIP_DEVICE_CONFIG_USE_TEST_SETUP_DISCRIMINATOR;
589 #endif // defined(CHIP_DEVICE_CONFIG_USE_TEST_SETUP_DISCRIMINATOR) && CHIP_DEVICE_CONFIG_USE_TEST_SETUP_DISCRIMINATOR
592 setupDiscriminator = static_cast<uint16_t>(val);
598 template <class ImplClass>
599 CHIP_ERROR GenericConfigurationManagerImpl<ImplClass>::_StoreSetupDiscriminator(uint16_t setupDiscriminator)
601 return Impl()->WriteConfigValue(ImplClass::kConfigKey_SetupDiscriminator, static_cast<uint32_t>(setupDiscriminator));
604 template <class ImplClass>
605 CHIP_ERROR GenericConfigurationManagerImpl<ImplClass>::_GetFabricId(uint64_t & fabricId)
607 CHIP_ERROR err = Impl()->ReadConfigValue(ImplClass::kConfigKey_FabricId, fabricId);
609 #if CHIP_DEVICE_CONFIG_ENABLE_TEST_DEVICE_IDENTITY
610 if (err == CHIP_DEVICE_ERROR_CONFIG_NOT_FOUND || err == CHIP_ERROR_KEY_NOT_FOUND)
612 fabricId = TestFabricId;
615 #endif // CHIP_DEVICE_CONFIG_ENABLE_TEST_DEVICE_IDENTITY
619 template <class ImplClass>
620 CHIP_ERROR GenericConfigurationManagerImpl<ImplClass>::_StoreFabricId(uint64_t fabricId)
622 CHIP_ERROR err = CHIP_NO_ERROR;
624 #if CHIP_CONFIG_ENABLE_FABRIC_STATE
625 if (fabricId != kFabricIdNotSpecified)
627 err = Impl()->WriteConfigValue(ImplClass::kConfigKey_FabricId, fabricId);
629 mFlags.Set(Flags::kIsMemberOfFabric);
633 mFlags.Clear(Flags::kIsMemberOfFabric);
634 err = Impl()->ClearConfigValue(ImplClass::kConfigKey_FabricId);
644 template <class ImplClass>
645 CHIP_ERROR GenericConfigurationManagerImpl<ImplClass>::_GetServiceId(uint64_t & serviceId)
647 return Impl()->ReadConfigValue(ImplClass::kConfigKey_ServiceId, serviceId);
650 template <class ImplClass>
651 CHIP_ERROR GenericConfigurationManagerImpl<ImplClass>::_GetServiceConfig(uint8_t * buf, size_t bufSize, size_t & serviceConfigLen)
653 return Impl()->ReadConfigValueBin(ImplClass::kConfigKey_ServiceConfig, buf, bufSize, serviceConfigLen);
656 template <class ImplClass>
657 CHIP_ERROR GenericConfigurationManagerImpl<ImplClass>::_StoreServiceConfig(const uint8_t * serviceConfig, size_t serviceConfigLen)
659 return Impl()->WriteConfigValueBin(ImplClass::kConfigKey_ServiceConfig, serviceConfig, serviceConfigLen);
662 #if CHIP_ENABLE_ROTATING_DEVICE_ID
663 template <class ImplClass>
664 CHIP_ERROR GenericConfigurationManagerImpl<ImplClass>::_GetLifetimeCounter(uint16_t & lifetimeCounter)
666 lifetimeCounter = static_cast<uint16_t>(mLifetimePersistedCounter.GetValue());
667 return CHIP_NO_ERROR;
670 template <class ImplClass>
671 CHIP_ERROR GenericConfigurationManagerImpl<ImplClass>::_IncrementLifetimeCounter()
673 return mLifetimePersistedCounter.Advance();
677 template <class ImplClass>
678 CHIP_ERROR GenericConfigurationManagerImpl<ImplClass>::_GetPairedAccountId(char * buf, size_t bufSize, size_t & accountIdLen)
680 return Impl()->ReadConfigValueStr(ImplClass::kConfigKey_PairedAccountId, buf, bufSize, accountIdLen);
683 template <class ImplClass>
684 CHIP_ERROR GenericConfigurationManagerImpl<ImplClass>::_StorePairedAccountId(const char * accountId, size_t accountIdLen)
688 err = Impl()->WriteConfigValueStr(ImplClass::kConfigKey_PairedAccountId, accountId, accountIdLen);
691 mFlags.Set(Flags::kIsPairedToAccount, (accountId != nullptr && accountIdLen != 0));
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)
705 err = Impl()->WriteConfigValue(ImplClass::kConfigKey_ServiceId, serviceId);
708 err = _StoreServiceConfig(serviceConfig, serviceConfigLen);
711 err = _StorePairedAccountId(accountId, accountIdLen);
714 mFlags.Set(Flags::kIsServiceProvisioned);
715 mFlags.Set(Flags::kIsPairedToAccount, (accountId != nullptr && accountIdLen != 0));
718 if (err != CHIP_NO_ERROR)
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);
729 template <class ImplClass>
730 CHIP_ERROR GenericConfigurationManagerImpl<ImplClass>::_ClearServiceProvisioningData()
732 Impl()->ClearConfigValue(ImplClass::kConfigKey_ServiceId);
733 Impl()->ClearConfigValue(ImplClass::kConfigKey_ServiceConfig);
734 Impl()->ClearConfigValue(ImplClass::kConfigKey_PairedAccountId);
736 // TODO: Move these behaviors out of configuration manager.
738 // If necessary, post an event alerting other subsystems to the change in
739 // the account pairing state.
740 if (_IsPairedToAccount())
742 ChipDeviceEvent event;
743 event.Type = DeviceEventType::kAccountPairingChange;
744 event.AccountPairingChange.IsPairedToAccount = false;
745 PlatformMgr().PostEvent(&event);
748 // If necessary, post an event alerting other subsystems to the change in
749 // the service provisioning state.
750 if (_IsServiceProvisioned())
752 ChipDeviceEvent event;
753 event.Type = DeviceEventType::kServiceProvisioningChange;
754 event.ServiceProvisioningChange.IsServiceProvisioned = false;
755 event.ServiceProvisioningChange.ServiceConfigUpdated = false;
756 PlatformMgr().PostEvent(&event);
759 mFlags.Clear(Flags::kIsServiceProvisioned);
760 mFlags.Clear(Flags::kIsPairedToAccount);
762 return CHIP_NO_ERROR;
765 template <class ImplClass>
766 CHIP_ERROR GenericConfigurationManagerImpl<ImplClass>::_GetFailSafeArmed(bool & val)
768 return Impl()->ReadConfigValue(ImplClass::kConfigKey_FailSafeArmed, val);
771 template <class ImplClass>
772 CHIP_ERROR GenericConfigurationManagerImpl<ImplClass>::_SetFailSafeArmed(bool val)
774 return Impl()->WriteConfigValue(ImplClass::kConfigKey_FailSafeArmed, val);
777 template <class ImplClass>
778 CHIP_ERROR GenericConfigurationManagerImpl<ImplClass>::_GetQRCodeString(char * buf, size_t bufSize)
780 return CHIP_ERROR_NOT_IMPLEMENTED;
783 template <class ImplClass>
784 CHIP_ERROR GenericConfigurationManagerImpl<ImplClass>::_GetWiFiAPSSID(char * buf, size_t bufSize)
788 #ifdef CHIP_DEVICE_CONFIG_WIFI_AP_SSID_PREFIX
792 VerifyOrExit(bufSize >= sizeof(CHIP_DEVICE_CONFIG_WIFI_AP_SSID_PREFIX) + 4, err = CHIP_ERROR_BUFFER_TOO_SMALL);
794 err = Impl()->_GetPrimaryWiFiMACAddress(mac);
797 snprintf(buf, bufSize, "%s%02X%02X", CHIP_DEVICE_CONFIG_WIFI_AP_SSID_PREFIX, mac[4], mac[5]);
798 buf[bufSize - 1] = 0;
800 #else // CHIP_DEVICE_CONFIG_WIFI_AP_SSID_PREFIX
802 ExitNow(err = CHIP_DEVICE_ERROR_CONFIG_NOT_FOUND);
804 #endif // CHIP_DEVICE_CONFIG_WIFI_AP_SSID_PREFIX
810 template <class ImplClass>
812 GenericConfigurationManagerImpl<ImplClass>::_GetBLEDeviceIdentificationInfo(Ble::ChipBLEDeviceIdentificationInfo & deviceIdInfo)
816 uint16_t discriminator;
820 err = Impl()->_GetVendorId(id);
822 deviceIdInfo.SetVendorId(id);
824 err = Impl()->_GetProductId(id);
826 deviceIdInfo.SetProductId(id);
828 err = Impl()->_GetSetupDiscriminator(discriminator);
830 deviceIdInfo.SetDeviceDiscriminator(discriminator);
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;
842 deviceIdInfo.PairingStatus = Impl()->_IsPairedToAccount() ? Ble::ChipBLEDeviceIdentificationInfo::kPairingStatus_Paired
843 : Ble::ChipBLEDeviceIdentificationInfo::kPairingStatus_Unpaired;
850 template <class ImplClass>
851 bool GenericConfigurationManagerImpl<ImplClass>::_IsServiceProvisioned()
853 return mFlags.Has(Flags::kIsServiceProvisioned);
856 template <class ImplClass>
857 bool GenericConfigurationManagerImpl<ImplClass>::_IsMemberOfFabric()
859 return mFlags.Has(Flags::kIsMemberOfFabric);
862 template <class ImplClass>
863 bool GenericConfigurationManagerImpl<ImplClass>::_IsPairedToAccount()
865 return mFlags.Has(Flags::kIsPairedToAccount);
868 template <class ImplClass>
869 bool GenericConfigurationManagerImpl<ImplClass>::_IsFullyProvisioned()
871 #if CHIP_BYPASS_RENDEZVOUS
873 #else // CHIP_BYPASS_RENDEZVOUS
876 #if CHIP_DEVICE_CONFIG_ENABLE_WIFI_STATION
877 ConnectivityMgr().IsWiFiStationProvisioned() &&
879 #if CHIP_DEVICE_CONFIG_ENABLE_THREAD
880 ConnectivityMgr().IsThreadProvisioned() &&
882 #if CHIP_DEVICE_CONFIG_ENABLE_JUST_IN_TIME_PROVISIONING
883 (!UseManufacturerCredentialsAsOperational() && _OperationalDeviceCredentialsProvisioned()) &&
885 // TODO: Add checks regarding fabric membership (IsMemberOfFabric()) and account pairing (IsPairedToAccount()),
886 // when functionalities will be implemented.
888 #endif // CHIP_BYPASS_RENDEZVOUS
891 template <class ImplClass>
892 CHIP_ERROR GenericConfigurationManagerImpl<ImplClass>::_ComputeProvisioningHash(uint8_t * hashBuf, size_t hashBufSize)
894 CHIP_ERROR err = CHIP_NO_ERROR;
896 #if CHIP_DEVICE_CONFIG_LOG_PROVISIONING_HASH
897 using HashAlgo = chip::Crypto::Hash_SHA256_stream;
900 chip::Platform::ScopedMemoryBuffer dataBuf;
902 constexpr uint16_t kLenFieldLen = 4; // 4 hex characters
904 VerifyOrExit(hashBufSize >= chip::Crypto::kSHA256_Hash_Length, err = CHIP_ERROR_BUFFER_TOO_SMALL);
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.
909 // A CHIP provisioning hash is a SHA-256 hash of an ASCII string with the following format:
911 // DDDDddddddddddddddddCCCCcccc…ccccIIIIiiii…iiiiKKKKkkkk…kkkkPPPPpppppp
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.
928 // Hash the device id
931 constexpr uint16_t kDeviceIdLen = 16; // 16 hex characters
932 char inputBuf[kLenFieldLen + kDeviceIdLen + 1]; // +1 for terminator
934 err = Impl()->_GetManufacturerDeviceId(deviceId);
937 snprintf(inputBuf, sizeof(inputBuf), "0010%016" PRIX64, deviceId);
939 hash.AddData((uint8_t *) inputBuf, kLenFieldLen + kDeviceIdLen);
942 // Hash the device certificate
946 // Determine the length of the device certificate.
947 err = Impl()->_GetManufacturerDeviceCertificate((uint8_t *) NULL, 0, certLen);
950 // Create a temporary buffer to hold the certificate. (This will also be used for
952 dataBufSize = certLen;
953 VerifyOrExit(dataBuf.Alloc(dataBufSize), err = CHIP_ERROR_NO_MEMORY);
955 // Read the certificate.
956 err = Impl()->_GetManufacturerDeviceCertificate(dataBuf.Ptr<uint8_t>(), certLen, certLen);
960 // Hash the device intermediate CA certificates
961 if (Impl()->ConfigValueExists(ImplClass::kConfigKey_MfrDeviceICACerts))
965 // Determine the length of the device intermediate CA certificates.
966 err = Impl()->_GetManufacturerDeviceIntermediateCACerts((uint8_t *) NULL, 0, certsLen);
969 // Allocate larger buffer to hold the intermediate CA certificates.
970 // (This will also be used for the private key).
971 if (certsLen > dataBufSize)
973 dataBufSize = certsLen;
974 VerifyOrExit(dataBuf.Alloc(dataBufSize), err = CHIP_ERROR_NO_MEMORY);
977 // Read the device intermediate CA certificates.
978 err = Impl()->_GetManufacturerDeviceIntermediateCACerts(dataBuf.Ptr<uint8_t>(), certsLen, certsLen);
982 // Hash the device private key
986 // Determine the length of the device private key.
987 err = Impl()->_GetManufacturerDevicePrivateKey((uint8_t *) NULL, 0, keyLen);
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);
997 // Hash the device pairing code. If the device does not have a pairing code, hash a zero-length value.
999 char pairingCode[ConfigurationManager::kMaxPairingCodeLength + 1]; // +1 for terminator
1000 char lenStr[kLenFieldLen + 1]; // +1 for terminator
1001 size_t pairingCodeLen;
1003 err = Impl()->_GetPairingCode(pairingCode, sizeof(pairingCode), pairingCodeLen);
1004 if (err == CHIP_DEVICE_ERROR_CONFIG_NOT_FOUND)
1007 err = CHIP_NO_ERROR;
1011 snprintf(lenStr, sizeof(lenStr), "%04" PRIX16, (uint16_t) pairingCodeLen);
1013 hash.AddData((uint8_t *) lenStr, kLenFieldLen);
1014 hash.AddData((uint8_t *) pairingCode, pairingCodeLen);
1017 hash.Finish(hashBuf);
1022 chip::Crypto::ClearSecretData(dataBuf.Ptr(), dataBufSize);
1024 #endif // CHIP_DEVICE_CONFIG_LOG_PROVISIONING_HASH
1029 #if !defined(NDEBUG)
1030 template <class ImplClass>
1031 CHIP_ERROR GenericConfigurationManagerImpl<ImplClass>::_RunUnitTests()
1033 ChipLogProgress(DeviceLayer, "Running configuration unit test");
1034 Impl()->RunConfigUnitTest();
1036 return CHIP_NO_ERROR;
1040 template <class ImplClass>
1041 void GenericConfigurationManagerImpl<ImplClass>::_LogDeviceConfig()
1045 ChipLogProgress(DeviceLayer, "Device Configuration:");
1047 #if CHIP_CONFIG_ENABLE_FABRIC_STATE
1048 ChipLogProgress(DeviceLayer, " Device Id: %016" PRIX64, FabricState.LocalNodeId);
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)");
1060 if (Impl()->_GetVendorId(vendorId) != CHIP_NO_ERROR)
1064 ChipLogProgress(DeviceLayer, " Vendor Id: %" PRIu16 " (0x%" PRIX16 ")", vendorId, vendorId);
1069 if (Impl()->_GetProductId(productId) != CHIP_NO_ERROR)
1073 ChipLogProgress(DeviceLayer, " Product Id: %" PRIu16 " (0x%" PRIX16 ")", productId, productId);
1077 uint16_t productRev;
1078 if (Impl()->_GetProductRevision(productRev) != CHIP_NO_ERROR)
1082 ChipLogProgress(DeviceLayer, " Product Revision: %" PRIu16, productRev);
1086 uint32_t setupPINCode;
1087 if (Impl()->_GetSetupPinCode(setupPINCode) != CHIP_NO_ERROR)
1091 ChipLogProgress(DeviceLayer, " Setup Pin Code: %" PRIu32 "", setupPINCode);
1095 uint16_t setupDiscriminator;
1096 if (Impl()->_GetSetupDiscriminator(setupDiscriminator) != CHIP_NO_ERROR)
1098 setupDiscriminator = 0;
1100 ChipLogProgress(DeviceLayer, " Setup Discriminator: %" PRIu16 " (0x%" PRIX16 ")", setupDiscriminator, setupDiscriminator);
1105 uint8_t month, dayOfMonth;
1106 err = Impl()->_GetManufacturingDate(year, month, dayOfMonth);
1107 if (err == CHIP_NO_ERROR)
1109 ChipLogProgress(DeviceLayer, " Manufacturing Date: %04" PRIu16 "/%02" PRIu8 "/%02" PRIu8, year, month, dayOfMonth);
1113 ChipLogProgress(DeviceLayer, " Manufacturing Date: (not set)");
1117 #if CHIP_CONFIG_ENABLE_FABRIC_STATE
1118 if (FabricState.FabricId != kFabricIdNotSpecified)
1120 ChipLogProgress(DeviceLayer, " Fabric Id: %016" PRIX64, FabricState.FabricId);
1124 ChipLogProgress(DeviceLayer, " Fabric Id: (none)");
1127 ChipLogProgress(DeviceLayer, " Pairing Code: %s", (FabricState.PairingCode != NULL) ? FabricState.PairingCode : "(none)");
1128 #endif // CHIP_CONFIG_ENABLE_FABRIC_STATE
1131 // Fully instantiate the generic implementation class in whatever compilation unit includes this file.
1132 template class GenericConfigurationManagerImpl<ConfigurationManagerImpl>;
1134 } // namespace Internal
1135 } // namespace DeviceLayer
1138 #endif // GENERIC_CONFIGURATION_MANAGER_IMPL_CPP