/* * * Copyright (c) 2025 Project CHIP Authors * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #include #include #include #include #include #include namespace chip { namespace DeviceLayer { const char * ESP32ManufacturingDataProvider::PrecedenceToString(Precedence precedence) { switch (precedence) { case Precedence::kFactoryFirst: return "FactoryFirst"; case Precedence::kSecureCertFirst: return "SecureCertFirst"; default: return "Unknown"; } } ESP32ManufacturingDataProvider::ESP32ManufacturingDataProvider(Precedence precedence) : CommissionableDataProvider() #if CHIP_DEVICE_CONFIG_ENABLE_DEVICE_INSTANCE_INFO_PROVIDER , Internal::GenericDeviceInstanceInfoProvider(ConfigurationManagerImpl::GetDefaultInstance()) #endif , mPrecedence(precedence) { // check data integrity of both factory and secure cert data, we should have at least one valid data provider mFactoryDataValid = CheckFactoryDataIntegrity(); mSecureCertDataValid = CheckSecureCertDataIntegrity(); // should we really die here? can the non-Matter functionality still work? VerifyOrReturn(mFactoryDataValid || mSecureCertDataValid, ChipLogError(DeviceLayer, "No valid data found in factory or secure cert partition")); SetProvidersAsPerPrecedence(); ChipLogDetail(DeviceLayer, "ESP32ManufacturingDataProvider initialized with precedence:%s", PrecedenceToString(precedence)); } ESP32ManufacturingDataProvider::Precedence ESP32ManufacturingDataProvider::GetPrecedence() const { return mPrecedence; } // check if the factory has valid data, if not, return false bool ESP32ManufacturingDataProvider::CheckFactoryDataIntegrity() { uint16_t setupDiscriminator; uint32_t iterationCount; uint8_t saltBuf[chip::Crypto::kSpake2p_Max_PBKDF_Salt_Length]; uint8_t verifierBuf[chip::Crypto::kSpake2p_VerifierSerialized_Length]; uint8_t uniqueIdSpan[ConfigurationManager::kRotatingDeviceIDUniqueIDLength]; MutableByteSpan salt(saltBuf); MutableByteSpan verifier(verifierBuf); size_t verifierLen; MutableByteSpan uniqueId(uniqueIdSpan); VerifyOrReturnValue(mPrecedence == Precedence::kFactoryFirst, false); VerifyOrReturnValue(mFactoryDataProvider.GetSetupDiscriminator(setupDiscriminator) == CHIP_NO_ERROR, false); VerifyOrReturnValue(mFactoryDataProvider.GetSpake2pIterationCount(iterationCount) == CHIP_NO_ERROR, false); VerifyOrReturnValue(mFactoryDataProvider.GetSpake2pSalt(salt) == CHIP_NO_ERROR, false); VerifyOrReturnValue(mFactoryDataProvider.GetSpake2pVerifier(verifier, verifierLen) == CHIP_NO_ERROR, false); #if CHIP_DEVICE_CONFIG_ENABLE_DEVICE_INSTANCE_INFO_PROVIDER && CHIP_ENABLE_ROTATING_DEVICE_ID VerifyOrReturnValue(mFactoryDataProvider.GetRotatingDeviceIdUniqueId(uniqueId) == CHIP_NO_ERROR, false); #endif // CHIP_DEVICE_CONFIG_ENABLE_DEVICE_INSTANCE_INFO_PROVIDER && CHIP_ENABLE_ROTATING_DEVICE_ID return true; } // check if the secure cert has valid data, if not, return false bool ESP32ManufacturingDataProvider::CheckSecureCertDataIntegrity() { uint16_t setupDiscriminator; uint32_t iterationCount; uint8_t saltBuf[chip::Crypto::kSpake2p_Max_PBKDF_Salt_Length]; uint8_t verifierBuf[chip::Crypto::kSpake2p_VerifierSerialized_Length]; uint8_t uniqueIdSpan[ConfigurationManager::kRotatingDeviceIDUniqueIDLength]; MutableByteSpan salt(saltBuf); MutableByteSpan verifier(verifierBuf); size_t verifierLen; MutableByteSpan uniqueId(uniqueIdSpan); VerifyOrReturnValue(mSecureCertDataProvider.GetSetupDiscriminator(setupDiscriminator) == CHIP_NO_ERROR, false); VerifyOrReturnValue(mSecureCertDataProvider.GetSpake2pIterationCount(iterationCount) == CHIP_NO_ERROR, false); VerifyOrReturnValue(mSecureCertDataProvider.GetSpake2pSalt(salt) == CHIP_NO_ERROR, false); VerifyOrReturnValue(mSecureCertDataProvider.GetSpake2pVerifier(verifier, verifierLen) == CHIP_NO_ERROR, false); #if CHIP_DEVICE_CONFIG_ENABLE_DEVICE_INSTANCE_INFO_PROVIDER && CHIP_ENABLE_ROTATING_DEVICE_ID VerifyOrReturnValue(mSecureCertDataProvider.GetRotatingDeviceIdUniqueId(uniqueId) == CHIP_NO_ERROR, false); #endif // CHIP_DEVICE_CONFIG_ENABLE_DEVICE_INSTANCE_INFO_PROVIDER && CHIP_ENABLE_ROTATING_DEVICE_ID return true; } CHIP_ERROR ESP32ManufacturingDataProvider::SetProvidersAsPerPrecedence() { bool useFactoryData = false; // we performed CheckFactoryDataIntegrity() and CheckSecureCertDataIntegrity() in constructor, // so we can use the result here switch (mPrecedence) { case Precedence::kFactoryFirst: { useFactoryData = mFactoryDataValid; break; } case Precedence::kSecureCertFirst: { useFactoryData = !mSecureCertDataValid; break; } default: { ChipLogError(DeviceLayer, "Invalid precedence"); return CHIP_ERROR_INVALID_ARGUMENT; } } ChipLogProgress(DeviceLayer, "Using commissionable and device instance info providers from %s", useFactoryData ? "factory" : "secure cert"); mCommissionableDataProvider = useFactoryData ? &mFactoryDataProvider : &mSecureCertDataProvider; mDeviceInstanceInfoProvider = useFactoryData ? &mFactoryDataProvider : &mSecureCertDataProvider; return CHIP_NO_ERROR; } CHIP_ERROR ESP32ManufacturingDataProvider::GetSetupDiscriminator(uint16_t &setupDiscriminator) { return mCommissionableDataProvider->GetSetupDiscriminator(setupDiscriminator); } CHIP_ERROR ESP32ManufacturingDataProvider::GetSpake2pIterationCount(uint32_t &iterationCount) { return mCommissionableDataProvider->GetSpake2pIterationCount(iterationCount); } CHIP_ERROR ESP32ManufacturingDataProvider::GetSpake2pSalt(MutableByteSpan &saltBuf) { return mCommissionableDataProvider->GetSpake2pSalt(saltBuf); } CHIP_ERROR ESP32ManufacturingDataProvider::GetSpake2pVerifier(MutableByteSpan &verifierBuf, size_t &verifierLen) { return mCommissionableDataProvider->GetSpake2pVerifier(verifierBuf, verifierLen); } CHIP_ERROR ESP32ManufacturingDataProvider::GetRotatingDeviceIdUniqueId(MutableByteSpan &uniqueIdSpan) { #if CHIP_DEVICE_CONFIG_ENABLE_DEVICE_INSTANCE_INFO_PROVIDER && CHIP_ENABLE_ROTATING_DEVICE_ID return mDeviceInstanceInfoProvider->GetRotatingDeviceIdUniqueId(uniqueIdSpan); #else return CHIP_ERROR_NOT_IMPLEMENTED; #endif // CHIP_DEVICE_CONFIG_ENABLE_DEVICE_INSTANCE_INFO_PROVIDER && CHIP_ENABLE_ROTATING_DEVICE_ID } } // namespace DeviceLayer } // namespace chip