3 * Copyright (c) 2020 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()
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));
63 #if CHIP_ENABLE_ROTATING_DEVICE_ID
64 mLifetimePersistedCounter.Init(CHIP_CONFIG_LIFETIIME_PERSISTED_COUNTER_KEY);
70 template <class ImplClass>
71 CHIP_ERROR GenericConfigurationManagerImpl<ImplClass>::_ConfigureChipStack()
73 CHIP_ERROR err = CHIP_NO_ERROR;
75 #if CHIP_CONFIG_ENABLE_FABRIC_STATE
76 size_t pairingCodeLen;
78 static char sPairingCodeBuf[ConfigurationManager::kMaxPairingCodeLength + 1];
80 // Configure the CHIP FabricState object with the local node id.
81 err = Impl()->_GetDeviceId(FabricState.LocalNodeId);
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)
89 FabricState.PairingCode = sPairingCodeBuf;
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)
96 FabricState.FabricId = kFabricIdNotSpecified;
100 #endif // CHIP_CONFIG_ENABLE_FABRIC_STATE
102 #if CHIP_PROGRESS_LOGGING
104 Impl()->_LogDeviceConfig();
106 #if CHIP_DEVICE_CONFIG_LOG_PROVISIONING_HASH
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)
113 Base64Encode(provHash, sizeof(provHash), provHashBase64);
114 provHashBase64[sizeof(provHashBase64) - 1] = '\0';
115 ChipLogProgress(DeviceLayer, "CHIP Provisioning Hash: %s", provHashBase64);
119 ChipLogError(DeviceLayer, "Error generating CHIP Provisioning Hash: %s", chip::ErrorStr(err));
123 #endif // CHIP_DEVICE_CONFIG_LOG_PROVISIONING_HASH
125 #endif // CHIP_PROGRESS_LOGGING
133 template <class ImplClass>
134 CHIP_ERROR GenericConfigurationManagerImpl<ImplClass>::_GetFirmwareRevision(char * buf, size_t bufSize, size_t & outLen)
136 #ifdef CHIP_DEVICE_CONFIG_DEVICE_FIRMWARE_REVISION
137 if (CHIP_DEVICE_CONFIG_DEVICE_FIRMWARE_REVISION[0] != 0)
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;
143 #endif // CHIP_DEVICE_CONFIG_DEVICE_FIRMWARE_REVISION
146 return CHIP_DEVICE_ERROR_CONFIG_NOT_FOUND;
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)
153 CHIP_ERROR err = CHIP_NO_ERROR;
155 err = ParseCompilerDateStr(CHIP_DEVICE_CONFIG_FIRWMARE_BUILD_DATE, year, month, dayOfMonth);
158 err = Parse24HourTimeStr(CHIP_DEVICE_CONFIG_FIRMWARE_BUILD_TIME, hour, minute, second);
165 template <class ImplClass>
166 CHIP_ERROR GenericConfigurationManagerImpl<ImplClass>::_GetManufacturerDeviceId(uint64_t & deviceId)
170 err = Impl()->ReadConfigValue(ImplClass::kConfigKey_MfrDeviceId, deviceId);
172 #if CHIP_DEVICE_CONFIG_ENABLE_TEST_DEVICE_IDENTITY
173 if (err == CHIP_DEVICE_ERROR_CONFIG_NOT_FOUND || err == CHIP_ERROR_KEY_NOT_FOUND)
175 deviceId = TestDeviceId;
183 template <class ImplClass>
184 CHIP_ERROR GenericConfigurationManagerImpl<ImplClass>::_StoreManufacturerDeviceId(uint64_t deviceId)
186 return Impl()->WriteConfigValue(ImplClass::kConfigKey_MfrDeviceId, deviceId);
189 template <class ImplClass>
190 CHIP_ERROR GenericConfigurationManagerImpl<ImplClass>::_GetSerialNumber(char * buf, size_t bufSize, size_t & serialNumLen)
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)
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;
203 #endif // CHIP_DEVICE_CONFIG_TEST_SERIAL_NUMBER
210 template <class ImplClass>
211 CHIP_ERROR GenericConfigurationManagerImpl<ImplClass>::_StoreSerialNumber(const char * serialNum, size_t serialNumLen)
213 return Impl()->WriteConfigValueStr(ImplClass::kConfigKey_SerialNum, serialNum, serialNumLen);
216 template <class ImplClass>
217 CHIP_ERROR GenericConfigurationManagerImpl<ImplClass>::_GetPrimaryWiFiMACAddress(uint8_t * buf)
219 return CHIP_DEVICE_ERROR_CONFIG_NOT_FOUND;
222 template <class ImplClass>
223 CHIP_ERROR GenericConfigurationManagerImpl<ImplClass>::_StorePrimaryWiFiMACAddress(const uint8_t * buf)
225 return CHIP_ERROR_UNSUPPORTED_CHIP_FEATURE;
228 template <class ImplClass>
229 CHIP_ERROR GenericConfigurationManagerImpl<ImplClass>::_GetPrimary802154MACAddress(uint8_t * buf)
231 #if CHIP_DEVICE_CONFIG_ENABLE_THREAD
232 return ThreadStackManager().GetPrimary802154MACAddress(buf);
234 return CHIP_DEVICE_ERROR_CONFIG_NOT_FOUND;
235 #endif // CHIP_DEVICE_CONFIG_ENABLE_THREAD
238 template <class ImplClass>
239 CHIP_ERROR GenericConfigurationManagerImpl<ImplClass>::_StorePrimary802154MACAddress(const uint8_t * buf)
241 return CHIP_ERROR_UNSUPPORTED_CHIP_FEATURE;
244 template <class ImplClass>
245 inline CHIP_ERROR GenericConfigurationManagerImpl<ImplClass>::_GetProductRevision(uint16_t & productRev)
250 err = Impl()->ReadConfigValue(ImplClass::kConfigKey_ProductRevision, val);
251 if (err == CHIP_DEVICE_ERROR_CONFIG_NOT_FOUND)
253 productRev = static_cast<uint16_t>(CHIP_DEVICE_CONFIG_DEFAULT_DEVICE_PRODUCT_REVISION);
258 productRev = static_cast<uint16_t>(val);
264 template <class ImplClass>
265 inline CHIP_ERROR GenericConfigurationManagerImpl<ImplClass>::_StoreProductRevision(uint16_t productRev)
267 return Impl()->WriteConfigValue(ImplClass::kConfigKey_ProductRevision, static_cast<uint32_t>(productRev));
270 template <class ImplClass>
271 CHIP_ERROR GenericConfigurationManagerImpl<ImplClass>::_GetManufacturingDate(uint16_t & year, uint8_t & month, uint8_t & dayOfMonth)
276 kDateStringLength = 10 // YYYY-MM-DD
278 char dateStr[kDateStringLength + 1];
282 err = Impl()->ReadConfigValueStr(ImplClass::kConfigKey_ManufacturingDate, dateStr, sizeof(dateStr), dateLen);
285 VerifyOrExit(dateLen == kDateStringLength, err = CHIP_ERROR_INVALID_ARGUMENT);
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);
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);
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);
303 if (err != CHIP_NO_ERROR && err != CHIP_DEVICE_ERROR_CONFIG_NOT_FOUND)
305 ChipLogError(DeviceLayer, "Invalid manufacturing date: %s", dateStr);
310 template <class ImplClass>
311 CHIP_ERROR GenericConfigurationManagerImpl<ImplClass>::_StoreManufacturingDate(const char * mfgDate, size_t mfgDateLen)
313 return Impl()->WriteConfigValueStr(ImplClass::kConfigKey_ManufacturingDate, mfgDate, mfgDateLen);
316 template <class ImplClass>
317 CHIP_ERROR GenericConfigurationManagerImpl<ImplClass>::_GetManufacturerDeviceCertificate(uint8_t * buf, size_t bufSize,
322 err = Impl()->ReadConfigValueBin(ImplClass::kConfigKey_MfrDeviceCert, buf, bufSize, certLen);
324 #if CHIP_DEVICE_CONFIG_ENABLE_TEST_DEVICE_IDENTITY
326 if (err == CHIP_DEVICE_ERROR_CONFIG_NOT_FOUND)
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);
335 #endif // CHIP_DEVICE_CONFIG_ENABLE_TEST_DEVICE_IDENTITY
343 template <class ImplClass>
344 CHIP_ERROR GenericConfigurationManagerImpl<ImplClass>::_StoreManufacturerDeviceCertificate(const uint8_t * cert, size_t certLen)
346 return Impl()->WriteConfigValueBin(ImplClass::kConfigKey_MfrDeviceCert, cert, certLen);
349 template <class ImplClass>
350 CHIP_ERROR GenericConfigurationManagerImpl<ImplClass>::_GetManufacturerDeviceIntermediateCACerts(uint8_t * buf, size_t bufSize,
355 err = Impl()->ReadConfigValueBin(ImplClass::kConfigKey_MfrDeviceICACerts, buf, bufSize, certsLen);
357 #if CHIP_DEVICE_CONFIG_ENABLE_TEST_DEVICE_IDENTITY
359 if (err == CHIP_DEVICE_ERROR_CONFIG_NOT_FOUND)
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);
368 #endif // CHIP_DEVICE_CONFIG_ENABLE_TEST_DEVICE_IDENTITY
376 template <class ImplClass>
377 CHIP_ERROR GenericConfigurationManagerImpl<ImplClass>::_StoreManufacturerDeviceIntermediateCACerts(const uint8_t * certs,
380 return Impl()->WriteConfigValueBin(ImplClass::kConfigKey_MfrDeviceICACerts, certs, certsLen);
383 template <class ImplClass>
384 CHIP_ERROR GenericConfigurationManagerImpl<ImplClass>::_GetManufacturerDevicePrivateKey(uint8_t * buf, size_t bufSize,
389 err = Impl()->ReadConfigValueBin(ImplClass::kConfigKey_MfrDevicePrivateKey, buf, bufSize, keyLen);
391 #if CHIP_DEVICE_CONFIG_ENABLE_TEST_DEVICE_IDENTITY
393 if (err == CHIP_DEVICE_ERROR_CONFIG_NOT_FOUND)
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);
402 #endif // CHIP_DEVICE_CONFIG_ENABLE_TEST_DEVICE_IDENTITY
410 template <class ImplClass>
411 CHIP_ERROR GenericConfigurationManagerImpl<ImplClass>::_StoreManufacturerDevicePrivateKey(const uint8_t * key, size_t keyLen)
413 return Impl()->WriteConfigValueBin(ImplClass::kConfigKey_MfrDevicePrivateKey, key, keyLen);
416 template <class ImplClass>
417 CHIP_ERROR GenericConfigurationManagerImpl<ImplClass>::_GetDeviceId(uint64_t & deviceId)
421 #if CHIP_DEVICE_CONFIG_ENABLE_JUST_IN_TIME_PROVISIONING
422 if (!UseManufacturerCredentialsAsOperational())
424 err = Impl()->ReadConfigValue(ImplClass::kConfigKey_OperationalDeviceId, deviceId);
429 err = Impl()->_GetManufacturerDeviceId(deviceId);
435 template <class ImplClass>
436 CHIP_ERROR GenericConfigurationManagerImpl<ImplClass>::_GetDeviceCertificate(uint8_t * buf, size_t bufSize, size_t & certLen)
440 #if CHIP_DEVICE_CONFIG_ENABLE_JUST_IN_TIME_PROVISIONING
441 if (!UseManufacturerCredentialsAsOperational())
443 err = Impl()->ReadConfigValueBin(ImplClass::kConfigKey_OperationalDeviceCert, buf, bufSize, certLen);
448 err = Impl()->_GetManufacturerDeviceCertificate(buf, bufSize, certLen);
454 template <class ImplClass>
455 CHIP_ERROR GenericConfigurationManagerImpl<ImplClass>::_GetDeviceIntermediateCACerts(uint8_t * buf, size_t bufSize,
460 #if CHIP_DEVICE_CONFIG_ENABLE_JUST_IN_TIME_PROVISIONING
461 if (!UseManufacturerCredentialsAsOperational())
463 err = Impl()->ReadConfigValueBin(ImplClass::kConfigKey_OperationalDeviceICACerts, buf, bufSize, certsLen);
468 err = Impl()->_GetManufacturerDeviceIntermediateCACerts(buf, bufSize, certsLen);
474 template <class ImplClass>
475 CHIP_ERROR GenericConfigurationManagerImpl<ImplClass>::_GetDevicePrivateKey(uint8_t * buf, size_t bufSize, size_t & keyLen)
479 #if CHIP_DEVICE_CONFIG_ENABLE_JUST_IN_TIME_PROVISIONING
480 if (!UseManufacturerCredentialsAsOperational())
482 err = Impl()->ReadConfigValueBin(ImplClass::kConfigKey_OperationalDevicePrivateKey, buf, bufSize, keyLen);
487 err = Impl()->_GetManufacturerDevicePrivateKey(buf, bufSize, keyLen);
493 #if CHIP_DEVICE_CONFIG_ENABLE_JUST_IN_TIME_PROVISIONING
495 template <class ImplClass>
496 CHIP_ERROR GenericConfigurationManagerImpl<ImplClass>::_StoreDeviceId(uint64_t deviceId)
498 return Impl()->WriteConfigValue(ImplClass::kConfigKey_OperationalDeviceId, deviceId);
501 template <class ImplClass>
502 CHIP_ERROR GenericConfigurationManagerImpl<ImplClass>::_StoreDeviceCertificate(const uint8_t * cert, size_t certLen)
504 return Impl()->WriteConfigValueBin(ImplClass::kConfigKey_OperationalDeviceCert, cert, certLen);
507 template <class ImplClass>
508 CHIP_ERROR GenericConfigurationManagerImpl<ImplClass>::_StoreDeviceIntermediateCACerts(const uint8_t * certs, size_t certsLen)
510 return Impl()->WriteConfigValueBin(ImplClass::kConfigKey_OperationalDeviceICACerts, certs, certsLen);
513 template <class ImplClass>
514 CHIP_ERROR GenericConfigurationManagerImpl<ImplClass>::_StoreDevicePrivateKey(const uint8_t * key, size_t keyLen)
516 return Impl()->WriteConfigValueBin(ImplClass::kConfigKey_OperationalDevicePrivateKey, key, keyLen);
519 template <class ImplClass>
520 CHIP_ERROR GenericConfigurationManagerImpl<ImplClass>::_ClearOperationalDeviceCredentials(void)
522 Impl()->ClearConfigValue(ImplClass::kConfigKey_OperationalDeviceId);
523 Impl()->ClearConfigValue(ImplClass::kConfigKey_OperationalDeviceCert);
524 Impl()->ClearConfigValue(ImplClass::kConfigKey_OperationalDeviceICACerts);
525 Impl()->ClearConfigValue(ImplClass::kConfigKey_OperationalDevicePrivateKey);
527 ClearFlag(mFlags, kFlag_OperationalDeviceCredentialsProvisioned);
529 return CHIP_NO_ERROR;
532 template <class ImplClass>
533 bool GenericConfigurationManagerImpl<ImplClass>::_OperationalDeviceCredentialsProvisioned()
535 return ::chip::GetFlag(mFlags, kFlag_OperationalDeviceCredentialsProvisioned);
538 template <class ImplClass>
539 bool GenericConfigurationManagerImpl<ImplClass>::UseManufacturerCredentialsAsOperational()
541 return ::chip::GetFlag(mFlags, kFlag_UseManufacturerCredentialsAsOperational);
544 template <class ImplClass>
545 void GenericConfigurationManagerImpl<ImplClass>::_UseManufacturerCredentialsAsOperational(bool val)
547 SetFlag(mFlags, kFlag_UseManufacturerCredentialsAsOperational, val);
550 #endif // CHIP_DEVICE_CONFIG_ENABLE_JUST_IN_TIME_PROVISIONING
552 template <class ImplClass>
553 CHIP_ERROR GenericConfigurationManagerImpl<ImplClass>::_GetSetupPinCode(uint32_t & setupPinCode)
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)
561 setupPinCode = CHIP_DEVICE_CONFIG_USE_TEST_SETUP_PIN_CODE;
564 #endif // defined(CHIP_DEVICE_CONFIG_USE_TEST_SETUP_PIN_CODE) && CHIP_DEVICE_CONFIG_USE_TEST_SETUP_PIN_CODE
571 template <class ImplClass>
572 CHIP_ERROR GenericConfigurationManagerImpl<ImplClass>::_StoreSetupPinCode(uint32_t setupPinCode)
574 return Impl()->WriteConfigValue(ImplClass::kConfigKey_SetupPinCode, setupPinCode);
577 template <class ImplClass>
578 CHIP_ERROR GenericConfigurationManagerImpl<ImplClass>::_GetSetupDiscriminator(uint16_t & setupDiscriminator)
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)
587 val = CHIP_DEVICE_CONFIG_USE_TEST_SETUP_DISCRIMINATOR;
590 #endif // defined(CHIP_DEVICE_CONFIG_USE_TEST_SETUP_DISCRIMINATOR) && CHIP_DEVICE_CONFIG_USE_TEST_SETUP_DISCRIMINATOR
593 setupDiscriminator = static_cast<uint16_t>(val);
599 template <class ImplClass>
600 CHIP_ERROR GenericConfigurationManagerImpl<ImplClass>::_StoreSetupDiscriminator(uint16_t setupDiscriminator)
602 return Impl()->WriteConfigValue(ImplClass::kConfigKey_SetupDiscriminator, static_cast<uint32_t>(setupDiscriminator));
605 template <class ImplClass>
606 CHIP_ERROR GenericConfigurationManagerImpl<ImplClass>::_GetFabricId(uint64_t & fabricId)
608 CHIP_ERROR err = Impl()->ReadConfigValue(ImplClass::kConfigKey_FabricId, fabricId);
610 #if CHIP_DEVICE_CONFIG_ENABLE_TEST_DEVICE_IDENTITY
611 if (err == CHIP_DEVICE_ERROR_CONFIG_NOT_FOUND || err == CHIP_ERROR_KEY_NOT_FOUND)
613 fabricId = TestFabricId;
616 #endif // CHIP_DEVICE_CONFIG_ENABLE_TEST_DEVICE_IDENTITY
620 template <class ImplClass>
621 CHIP_ERROR GenericConfigurationManagerImpl<ImplClass>::_StoreFabricId(uint64_t fabricId)
623 CHIP_ERROR err = CHIP_NO_ERROR;
625 #if CHIP_CONFIG_ENABLE_FABRIC_STATE
626 if (fabricId != kFabricIdNotSpecified)
628 err = Impl()->WriteConfigValue(ImplClass::kConfigKey_FabricId, fabricId);
630 SetFlag(mFlags, kFlag_IsMemberOfFabric);
634 ClearFlag(mFlags, kFlag_IsMemberOfFabric);
635 err = Impl()->ClearConfigValue(ImplClass::kConfigKey_FabricId);
645 template <class ImplClass>
646 CHIP_ERROR GenericConfigurationManagerImpl<ImplClass>::_GetServiceId(uint64_t & serviceId)
648 return Impl()->ReadConfigValue(ImplClass::kConfigKey_ServiceId, serviceId);
651 template <class ImplClass>
652 CHIP_ERROR GenericConfigurationManagerImpl<ImplClass>::_GetServiceConfig(uint8_t * buf, size_t bufSize, size_t & serviceConfigLen)
654 return Impl()->ReadConfigValueBin(ImplClass::kConfigKey_ServiceConfig, buf, bufSize, serviceConfigLen);
657 template <class ImplClass>
658 CHIP_ERROR GenericConfigurationManagerImpl<ImplClass>::_StoreServiceConfig(const uint8_t * serviceConfig, size_t serviceConfigLen)
660 return Impl()->WriteConfigValueBin(ImplClass::kConfigKey_ServiceConfig, serviceConfig, serviceConfigLen);
663 #if CHIP_ENABLE_ROTATING_DEVICE_ID
664 template <class ImplClass>
665 CHIP_ERROR GenericConfigurationManagerImpl<ImplClass>::_GetLifetimeCounter(uint16_t & lifetimeCounter)
667 lifetimeCounter = static_cast<uint16_t>(mLifetimePersistedCounter.GetValue());
668 return CHIP_NO_ERROR;
671 template <class ImplClass>
672 CHIP_ERROR GenericConfigurationManagerImpl<ImplClass>::_IncrementLifetimeCounter()
674 return mLifetimePersistedCounter.Advance();
678 template <class ImplClass>
679 CHIP_ERROR GenericConfigurationManagerImpl<ImplClass>::_GetPairedAccountId(char * buf, size_t bufSize, size_t & accountIdLen)
681 return Impl()->ReadConfigValueStr(ImplClass::kConfigKey_PairedAccountId, buf, bufSize, accountIdLen);
684 template <class ImplClass>
685 CHIP_ERROR GenericConfigurationManagerImpl<ImplClass>::_StorePairedAccountId(const char * accountId, size_t accountIdLen)
689 err = Impl()->WriteConfigValueStr(ImplClass::kConfigKey_PairedAccountId, accountId, accountIdLen);
692 SetFlag(mFlags, kFlag_IsPairedToAccount, (accountId != nullptr && accountIdLen != 0));
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)
706 err = Impl()->WriteConfigValue(ImplClass::kConfigKey_ServiceId, serviceId);
709 err = _StoreServiceConfig(serviceConfig, serviceConfigLen);
712 err = _StorePairedAccountId(accountId, accountIdLen);
715 SetFlag(mFlags, kFlag_IsServiceProvisioned);
716 SetFlag(mFlags, kFlag_IsPairedToAccount, (accountId != nullptr && accountIdLen != 0));
719 if (err != CHIP_NO_ERROR)
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);
730 template <class ImplClass>
731 CHIP_ERROR GenericConfigurationManagerImpl<ImplClass>::_ClearServiceProvisioningData()
733 Impl()->ClearConfigValue(ImplClass::kConfigKey_ServiceId);
734 Impl()->ClearConfigValue(ImplClass::kConfigKey_ServiceConfig);
735 Impl()->ClearConfigValue(ImplClass::kConfigKey_PairedAccountId);
737 // TODO: Move these behaviors out of configuration manager.
739 // If necessary, post an event alerting other subsystems to the change in
740 // the account pairing state.
741 if (_IsPairedToAccount())
743 ChipDeviceEvent event;
744 event.Type = DeviceEventType::kAccountPairingChange;
745 event.AccountPairingChange.IsPairedToAccount = false;
746 PlatformMgr().PostEvent(&event);
749 // If necessary, post an event alerting other subsystems to the change in
750 // the service provisioning state.
751 if (_IsServiceProvisioned())
753 ChipDeviceEvent event;
754 event.Type = DeviceEventType::kServiceProvisioningChange;
755 event.ServiceProvisioningChange.IsServiceProvisioned = false;
756 event.ServiceProvisioningChange.ServiceConfigUpdated = false;
757 PlatformMgr().PostEvent(&event);
760 ClearFlag(mFlags, kFlag_IsServiceProvisioned);
761 ClearFlag(mFlags, kFlag_IsPairedToAccount);
763 return CHIP_NO_ERROR;
766 template <class ImplClass>
767 CHIP_ERROR GenericConfigurationManagerImpl<ImplClass>::_GetFailSafeArmed(bool & val)
769 return Impl()->ReadConfigValue(ImplClass::kConfigKey_FailSafeArmed, val);
772 template <class ImplClass>
773 CHIP_ERROR GenericConfigurationManagerImpl<ImplClass>::_SetFailSafeArmed(bool val)
775 return Impl()->WriteConfigValue(ImplClass::kConfigKey_FailSafeArmed, val);
778 template <class ImplClass>
779 CHIP_ERROR GenericConfigurationManagerImpl<ImplClass>::_GetQRCodeString(char * buf, size_t bufSize)
781 return CHIP_ERROR_NOT_IMPLEMENTED;
784 template <class ImplClass>
785 CHIP_ERROR GenericConfigurationManagerImpl<ImplClass>::_GetWiFiAPSSID(char * buf, size_t bufSize)
789 #ifdef CHIP_DEVICE_CONFIG_WIFI_AP_SSID_PREFIX
793 VerifyOrExit(bufSize >= sizeof(CHIP_DEVICE_CONFIG_WIFI_AP_SSID_PREFIX) + 4, err = CHIP_ERROR_BUFFER_TOO_SMALL);
795 err = Impl()->_GetPrimaryWiFiMACAddress(mac);
798 snprintf(buf, bufSize, "%s%02X%02X", CHIP_DEVICE_CONFIG_WIFI_AP_SSID_PREFIX, mac[4], mac[5]);
799 buf[bufSize - 1] = 0;
801 #else // CHIP_DEVICE_CONFIG_WIFI_AP_SSID_PREFIX
803 ExitNow(err = CHIP_DEVICE_ERROR_CONFIG_NOT_FOUND);
805 #endif // CHIP_DEVICE_CONFIG_WIFI_AP_SSID_PREFIX
811 template <class ImplClass>
813 GenericConfigurationManagerImpl<ImplClass>::_GetBLEDeviceIdentificationInfo(Ble::ChipBLEDeviceIdentificationInfo & deviceIdInfo)
817 uint16_t discriminator;
821 err = Impl()->_GetVendorId(id);
823 deviceIdInfo.SetVendorId(id);
825 err = Impl()->_GetProductId(id);
827 deviceIdInfo.SetProductId(id);
829 err = Impl()->_GetSetupDiscriminator(discriminator);
831 deviceIdInfo.SetDeviceDiscriminator(discriminator);
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;
843 deviceIdInfo.PairingStatus = Impl()->_IsPairedToAccount() ? Ble::ChipBLEDeviceIdentificationInfo::kPairingStatus_Paired
844 : Ble::ChipBLEDeviceIdentificationInfo::kPairingStatus_Unpaired;
851 template <class ImplClass>
852 bool GenericConfigurationManagerImpl<ImplClass>::_IsServiceProvisioned()
854 return ::chip::GetFlag(mFlags, kFlag_IsServiceProvisioned);
857 template <class ImplClass>
858 bool GenericConfigurationManagerImpl<ImplClass>::_IsMemberOfFabric()
860 return ::chip::GetFlag(mFlags, kFlag_IsMemberOfFabric);
863 template <class ImplClass>
864 bool GenericConfigurationManagerImpl<ImplClass>::_IsPairedToAccount()
866 return ::chip::GetFlag(mFlags, kFlag_IsPairedToAccount);
869 template <class ImplClass>
870 bool GenericConfigurationManagerImpl<ImplClass>::_IsFullyProvisioned()
872 #if CHIP_BYPASS_RENDEZVOUS
874 #else // CHIP_BYPASS_RENDEZVOUS
877 #if CHIP_DEVICE_CONFIG_ENABLE_WIFI_STATION
878 ConnectivityMgr().IsWiFiStationProvisioned() &&
880 #if CHIP_DEVICE_CONFIG_ENABLE_THREAD
881 ConnectivityMgr().IsThreadProvisioned() &&
883 #if CHIP_DEVICE_CONFIG_ENABLE_JUST_IN_TIME_PROVISIONING
884 (!UseManufacturerCredentialsAsOperational() && _OperationalDeviceCredentialsProvisioned()) &&
886 // TODO: Add checks regarding fabric membership (IsMemberOfFabric()) and account pairing (IsPairedToAccount()),
887 // when functionalities will be implemented.
889 #endif // CHIP_BYPASS_RENDEZVOUS
892 template <class ImplClass>
893 CHIP_ERROR GenericConfigurationManagerImpl<ImplClass>::_ComputeProvisioningHash(uint8_t * hashBuf, size_t hashBufSize)
895 CHIP_ERROR err = CHIP_NO_ERROR;
897 #if CHIP_DEVICE_CONFIG_LOG_PROVISIONING_HASH
898 using HashAlgo = chip::Crypto::Hash_SHA256_stream;
901 chip::Platform::ScopedMemoryBuffer dataBuf;
903 constexpr uint16_t kLenFieldLen = 4; // 4 hex characters
905 VerifyOrExit(hashBufSize >= chip::Crypto::kSHA256_Hash_Length, err = CHIP_ERROR_BUFFER_TOO_SMALL);
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.
910 // A CHIP provisioning hash is a SHA-256 hash of an ASCII string with the following format:
912 // DDDDddddddddddddddddCCCCcccc…ccccIIIIiiii…iiiiKKKKkkkk…kkkkPPPPpppppp
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.
929 // Hash the device id
932 constexpr uint16_t kDeviceIdLen = 16; // 16 hex characters
933 char inputBuf[kLenFieldLen + kDeviceIdLen + 1]; // +1 for terminator
935 err = Impl()->_GetManufacturerDeviceId(deviceId);
938 snprintf(inputBuf, sizeof(inputBuf), "0010%016" PRIX64, deviceId);
940 hash.AddData((uint8_t *) inputBuf, kLenFieldLen + kDeviceIdLen);
943 // Hash the device certificate
947 // Determine the length of the device certificate.
948 err = Impl()->_GetManufacturerDeviceCertificate((uint8_t *) NULL, 0, certLen);
951 // Create a temporary buffer to hold the certificate. (This will also be used for
953 dataBufSize = certLen;
954 VerifyOrExit(dataBuf.Alloc(dataBufSize), err = CHIP_ERROR_NO_MEMORY);
956 // Read the certificate.
957 err = Impl()->_GetManufacturerDeviceCertificate(dataBuf.Ptr<uint8_t>(), certLen, certLen);
961 // Hash the device intermediate CA certificates
962 if (Impl()->ConfigValueExists(ImplClass::kConfigKey_MfrDeviceICACerts))
966 // Determine the length of the device intermediate CA certificates.
967 err = Impl()->_GetManufacturerDeviceIntermediateCACerts((uint8_t *) NULL, 0, certsLen);
970 // Allocate larger buffer to hold the intermediate CA certificates.
971 // (This will also be used for the private key).
972 if (certsLen > dataBufSize)
974 dataBufSize = certsLen;
975 VerifyOrExit(dataBuf.Alloc(dataBufSize), err = CHIP_ERROR_NO_MEMORY);
978 // Read the device intermediate CA certificates.
979 err = Impl()->_GetManufacturerDeviceIntermediateCACerts(dataBuf.Ptr<uint8_t>(), certsLen, certsLen);
983 // Hash the device private key
987 // Determine the length of the device private key.
988 err = Impl()->_GetManufacturerDevicePrivateKey((uint8_t *) NULL, 0, keyLen);
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);
998 // Hash the device pairing code. If the device does not have a pairing code, hash a zero-length value.
1000 char pairingCode[ConfigurationManager::kMaxPairingCodeLength + 1]; // +1 for terminator
1001 char lenStr[kLenFieldLen + 1]; // +1 for terminator
1002 size_t pairingCodeLen;
1004 err = Impl()->_GetPairingCode(pairingCode, sizeof(pairingCode), pairingCodeLen);
1005 if (err == CHIP_DEVICE_ERROR_CONFIG_NOT_FOUND)
1008 err = CHIP_NO_ERROR;
1012 snprintf(lenStr, sizeof(lenStr), "%04" PRIX16, (uint16_t) pairingCodeLen);
1014 hash.AddData((uint8_t *) lenStr, kLenFieldLen);
1015 hash.AddData((uint8_t *) pairingCode, pairingCodeLen);
1018 hash.Finish(hashBuf);
1023 chip::Crypto::ClearSecretData(dataBuf.Ptr(), dataBufSize);
1025 #endif // CHIP_DEVICE_CONFIG_LOG_PROVISIONING_HASH
1030 #if !defined(NDEBUG)
1031 template <class ImplClass>
1032 CHIP_ERROR GenericConfigurationManagerImpl<ImplClass>::_RunUnitTests()
1034 ChipLogProgress(DeviceLayer, "Running configuration unit test");
1035 Impl()->RunConfigUnitTest();
1037 return CHIP_NO_ERROR;
1041 template <class ImplClass>
1042 void GenericConfigurationManagerImpl<ImplClass>::_LogDeviceConfig()
1046 ChipLogProgress(DeviceLayer, "Device Configuration:");
1048 #if CHIP_CONFIG_ENABLE_FABRIC_STATE
1049 ChipLogProgress(DeviceLayer, " Device Id: %016" PRIX64, FabricState.LocalNodeId);
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)");
1061 if (Impl()->_GetVendorId(vendorId) != CHIP_NO_ERROR)
1065 ChipLogProgress(DeviceLayer, " Vendor Id: %" PRIu16 " (0x%" PRIX16 ")", vendorId, vendorId);
1070 if (Impl()->_GetProductId(productId) != CHIP_NO_ERROR)
1074 ChipLogProgress(DeviceLayer, " Product Id: %" PRIu16 " (0x%" PRIX16 ")", productId, productId);
1078 uint16_t productRev;
1079 if (Impl()->_GetProductRevision(productRev) != CHIP_NO_ERROR)
1083 ChipLogProgress(DeviceLayer, " Product Revision: %" PRIu16, productRev);
1087 uint32_t setupPINCode;
1088 if (Impl()->_GetSetupPinCode(setupPINCode) != CHIP_NO_ERROR)
1092 ChipLogProgress(DeviceLayer, " Setup Pin Code: %" PRIu32 "", setupPINCode);
1096 uint16_t setupDiscriminator;
1097 if (Impl()->_GetSetupDiscriminator(setupDiscriminator) != CHIP_NO_ERROR)
1099 setupDiscriminator = 0;
1101 ChipLogProgress(DeviceLayer, " Setup Discriminator: %" PRIu16 " (0x%" PRIX16 ")", setupDiscriminator, setupDiscriminator);
1106 uint8_t month, dayOfMonth;
1107 err = Impl()->_GetManufacturingDate(year, month, dayOfMonth);
1108 if (err == CHIP_NO_ERROR)
1110 ChipLogProgress(DeviceLayer, " Manufacturing Date: %04" PRIu16 "/%02" PRIu8 "/%02" PRIu8, year, month, dayOfMonth);
1114 ChipLogProgress(DeviceLayer, " Manufacturing Date: (not set)");
1118 #if CHIP_CONFIG_ENABLE_FABRIC_STATE
1119 if (FabricState.FabricId != kFabricIdNotSpecified)
1121 ChipLogProgress(DeviceLayer, " Fabric Id: %016" PRIX64, FabricState.FabricId);
1125 ChipLogProgress(DeviceLayer, " Fabric Id: (none)");
1128 ChipLogProgress(DeviceLayer, " Pairing Code: %s", (FabricState.PairingCode != NULL) ? FabricState.PairingCode : "(none)");
1129 #endif // CHIP_CONFIG_ENABLE_FABRIC_STATE
1132 // Fully instantiate the generic implementation class in whatever compilation unit includes this file.
1133 template class GenericConfigurationManagerImpl<ConfigurationManagerImpl>;
1135 } // namespace Internal
1136 } // namespace DeviceLayer
1139 #endif // GENERIC_CONFIGURATION_MANAGER_IMPL_CPP