From 8ae80e679b6865c1c608dacef4edaa17248b7cd3 Mon Sep 17 00:00:00 2001 From: Tennessee Carmel-Veilleux Date: Fri, 11 Mar 2022 15:49:56 -0500 Subject: [PATCH] Introduce CommissionableDataProvider for discriminator and verifier (#16020) * Introduce CommissionableDataProvider for discriminator and verifier - Current API in ConfigurationManager makes it very hard to provide spec-mandated per-device SPAKE2+ parameters (verifier, salt, iteration counts) and discovery discriminator, since it expects "in-app" common SDK handling of the data for something that actually usually comes from the factory. This PR does the following: - Adds CommissionableDataProvider interface, of which an instance is known to the ConfigurationManager. - Adds a legacy path to avoid requiring setting a CommissionableDataProvider in the short term - A linux implementation of CommissionableDataProvider showcasing providing externally generated SPAKE2+ verifier/salt/iterations - Refactoring of all direct usage of ConfigurationManager to get discriminator/SPAKE2+ parameters Testing done: - Cert tests still pass with no change - All unit tests still pass, including those modified - Setting GN arg `chip_use_transitional_commissionable_data_provider=0` properly causes targets that don't provide an implementation from running. - Manually verified the new Linux command-line arguments to all-clusters-app allow passing custom version of verifier or iteration counts. Fixes #15543 * Restyled by clang-format * Restyled by gn * Fix PRIu32 * Fix more presubmit rework failures * Fix one missing override * Address review comments * Restyled by clang-format * Fix more CI, do more renames * Restyled by clang-format * Address review comments * Restyled by clang-format * Restyled by gn * Fix doxygen stuff * Fix fake ConfigurationaManagerImpl.h * Fix cirque * Address review comments from PR #16020 * Fix CI after refactor based on review comments Co-authored-by: Restyled.io --- examples/bridge-app/linux/main.cpp | 5 +- .../common/CredentialIssuerCommands.h | 6 +- examples/common/pigweed/rpc_services/Device.h | 10 +- examples/platform/linux/AppMain.cpp | 60 +++- examples/platform/linux/BUILD.gn | 2 + .../linux/LinuxCommissionableDataProvider.cpp | 227 ++++++++++++ .../linux/LinuxCommissionableDataProvider.h | 86 +++++ examples/platform/linux/Options.cpp | 126 ++++++- examples/platform/linux/Options.h | 5 + .../administrator-commissioning-server.cpp | 1 + src/app/server/CommissioningWindowManager.cpp | 39 +-- src/app/server/CommissioningWindowManager.h | 3 - src/app/server/Dnssd.cpp | 27 +- src/app/server/Dnssd.h | 14 + src/app/server/OnboardingCodesUtil.cpp | 17 +- src/app/tests/TestCommissionManager.cpp | 17 +- .../python/chip/native/StackInit.cpp | 9 + .../DeviceAttestationCredsProvider.h | 10 +- .../platform/CommissionableDataProvider.h | 165 +++++++++ src/include/platform/ConfigurationManager.h | 7 - .../TestOnlyCommissionableDataProvider.h | 107 ++++++ .../GenericConfigurationManagerImpl.cpp | 329 ++++++++++-------- .../GenericConfigurationManagerImpl.h | 19 +- src/lib/shell/commands/Config.cpp | 11 +- src/platform/Ameba/BLEManagerImpl.cpp | 3 +- src/platform/BUILD.gn | 15 + src/platform/CommissionableDataProvider.cpp | 47 +++ .../ESP32/ConnectivityManagerImpl_WiFi.cpp | 3 +- .../ESP32/bluedroid/BLEManagerImpl.cpp | 3 +- src/platform/ESP32/nimble/BLEManagerImpl.cpp | 3 +- src/platform/Linux/BLEManagerImpl.cpp | 3 +- .../Linux/ConnectivityManagerImpl.cpp | 3 +- ...nericThreadStackManagerImpl_OpenThread.cpp | 10 +- src/platform/fake/ConfigurationManagerImpl.h | 10 - src/platform/mbed/BLEManagerImpl.cpp | 3 +- .../nxp/k32w/k32w0/BLEManagerImpl.cpp | 4 +- src/platform/tests/TestConfigurationMgr.cpp | 34 -- src/setup_payload/SetupPayload.h | 3 - 38 files changed, 1161 insertions(+), 285 deletions(-) create mode 100644 examples/platform/linux/LinuxCommissionableDataProvider.cpp create mode 100644 examples/platform/linux/LinuxCommissionableDataProvider.h create mode 100644 src/include/platform/CommissionableDataProvider.h create mode 100644 src/include/platform/TestOnlyCommissionableDataProvider.h create mode 100644 src/platform/CommissionableDataProvider.cpp diff --git a/examples/bridge-app/linux/main.cpp b/examples/bridge-app/linux/main.cpp index 62f311909dbcc2..2fec367c1c9f57 100644 --- a/examples/bridge-app/linux/main.cpp +++ b/examples/bridge-app/linux/main.cpp @@ -34,6 +34,7 @@ #include #include #include +#include #include #include @@ -550,10 +551,10 @@ CHIP_ERROR PrintQRCodeContent() uint16_t productId; std::string result; - err = ConfigurationMgr().GetSetupPinCode(setUpPINCode); + err = GetCommissionableDataProvider()->GetSetupPasscode(setUpPINCode); SuccessOrExit(err); - err = ConfigurationMgr().GetSetupDiscriminator(setUpDiscriminator); + err = GetCommissionableDataProvider()->GetSetupDiscriminator(setUpDiscriminator); SuccessOrExit(err); err = ConfigurationMgr().GetVendorId(vendorId); diff --git a/examples/chip-tool/commands/common/CredentialIssuerCommands.h b/examples/chip-tool/commands/common/CredentialIssuerCommands.h index 45f647c317becc..0682aef4876da5 100644 --- a/examples/chip-tool/commands/common/CredentialIssuerCommands.h +++ b/examples/chip-tool/commands/common/CredentialIssuerCommands.h @@ -64,9 +64,9 @@ class CredentialIssuerCommands * @param[in] nodeId The desired NodeId for the generated NOC Chain - May be optional/unused in some implementations. * @param[in] fabricId The desired FabricId for the generated NOC Chain - May be optional/unused in some implementations. * @param[in] keypair The desired Keypair for the generated NOC Chain - May be optional/unused in some implementations. - * @param[inout] rcac Buffer to hold the Root Certificate of the generated NOC Chain. - * @param[inout] icac Buffer to hold the Intermediate Certificate of the generated NOC Chain. - * @param[inout] noc Buffer to hold the Leaf Certificate of the generated NOC Chain. + * @param[in,out] rcac Buffer to hold the Root Certificate of the generated NOC Chain. + * @param[in,out] icac Buffer to hold the Intermediate Certificate of the generated NOC Chain. + * @param[in,out] noc Buffer to hold the Leaf Certificate of the generated NOC Chain. * * @return CHIP_ERROR CHIP_NO_ERROR on success, or corresponding error code. */ diff --git a/examples/common/pigweed/rpc_services/Device.h b/examples/common/pigweed/rpc_services/Device.h index 3b95996cbff283..fc5605d7dbd538 100644 --- a/examples/common/pigweed/rpc_services/Device.h +++ b/examples/common/pigweed/rpc_services/Device.h @@ -19,6 +19,7 @@ #pragma once #include +#include #include "app/server/OnboardingCodesUtil.h" #include "app/server/Server.h" @@ -126,14 +127,14 @@ class Device : public pw_rpc::nanopb::Device::Service } uint32_t code; - if (DeviceLayer::ConfigurationMgr().GetSetupPinCode(code) == CHIP_NO_ERROR) + if (DeviceLayer::GetCommissionableDataProvider()->GetSetupPasscode(code) == CHIP_NO_ERROR) { response.pairing_info.code = code; response.has_pairing_info = true; } uint16_t discriminator; - if (DeviceLayer::ConfigurationMgr().GetSetupDiscriminator(discriminator) == CHIP_NO_ERROR) + if (DeviceLayer::GetCommissionableDataProvider()->GetSetupDiscriminator(discriminator) == CHIP_NO_ERROR) { response.pairing_info.discriminator = static_cast(discriminator); response.has_pairing_info = true; @@ -158,8 +159,9 @@ class Device : public pw_rpc::nanopb::Device::Service virtual pw::Status SetPairingInfo(const chip_rpc_PairingInfo & request, pw_protobuf_Empty & response) { - if (DeviceLayer::ConfigurationMgr().StoreSetupPinCode(request.code) != CHIP_NO_ERROR || - DeviceLayer::ConfigurationMgr().StoreSetupDiscriminator(request.discriminator) != CHIP_NO_ERROR) + if (DeviceLayer::GetCommissionableDataProvider()->SetSetupPasscode(request.code) != CHIP_NO_ERROR || + DeviceLayer::GetCommissionableDataProvider()->SetSetupDiscriminator(request.discriminator) != + CHIP_NO_ERROR) { return pw::Status::Unknown(); } diff --git a/examples/platform/linux/AppMain.cpp b/examples/platform/linux/AppMain.cpp index 2b6221095fec58..bb77b5a60c0477 100644 --- a/examples/platform/linux/AppMain.cpp +++ b/examples/platform/linux/AppMain.cpp @@ -22,8 +22,10 @@ #include #include #include +#include #include #include +#include #include #include @@ -35,7 +37,9 @@ #include #include +#include #include +#include #if CHIP_DEVICE_CONFIG_ENABLE_BOTH_COMMISSIONER_AND_COMMISSIONEE #include @@ -58,6 +62,7 @@ #include #include "AppMain.h" +#include "LinuxCommissionableDataProvider.h" using namespace chip; using namespace chip::ArgParser; @@ -142,6 +147,50 @@ void SetupSignalHandlers() signal(SIGIO, OnSignalHandler); signal(SIGINT, OnSignalHandler); } + +CHIP_ERROR InitCommissionableDataProvider(LinuxCommissionableDataProvider & provider, LinuxDeviceOptions & options) +{ + chip::Optional setupPasscode; + + if (options.payload.setUpPINCode != 0) + { + setupPasscode.SetValue(options.payload.setUpPINCode); + } + else if (!options.spake2pVerifier.HasValue()) + { + uint32_t defaultTestPasscode = 0; + chip::DeviceLayer::TestOnlyCommissionableDataProvider TestOnlyCommissionableDataProvider; + VerifyOrDie(TestOnlyCommissionableDataProvider.GetSetupPasscode(defaultTestPasscode) == CHIP_NO_ERROR); + + ChipLogError(Support, + "*** WARNING: Using temporary passcode %u due to no neither --passcode or --spake2p-verifier-base64 " + "given on command line. This is temporary and will disappear. Please update your scripts " + "to explicitly configure onboarding credentials. ***", + static_cast(defaultTestPasscode)); + setupPasscode.SetValue(defaultTestPasscode); + options.payload.setUpPINCode = defaultTestPasscode; + } + else + { + // Passcode is 0, so will be ignored, and verifier will take over. Onboarding payload + // printed for debug will be invalid, but if the onboarding payload had been given + // properly to the commissioner later, PASE will succeed. + } + + // Default to minimum PBKDF iterations + uint32_t spake2pIterationCount = chip::Crypto::kSpake2p_Min_PBKDF_Iterations; + if (options.spake2pIterations != 0) + { + spake2pIterationCount = options.spake2pIterations; + } + ChipLogError(Support, "PASE PBKDF iterations set to %u", static_cast(spake2pIterationCount)); + + return provider.Init(options.spake2pVerifier, options.spake2pSalt, spake2pIterationCount, setupPasscode, + options.payload.discriminator); +} + +// To hold SPAKE2+ verifier, discriminator, passcode +LinuxCommissionableDataProvider gCommissionableDataProvider; } // namespace #if CHIP_DEVICE_CONFIG_ENABLE_WPA @@ -195,12 +244,11 @@ int ChipLinuxAppInit(int argc, char ** argv, OptionSet * customOptions) err = DeviceLayer::PlatformMgr().InitChipStack(); SuccessOrExit(err); - if (0 != LinuxDeviceOptions::GetInstance().payload.discriminator) - { - uint16_t discriminator = LinuxDeviceOptions::GetInstance().payload.discriminator; - err = DeviceLayer::ConfigurationMgr().StoreSetupDiscriminator(discriminator); - SuccessOrExit(err); - } + // Init the commissionable data provider based on command line options + // to handle custom verifiers, discriminators, etc. + err = InitCommissionableDataProvider(gCommissionableDataProvider, LinuxDeviceOptions::GetInstance()); + SuccessOrExit(err); + DeviceLayer::SetCommissionableDataProvider(&gCommissionableDataProvider); err = GetSetupPayload(LinuxDeviceOptions::GetInstance().payload, rendezvousFlags); SuccessOrExit(err); diff --git a/examples/platform/linux/BUILD.gn b/examples/platform/linux/BUILD.gn index 99175e4d2aa4cf..7c8c9d666fa508 100644 --- a/examples/platform/linux/BUILD.gn +++ b/examples/platform/linux/BUILD.gn @@ -30,6 +30,8 @@ source_set("app-main") { "CommissioneeShellCommands.h", "ControllerShellCommands.cpp", "ControllerShellCommands.h", + "LinuxCommissionableDataProvider.cpp", + "LinuxCommissionableDataProvider.h", "Options.cpp", "Options.h", ] diff --git a/examples/platform/linux/LinuxCommissionableDataProvider.cpp b/examples/platform/linux/LinuxCommissionableDataProvider.cpp new file mode 100644 index 00000000000000..7733d99c3ca860 --- /dev/null +++ b/examples/platform/linux/LinuxCommissionableDataProvider.cpp @@ -0,0 +1,227 @@ +/* + * + * Copyright (c) 2022 Project CHIP Authors + * All rights reserved. + * + * 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 "LinuxCommissionableDataProvider.h" + +#include + +#include +#include +#include +#include + +using namespace chip::Crypto; + +namespace { + +CHIP_ERROR GeneratePaseSalt(std::vector & spake2pSaltVector) +{ + constexpr size_t kSaltLen = kSpake2p_Max_PBKDF_Salt_Length; + spake2pSaltVector.resize(kSaltLen); + return DRBG_get_bytes(spake2pSaltVector.data(), spake2pSaltVector.size()); +} + +} // namespace + +CHIP_ERROR LinuxCommissionableDataProvider::Init(chip::Optional> serializedSpake2pVerifier, + chip::Optional> spake2pSalt, uint32_t spake2pIterationCount, + chip::Optional setupPasscode, uint16_t discriminator) +{ + VerifyOrReturnError(mIsInitialized == false, CHIP_ERROR_INCORRECT_STATE); + + if (discriminator > chip::kMaxDiscriminatorValue) + { + ChipLogError(Support, "Discriminator value invalid: %u", static_cast(discriminator)); + return CHIP_ERROR_INVALID_ARGUMENT; + } + + if ((spake2pIterationCount < kSpake2p_Min_PBKDF_Iterations) || (spake2pIterationCount > kSpake2p_Max_PBKDF_Iterations)) + { + ChipLogError(Support, "PASE Iteration count invalid: %u", static_cast(spake2pIterationCount)); + return CHIP_ERROR_INVALID_ARGUMENT; + } + + bool havePaseVerifier = serializedSpake2pVerifier.HasValue(); + Spake2pVerifier providedVerifier; + CHIP_ERROR err; + std::vector finalSerializedVerifier(kSpake2p_VerifierSerialized_Length); + if (havePaseVerifier) + { + if (serializedSpake2pVerifier.Value().size() != kSpake2p_VerifierSerialized_Length) + { + ChipLogError(Support, "PASE verifier size invalid: %u", + static_cast(serializedSpake2pVerifier.Value().size())); + return CHIP_ERROR_INVALID_ARGUMENT; + } + + chip::MutableByteSpan verifierSpan{ serializedSpake2pVerifier.Value().data(), serializedSpake2pVerifier.Value().size() }; + err = providedVerifier.Deserialize(verifierSpan); + if (err != CHIP_NO_ERROR) + { + ChipLogError(Support, "Failed to deserialized PASE verifier: %" CHIP_ERROR_FORMAT, err.Format()); + return err; + } + + ChipLogProgress(Support, "Got externally provided verifier, using it."); + } + + bool havePaseSalt = spake2pSalt.HasValue(); + if (havePaseVerifier && !havePaseSalt) + { + ChipLogError(Support, "LinuxCommissionableDataProvider didn't get a PASE salt, but got a verifier: ambiguous data"); + return CHIP_ERROR_INVALID_ARGUMENT; + } + + size_t spake2pSaltLength = havePaseSalt ? spake2pSalt.Value().size() : 0; + if (havePaseSalt && + ((spake2pSaltLength < kSpake2p_Min_PBKDF_Salt_Length) || (spake2pSaltLength > kSpake2p_Max_PBKDF_Salt_Length))) + { + ChipLogError(Support, "PASE salt length invalid: %u", static_cast(spake2pSaltLength)); + return CHIP_ERROR_INVALID_ARGUMENT; + } + else if (!havePaseSalt) + { + ChipLogProgress(Support, "LinuxCommissionableDataProvider didn't get a PASE salt, generating one."); + std::vector spake2pSaltVector; + err = GeneratePaseSalt(spake2pSaltVector); + if (err != CHIP_NO_ERROR) + { + ChipLogError(Support, "Failed to generate PASE salt: %" CHIP_ERROR_FORMAT, err.Format()); + return err; + } + spake2pSalt.SetValue(std::move(spake2pSaltVector)); + } + + bool havePasscode = setupPasscode.HasValue(); + Spake2pVerifier passcodeVerifier; + std::vector serializedPasscodeVerifier(kSpake2p_VerifierSerialized_Length); + chip::MutableByteSpan saltSpan{ spake2pSalt.Value().data(), spake2pSalt.Value().size() }; + if (havePasscode) + { + err = passcodeVerifier.Generate(spake2pIterationCount, saltSpan, setupPasscode.Value()); + if (err != CHIP_NO_ERROR) + { + ChipLogError(Support, "Failed to generate PASE verifier from passcode: %" CHIP_ERROR_FORMAT, err.Format()); + return err; + } + + chip::MutableByteSpan verifierSpan{ serializedPasscodeVerifier.data(), serializedPasscodeVerifier.size() }; + err = passcodeVerifier.Serialize(verifierSpan); + if (err != CHIP_NO_ERROR) + { + ChipLogError(Support, "Failed to serialize PASE verifier from passcode: %" CHIP_ERROR_FORMAT, err.Format()); + return err; + } + } + + // Make sure we actually have a verifier + if (!havePasscode && !havePaseVerifier) + { + ChipLogError(Support, "Missing both externally provided verifier and passcode: cannot produce final verifier"); + return CHIP_ERROR_INVALID_ARGUMENT; + } + + // If both passcode and external verifier were provided, validate they match, otherwise + // it's ambiguous. + if (havePasscode && havePaseVerifier) + { + if (serializedPasscodeVerifier != serializedSpake2pVerifier.Value()) + { + ChipLogError(Support, "Mismatching verifier between passcode and external verifier. Validate inputs."); + return CHIP_ERROR_INVALID_ARGUMENT; + } + ChipLogProgress(Support, "Validated externally provided passcode matches the one generated from provided passcode."); + } + + // External PASE verifier takes precedence when present (even though it is identical to passcode-based + // one when the latter is present). + if (havePaseVerifier) + { + finalSerializedVerifier = serializedSpake2pVerifier.Value(); + } + else + { + finalSerializedVerifier = serializedPasscodeVerifier; + } + + mDiscriminator = discriminator; + mSerializedPaseVerifier = std::move(finalSerializedVerifier); + mPaseSalt = std::move(spake2pSalt.Value()); + mPaseIterationCount = spake2pIterationCount; + if (havePasscode) + { + mSetupPasscode.SetValue(setupPasscode.Value()); + } + mIsInitialized = true; + + return CHIP_NO_ERROR; +} + +CHIP_ERROR LinuxCommissionableDataProvider::GetSetupDiscriminator(uint16_t & setupDiscriminator) +{ + VerifyOrReturnError(mIsInitialized == true, CHIP_ERROR_INCORRECT_STATE); + setupDiscriminator = mDiscriminator; + return CHIP_NO_ERROR; +} + +CHIP_ERROR LinuxCommissionableDataProvider::GetSpake2pIterationCount(uint32_t & iterationCount) +{ + VerifyOrReturnError(mIsInitialized == true, CHIP_ERROR_INCORRECT_STATE); + iterationCount = mPaseIterationCount; + return CHIP_NO_ERROR; +} + +CHIP_ERROR LinuxCommissionableDataProvider::GetSpake2pSalt(chip::MutableByteSpan & saltBuf) +{ + VerifyOrReturnError(mIsInitialized == true, CHIP_ERROR_INCORRECT_STATE); + + VerifyOrReturnError(saltBuf.size() >= kSpake2p_Max_PBKDF_Salt_Length, CHIP_ERROR_BUFFER_TOO_SMALL); + memcpy(saltBuf.data(), mPaseSalt.data(), mPaseSalt.size()); + saltBuf.reduce_size(mPaseSalt.size()); + + return CHIP_NO_ERROR; +} + +CHIP_ERROR LinuxCommissionableDataProvider::GetSpake2pVerifier(chip::MutableByteSpan & verifierBuf, size_t & outVerifierLen) +{ + VerifyOrReturnError(mIsInitialized == true, CHIP_ERROR_INCORRECT_STATE); + + // By now, serialized verifier from Init should be correct size + VerifyOrReturnError(mSerializedPaseVerifier.size() == kSpake2p_VerifierSerialized_Length, CHIP_ERROR_INTERNAL); + + outVerifierLen = mSerializedPaseVerifier.size(); + VerifyOrReturnError(verifierBuf.size() >= outVerifierLen, CHIP_ERROR_BUFFER_TOO_SMALL); + memcpy(verifierBuf.data(), mSerializedPaseVerifier.data(), mSerializedPaseVerifier.size()); + verifierBuf.reduce_size(mSerializedPaseVerifier.size()); + + return CHIP_NO_ERROR; +} + +CHIP_ERROR LinuxCommissionableDataProvider::GetSetupPasscode(uint32_t & setupPasscode) +{ + VerifyOrReturnError(mIsInitialized == true, CHIP_ERROR_INCORRECT_STATE); + + // Pretend not implemented if we don't have a passcode value externally set + if (!mSetupPasscode.HasValue()) + { + return CHIP_ERROR_NOT_IMPLEMENTED; + } + + setupPasscode = mSetupPasscode.Value(); + return CHIP_NO_ERROR; +} diff --git a/examples/platform/linux/LinuxCommissionableDataProvider.h b/examples/platform/linux/LinuxCommissionableDataProvider.h new file mode 100644 index 00000000000000..2254177c754734 --- /dev/null +++ b/examples/platform/linux/LinuxCommissionableDataProvider.h @@ -0,0 +1,86 @@ +/* + * + * Copyright (c) 2022 Project CHIP Authors + * All rights reserved. + * + * 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. + */ + +#pragma once + +#include +#include + +#include +#include +#include + +class LinuxCommissionableDataProvider : public chip::DeviceLayer::CommissionableDataProvider +{ +public: + LinuxCommissionableDataProvider() {} + + /** + * @brief Initialize the commissionable Data provider for Linux samples + * + * This version attempts to properly make use of the different arguments + * to allow direct override of PASE verifier, and correct computation of + * the PAKE verifier based on configurable iteration counts. + * + * The setupPasscode is not required BUT if it is absent, it will read + * back as 0 and log a warning. This means testing assumptions of being able + * to generate a setup payload will be wrong, but it will allow testing + * configurations where the passcode is maintained separately than the + * verifier for security purposes. + * + * @param serializedSpake2pVerifier - Optional serialized verifier that will + * override computation from setupPasscode if provided + * @param spake2pSalt - Optional salt to use. A random one will be generated + * otherwise. + * @param spake2pIterationCount - Iteration count to use. If not in range of the + * spec bounds, CHIP_ERROR_INVALID_ARGUMENT will be returned. + * @param setupPasscode - Optional setup passcode to store, and to use to generate + * PASE verifier if `serializedSpake2pVerifier` argument empty. + * @param discriminator - Discriminator to use for advertising. + * @return CHIP_ERROR_OK on success, CHIP_ERROR_INVALID_ARGUMENT on any invalid argument combinations, + * CHIP_ERROR_INVALID_STATE if already initialized, or other CHIP_ERROR values if inner + * implementation dependencies fail. + */ + CHIP_ERROR Init(chip::Optional> serializedSpake2pVerifier, + chip::Optional> spake2pSalt, uint32_t spake2pIterationCount, + chip::Optional setupPasscode, uint16_t discriminator); + + CHIP_ERROR GetSetupDiscriminator(uint16_t & setupDiscriminator) override; + CHIP_ERROR SetSetupDiscriminator(uint16_t setupDiscriminator) override + { + // We don't support overriding the discriminator post-init (it is deprecated!) + return CHIP_ERROR_NOT_IMPLEMENTED; + } + CHIP_ERROR GetSpake2pIterationCount(uint32_t & iterationCount) override; + CHIP_ERROR GetSpake2pSalt(chip::MutableByteSpan & saltBuf) override; + CHIP_ERROR GetSpake2pVerifier(chip::MutableByteSpan & verifierBuf, size_t & outVerifierLen) override; + CHIP_ERROR GetSetupPasscode(uint32_t & setupPasscode) override; + CHIP_ERROR SetSetupPasscode(uint32_t setupPasscode) override + { + // We don't support overriding the passcode post-init (it is deprecated!) + return CHIP_ERROR_NOT_IMPLEMENTED; + } + +private: + bool mIsInitialized = false; + std::vector mSerializedPaseVerifier; + std::vector mPaseSalt; + uint32_t mPaseIterationCount = 0; + chip::Optional mSetupPasscode; + uint16_t mDiscriminator = 0; +}; diff --git a/examples/platform/linux/Options.cpp b/examples/platform/linux/Options.cpp index a7451d93872dad..47322b73da2d4b 100644 --- a/examples/platform/linux/Options.cpp +++ b/examples/platform/linux/Options.cpp @@ -16,12 +16,17 @@ * limitations under the License. */ +#include +#include +#include + #include "Options.h" #include -#include +#include #include +#include using namespace chip; using namespace chip::ArgParser; @@ -48,7 +53,10 @@ enum kDeviceOption_Command = 0x100d, kDeviceOption_PICS = 0x100e, kDeviceOption_KVS = 0x100f, - kDeviceOption_InterfaceId = 0x1010 + kDeviceOption_InterfaceId = 0x1010, + kDeviceOption_Spake2pVerifierBase64 = 0x1011, + kDeviceOption_Spake2pSaltBase64 = 0x1012, + kDeviceOption_Spake2pIterations = 0x1013, }; constexpr unsigned kAppUsageLength = 64; @@ -70,6 +78,9 @@ OptionDef sDeviceOptionDefs[] = { { "capabilities", kArgumentRequired, kDeviceOption_Capabilities }, { "discriminator", kArgumentRequired, kDeviceOption_Discriminator }, { "passcode", kArgumentRequired, kDeviceOption_Passcode }, + { "spake2p-verifier-base64", kArgumentRequired, kDeviceOption_Spake2pVerifierBase64 }, + { "spake2p-salt-base64", kArgumentRequired, kDeviceOption_Spake2pSaltBase64 }, + { "spake2p-iterations", kArgumentRequired, kDeviceOption_Spake2pIterations }, { "secured-device-port", kArgumentRequired, kDeviceOption_SecuredDevicePort }, { "secured-commissioner-port", kArgumentRequired, kDeviceOption_SecuredCommissionerPort }, { "unsecured-commissioner-port", kArgumentRequired, kDeviceOption_UnsecuredCommissionerPort }, @@ -115,7 +126,22 @@ const char * sDeviceOptionHelp = " A 12-bit unsigned integer match the value which a device advertises during commissioning.\n" "\n" " --passcode \n" - " A 27-bit unsigned integer, which serves as proof of possession during commissioning.\n" + " A 27-bit unsigned integer, which serves as proof of possession during commissioning. \n" + " If not provided to compute a verifier, the --spake2p-verifier-base64 must be provided. \n" + "\n" + " --spake2p-verifier-base64 \n" + " A raw concatenation of 'W0' and 'L' (67 bytes) as base64 to override the verifier\n" + " auto-computed from the passcode, if provided.\n" + "\n" + " --spake2p-salt-base64 \n" + " 16-32 bytes of salt to use for the PASE verifier, as base64. If omitted, will be generated\n" + " randomly. If a --spake2p-verifier-base64 is passed, it must match against the salt otherwise\n" + " failure will arise.\n" + "\n" + " --spake2p-iterations \n" + " Number of PBKDF iterations to use. If omitted, will be 1000. If a --spake2p-verifier-base64 is\n" + " passed, the iteration counts must match that used to generate the verifier otherwise failure will\n" + " arise.\n" "\n" " --secured-device-port \n" " A 16-bit unsigned integer specifying the listen port to use for secure device messages (default is 5540).\n" @@ -140,6 +166,27 @@ const char * sDeviceOptionHelp = " A interface id to advertise on.\n" "\n"; +bool Base64ArgToVector(const char * arg, size_t maxSize, std::vector & outVector) +{ + size_t maxBase64Size = BASE64_ENCODED_LEN(maxSize); + outVector.resize(maxSize); + + size_t argLen = strlen(arg); + if (argLen > maxBase64Size) + { + return false; + } + + size_t decodedLen = chip::Base64Decode32(arg, argLen, reinterpret_cast(outVector.data())); + if (decodedLen == 0) + { + return false; + } + + outVector.resize(decodedLen); + return true; +} + bool HandleOption(const char * aProgram, OptionSet * aOptions, int aIdentifier, const char * aName, const char * aValue) { bool retval = true; @@ -201,6 +248,79 @@ bool HandleOption(const char * aProgram, OptionSet * aOptions, int aIdentifier, LinuxDeviceOptions::GetInstance().payload.setUpPINCode = static_cast(atoi(aValue)); break; + case kDeviceOption_Spake2pSaltBase64: { + constexpr size_t kMaxSize = chip::Crypto::kSpake2p_Max_PBKDF_Salt_Length; + std::vector saltVector; + + bool success = Base64ArgToVector(aValue, kMaxSize, saltVector); + + if (!success) + { + PrintArgError("%s: ERROR: Base64 format for argument %s was invalid\n", aProgram, aName); + retval = false; + break; + } + + if ((saltVector.size() < chip::Crypto::kSpake2p_Min_PBKDF_Salt_Length) || + (saltVector.size() > chip::Crypto::kSpake2p_Max_PBKDF_Salt_Length)) + { + PrintArgError("%s: ERROR: argument %s not in range [%zu, %zu]\n", aProgram, aName, + chip::Crypto::kSpake2p_Min_PBKDF_Salt_Length, chip::Crypto::kSpake2p_Max_PBKDF_Salt_Length); + retval = false; + break; + } + + LinuxDeviceOptions::GetInstance().spake2pSalt.SetValue(std::move(saltVector)); + break; + } + + case kDeviceOption_Spake2pVerifierBase64: { + constexpr size_t kMaxSize = chip::Crypto::kSpake2p_VerifierSerialized_Length; + std::vector serializedVerifier; + + bool success = Base64ArgToVector(aValue, kMaxSize, serializedVerifier); + + if (!success) + { + PrintArgError("%s: ERROR: Base64 format for argument %s was invalid\n", aProgram, aName); + retval = false; + break; + } + + if (serializedVerifier.size() != chip::Crypto::kSpake2p_VerifierSerialized_Length) + { + PrintArgError("%s: ERROR: argument %s should contain base64 for a %zu bytes octet string \n", aProgram, aName, + chip::Crypto::kSpake2p_VerifierSerialized_Length); + retval = false; + break; + } + + LinuxDeviceOptions::GetInstance().spake2pVerifier.SetValue(std::move(serializedVerifier)); + break; + } + + case kDeviceOption_Spake2pIterations: { + errno = 0; + uint32_t iterCount = static_cast(strtoul(aValue, nullptr, 0)); + if (errno == ERANGE) + { + PrintArgError("%s: ERROR: argument %s was not parsable as an integer\n", aProgram, aName); + retval = false; + break; + } + else if ((iterCount < chip::Crypto::kSpake2p_Min_PBKDF_Iterations) || + (iterCount > chip::Crypto::kSpake2p_Max_PBKDF_Iterations)) + { + PrintArgError("%s: ERROR: argument %s not in range [%zu, %zu]\n", aProgram, aName, + chip::Crypto::kSpake2p_Min_PBKDF_Iterations, chip::Crypto::kSpake2p_Max_PBKDF_Iterations); + retval = false; + break; + } + + LinuxDeviceOptions::GetInstance().spake2pIterations = iterCount; + break; + } + case kDeviceOption_SecuredDevicePort: LinuxDeviceOptions::GetInstance().securedDevicePort = static_cast(atoi(aValue)); break; diff --git a/examples/platform/linux/Options.h b/examples/platform/linux/Options.h index 5c9bf85c3159d9..1506fa53e61b81 100644 --- a/examples/platform/linux/Options.h +++ b/examples/platform/linux/Options.h @@ -25,15 +25,20 @@ #pragma once #include +#include #include #include +#include #include #include struct LinuxDeviceOptions { chip::SetupPayload payload; + chip::Optional> spake2pVerifier; + chip::Optional> spake2pSalt; + uint32_t spake2pIterations = 0; // When not provided (0), will default elsewhere uint32_t mBleDevice = 0; bool mWiFi = false; bool mThread = false; diff --git a/src/app/clusters/administrator-commissioning-server/administrator-commissioning-server.cpp b/src/app/clusters/administrator-commissioning-server/administrator-commissioning-server.cpp index 5302609f0fa064..8979bed03310e3 100644 --- a/src/app/clusters/administrator-commissioning-server/administrator-commissioning-server.cpp +++ b/src/app/clusters/administrator-commissioning-server/administrator-commissioning-server.cpp @@ -29,6 +29,7 @@ #include #include #include +#include #include using namespace chip; diff --git a/src/app/server/CommissioningWindowManager.cpp b/src/app/server/CommissioningWindowManager.cpp index fa421f532138b0..2ed88672c5e79f 100644 --- a/src/app/server/CommissioningWindowManager.cpp +++ b/src/app/server/CommissioningWindowManager.cpp @@ -21,6 +21,7 @@ #include #include #include +#include using namespace chip::app::Clusters; @@ -189,21 +190,23 @@ CHIP_ERROR CommissioningWindowManager::OpenCommissioningWindow() { uint32_t iterationCount = 0; uint8_t salt[kSpake2p_Max_PBKDF_Salt_Length] = { 0 }; - size_t saltLen = 0; Spake2pVerifierSerialized serializedVerifier = { 0 }; size_t serializedVerifierLen = 0; Spake2pVerifier verifier; + MutableByteSpan saltSpan{ salt }; + MutableByteSpan verifierSpan{ serializedVerifier }; + + auto * commissionableDataProvider = DeviceLayer::GetCommissionableDataProvider(); + ReturnErrorOnFailure(commissionableDataProvider->GetSpake2pIterationCount(iterationCount)); + ReturnErrorOnFailure(commissionableDataProvider->GetSpake2pSalt(saltSpan)); + ReturnErrorOnFailure(commissionableDataProvider->GetSpake2pVerifier(verifierSpan, serializedVerifierLen)); + VerifyOrReturnError(Crypto::kSpake2p_VerifierSerialized_Length == serializedVerifierLen, CHIP_ERROR_INVALID_ARGUMENT); + VerifyOrReturnError(verifierSpan.size() == serializedVerifierLen, CHIP_ERROR_INTERNAL); - ReturnErrorOnFailure(DeviceLayer::ConfigurationMgr().GetSpake2pIterationCount(iterationCount)); - ReturnErrorOnFailure(DeviceLayer::ConfigurationMgr().GetSpake2pSalt(salt, sizeof(salt), saltLen)); - ReturnErrorOnFailure(DeviceLayer::ConfigurationMgr().GetSpake2pVerifier( - serializedVerifier, kSpake2p_VerifierSerialized_Length, serializedVerifierLen)); - VerifyOrReturnError(kSpake2p_VerifierSerialized_Length == serializedVerifierLen, CHIP_ERROR_INVALID_ARGUMENT); ReturnErrorOnFailure(verifier.Deserialize(ByteSpan(serializedVerifier))); - ReturnErrorOnFailure(mPairingSession.WaitForPairing(verifier, iterationCount, ByteSpan(salt, saltLen), keyID, - Optional::Value(GetLocalMRPConfig()), - this)); + ReturnErrorOnFailure(mPairingSession.WaitForPairing( + verifier, iterationCount, saltSpan, keyID, Optional::Value(GetLocalMRPConfig()), this)); } ReturnErrorOnFailure(StartAdvertisement()); @@ -377,26 +380,12 @@ CHIP_ERROR CommissioningWindowManager::StopAdvertisement(bool aShuttingDown) CHIP_ERROR CommissioningWindowManager::SetTemporaryDiscriminator(uint16_t discriminator) { - if (!mOriginalDiscriminatorCached) - { - // Cache the original discriminator - ReturnErrorOnFailure(DeviceLayer::ConfigurationMgr().GetSetupDiscriminator(mOriginalDiscriminator)); - mOriginalDiscriminatorCached = true; - } - - return DeviceLayer::ConfigurationMgr().StoreSetupDiscriminator(discriminator); + return app::DnssdServer::Instance().SetEphemeralDiscriminator(MakeOptional(discriminator)); } CHIP_ERROR CommissioningWindowManager::RestoreDiscriminator() { - if (mOriginalDiscriminatorCached) - { - // Restore the original discriminator - ReturnErrorOnFailure(DeviceLayer::ConfigurationMgr().StoreSetupDiscriminator(mOriginalDiscriminator)); - mOriginalDiscriminatorCached = false; - } - - return CHIP_NO_ERROR; + return app::DnssdServer::Instance().SetEphemeralDiscriminator(NullOptional); } } // namespace chip diff --git a/src/app/server/CommissioningWindowManager.h b/src/app/server/CommissioningWindowManager.h index 86b360c38fd276..38e76562bb0bad 100644 --- a/src/app/server/CommissioningWindowManager.h +++ b/src/app/server/CommissioningWindowManager.h @@ -109,9 +109,6 @@ class CommissioningWindowManager : public SessionEstablishmentDelegate, public a bool mIsBLE = true; - bool mOriginalDiscriminatorCached = false; - uint16_t mOriginalDiscriminator = 0; - SessionIDAllocator * mIDAllocator = nullptr; PASESession mPairingSession; diff --git a/src/app/server/Dnssd.cpp b/src/app/server/Dnssd.cpp index 0b3b9fcaab01f7..f6df0e0fe444af 100644 --- a/src/app/server/Dnssd.cpp +++ b/src/app/server/Dnssd.cpp @@ -26,6 +26,7 @@ #include #include #include +#include #include #include #include @@ -33,6 +34,7 @@ #include #endif #include +#include #include #include @@ -249,6 +251,14 @@ CHIP_ERROR DnssdServer::GetCommissionableInstanceName(char * buffer, size_t buff return mdnsAdvertiser.GetCommissionableInstanceName(buffer, bufferLen); } +CHIP_ERROR DnssdServer::SetEphemeralDiscriminator(Optional discriminator) +{ + VerifyOrReturnError(discriminator.ValueOr(0) <= kMaxDiscriminatorValue, CHIP_ERROR_INVALID_ARGUMENT); + mEphemeralDiscriminator = discriminator; + + return CHIP_NO_ERROR; +} + /// Set MDNS operational advertisement CHIP_ERROR DnssdServer::AdvertiseOperational() { @@ -329,12 +339,21 @@ CHIP_ERROR DnssdServer::Advertise(bool commissionableNode, chip::Dnssd::Commissi advertiseParameters.SetProductId(chip::Optional::Value(value)); } - if (DeviceLayer::ConfigurationMgr().GetSetupDiscriminator(value) != CHIP_NO_ERROR) + uint16_t discriminator = 0; + CHIP_ERROR error = DeviceLayer::GetCommissionableDataProvider()->GetSetupDiscriminator(discriminator); + if (error != CHIP_NO_ERROR) { - ChipLogError(Discovery, "Setup discriminator not known. Using a default."); - value = 840; + ChipLogError(Discovery, + "Setup discriminator read error (%" CHIP_ERROR_FORMAT ")! Critical error, will not be commissionable.", + error.Format()); + return error; } - advertiseParameters.SetShortDiscriminator(static_cast((value >> 8) & 0x0F)).SetLongDiscriminator(value); + + // Override discriminator with temporary one if one is set + discriminator = mEphemeralDiscriminator.ValueOr(discriminator); + + advertiseParameters.SetShortDiscriminator(static_cast((discriminator >> 8) & 0x0F)) + .SetLongDiscriminator(discriminator); if (DeviceLayer::ConfigurationMgr().IsCommissionableDeviceTypeEnabled() && DeviceLayer::ConfigurationMgr().GetDeviceTypeId(value) == CHIP_NO_ERROR) diff --git a/src/app/server/Dnssd.h b/src/app/server/Dnssd.h index e27d44f8703242..c396fa5964b72d 100644 --- a/src/app/server/Dnssd.h +++ b/src/app/server/Dnssd.h @@ -112,6 +112,17 @@ class DLL_EXPORT DnssdServer /// Generates the (random) instance name that a CHIP device is to use for pre-commissioning DNS-SD CHIP_ERROR GetCommissionableInstanceName(char * buffer, size_t bufferLen); + /** + * @brief Overrides configuration so that commissionable advertisement will use an + * ephemeral discriminator such as one set for ECM. If the Optional has no + * value, the default basic discriminator is used as usual. + * + * @param[in] discriminator Ephemeral discriminator to override if it HasValue(), otherwise reverts + * to default. + * @return CHIP_NO_ERROR on success or CHIP_ERROR_INVALID_ARGUMENT on invalid value + */ + CHIP_ERROR SetEphemeralDiscriminator(Optional discriminator); + private: /// Overloaded utility method for commissioner and commissionable advertisement /// This method is used for both commissioner discovery and commissionable node discovery since @@ -149,6 +160,9 @@ class DLL_EXPORT DnssdServer uint16_t mUnsecuredPort = CHIP_UDC_PORT; Inet::InterfaceId mInterfaceId = Inet::InterfaceId::Null(); + // Ephemeral discriminator to use instead of the default if set + Optional mEphemeralDiscriminator; + /// schedule next discovery expiration CHIP_ERROR ScheduleDiscoveryExpiration(); int16_t mDiscoveryTimeoutSecs = CHIP_DEVICE_CONFIG_DISCOVERY_TIMEOUT_SECS; diff --git a/src/app/server/OnboardingCodesUtil.cpp b/src/app/server/OnboardingCodesUtil.cpp index f9e42d61c1e374..41bd12d15d23e2 100644 --- a/src/app/server/OnboardingCodesUtil.cpp +++ b/src/app/server/OnboardingCodesUtil.cpp @@ -25,6 +25,7 @@ #include #include #include +#include #include #include @@ -97,17 +98,25 @@ CHIP_ERROR GetSetupPayload(chip::SetupPayload & aSetupPayload, chip::RendezvousI aSetupPayload.version = 0; aSetupPayload.rendezvousInformation = aRendezvousFlags; - err = ConfigurationMgr().GetSetupPinCode(aSetupPayload.setUpPINCode); + err = GetCommissionableDataProvider()->GetSetupPasscode(aSetupPayload.setUpPINCode); if (err != CHIP_NO_ERROR) { - ChipLogProgress(AppServer, "ConfigurationMgr().GetSetupPinCode() failed: %s", chip::ErrorStr(err)); + ChipLogError(AppServer, "GetCommissionableDataProvider()->GetSetupPasscode() failed: %s", + chip::ErrorStr(err)); +#if defined(CHIP_DEVICE_CONFIG_USE_TEST_SETUP_PIN_CODE) && CHIP_DEVICE_CONFIG_USE_TEST_SETUP_PIN_CODE + ChipLogProgress(AppServer, "*** Using default EXAMPLE passcode %u ***", + static_cast(CHIP_DEVICE_CONFIG_USE_TEST_SETUP_PIN_CODE)); + aSetupPayload.setUpPINCode = CHIP_DEVICE_CONFIG_USE_TEST_SETUP_PIN_CODE; +#else return err; +#endif } - err = ConfigurationMgr().GetSetupDiscriminator(aSetupPayload.discriminator); + err = GetCommissionableDataProvider()->GetSetupDiscriminator(aSetupPayload.discriminator); if (err != CHIP_NO_ERROR) { - ChipLogProgress(AppServer, "ConfigurationMgr().GetSetupDiscriminator() failed: %s", chip::ErrorStr(err)); + ChipLogProgress(AppServer, "GetCommissionableDataProvider()->GetSetupDiscriminator() failed: %s", + chip::ErrorStr(err)); return err; } diff --git a/src/app/tests/TestCommissionManager.cpp b/src/app/tests/TestCommissionManager.cpp index e823d7f8eebe76..efcb270eaedddf 100644 --- a/src/app/tests/TestCommissionManager.cpp +++ b/src/app/tests/TestCommissionManager.cpp @@ -22,8 +22,10 @@ #include #include #include +#include #include #include +#include #include #include @@ -47,8 +49,13 @@ void InitializeChip(nlTestSuite * suite) NL_TEST_ASSERT(suite, err == CHIP_NO_ERROR); err = chip::DeviceLayer::PlatformMgr().InitChipStack(); NL_TEST_ASSERT(suite, err == CHIP_NO_ERROR); + + static chip::DeviceLayer::TestOnlyCommissionableDataProvider commissionableDataProvider; + chip::DeviceLayer::SetCommissionableDataProvider(&commissionableDataProvider); + err = Server::GetInstance().Init(); NL_TEST_ASSERT(suite, err == CHIP_NO_ERROR); + Server::GetInstance().GetCommissioningWindowManager().CloseCommissioningWindow(); chip::DeviceLayer::PlatformMgr().StartEventLoopTask(); } @@ -136,14 +143,14 @@ void CheckCommissioningWindowManagerEnhancedWindowTask(intptr_t context) nlTestSuite * suite = reinterpret_cast(context); CommissioningWindowManager & commissionMgr = Server::GetInstance().GetCommissioningWindowManager(); uint16_t originDiscriminator; - CHIP_ERROR err = chip::DeviceLayer::ConfigurationMgr().GetSetupDiscriminator(originDiscriminator); + CHIP_ERROR err = + chip::DeviceLayer::GetCommissionableDataProvider()->GetSetupDiscriminator(originDiscriminator); NL_TEST_ASSERT(suite, err == CHIP_NO_ERROR); uint16_t newDiscriminator = static_cast(originDiscriminator + 1); chip::Spake2pVerifier verifier; constexpr uint32_t kIterations = chip::kSpake2p_Min_PBKDF_Iterations; uint8_t salt[chip::kSpake2p_Min_PBKDF_Salt_Length]; chip::ByteSpan saltData(salt); - uint16_t currentDiscriminator; err = commissionMgr.OpenEnhancedCommissioningWindow(kNoCommissioningTimeout, newDiscriminator, verifier, kIterations, saltData); NL_TEST_ASSERT(suite, err == CHIP_NO_ERROR); @@ -151,17 +158,11 @@ void CheckCommissioningWindowManagerEnhancedWindowTask(intptr_t context) commissionMgr.CommissioningWindowStatus() == chip::app::Clusters::AdministratorCommissioning::CommissioningWindowStatus::kEnhancedWindowOpen); NL_TEST_ASSERT(suite, !chip::DeviceLayer::ConnectivityMgr().IsBLEAdvertisingEnabled()); - err = chip::DeviceLayer::ConfigurationMgr().GetSetupDiscriminator(currentDiscriminator); - NL_TEST_ASSERT(suite, err == CHIP_NO_ERROR); - NL_TEST_ASSERT(suite, currentDiscriminator == newDiscriminator); commissionMgr.CloseCommissioningWindow(); NL_TEST_ASSERT(suite, commissionMgr.CommissioningWindowStatus() == chip::app::Clusters::AdministratorCommissioning::CommissioningWindowStatus::kWindowNotOpen); - err = chip::DeviceLayer::ConfigurationMgr().GetSetupDiscriminator(currentDiscriminator); - NL_TEST_ASSERT(suite, err == CHIP_NO_ERROR); - NL_TEST_ASSERT(suite, currentDiscriminator == originDiscriminator); } void CheckCommissioningWindowManagerEnhancedWindow(nlTestSuite * suite, void *) diff --git a/src/controller/python/chip/native/StackInit.cpp b/src/controller/python/chip/native/StackInit.cpp index 3d071d1b4d8f22..4b140899b43cb2 100644 --- a/src/controller/python/chip/native/StackInit.cpp +++ b/src/controller/python/chip/native/StackInit.cpp @@ -21,7 +21,9 @@ #include #include #include +#include #include +#include namespace { @@ -80,6 +82,13 @@ void pychip_native_init() { ChipLogError(DeviceLayer, "Failed to initialize CHIP stack: platform init failed: %s", chip::ErrorStr(err)); } + + // Hack needed due to the fact that DnsSd server uses the CommissionableDataProvider even + // when never starting operational advertising. This will not be used but prevents + // null pointer dereferences. + static chip::DeviceLayer::TestOnlyCommissionableDataProvider TestOnlyCommissionableDataProvider; + chip::DeviceLayer::SetCommissionableDataProvider(&TestOnlyCommissionableDataProvider); + int result = pthread_create(&sPlatformMainThread, nullptr, PlatformMainLoop, nullptr); #if CHIP_ERROR_LOGGING int tmpErrno = errno; diff --git a/src/credentials/DeviceAttestationCredsProvider.h b/src/credentials/DeviceAttestationCredsProvider.h index b9351161372e6b..4f17c6259e7302 100644 --- a/src/credentials/DeviceAttestationCredsProvider.h +++ b/src/credentials/DeviceAttestationCredsProvider.h @@ -37,7 +37,7 @@ class DeviceAttestationCredentialsProvider * to match the data size. If no Certification Declaration is available, sets * `out_cd_buffer` to empty. * - * @param[inout] out_cd_buffer Buffer to receive the Certification Declaration body. + * @param[in,out] out_cd_buffer Buffer to receive the Certification Declaration body. * @returns CHIP_NO_ERROR on success, CHIP_ERROR_BUFFER_TOO_SMALL if `out_cd_buffer` * is too small, or another CHIP_ERROR from the underlying implementation * if access fails. @@ -49,7 +49,7 @@ class DeviceAttestationCredentialsProvider * on success to match the data size. If no Firmware Information is available, * sets `out_firmware_info_buffer` to empty. * - * @param[inout] out_firmware_info_buffer Buffer to receive the Firmware Information body. + * @param[in,out] out_firmware_info_buffer Buffer to receive the Firmware Information body. * @returns CHIP_NO_ERROR on success, CHIP_ERROR_BUFFER_TOO_SMALL if `out_firmware_info_buffer` * is too small, or another CHIP_ERROR from the underlying implementation if access fails. */ @@ -60,7 +60,7 @@ class DeviceAttestationCredentialsProvider * size on success to match the data size. If no Device Attestation Certificate * is available, sets `out_dac_buffer` to empty. * - * @param[inout] out_dac_buffer Buffer to receive the Device Attestation Certificate. + * @param[in,out] out_dac_buffer Buffer to receive the Device Attestation Certificate. * @returns CHIP_NO_ERROR on success, CHIP_ERROR_BUFFER_TOO_SMALL if `out_dac_buffer` * is too small, or another CHIP_ERROR from the underlying implementation if * access fails. @@ -72,7 +72,7 @@ class DeviceAttestationCredentialsProvider * size on success to match the data size. If no PAI certificate * is available, sets `out_pai_buffer` to empty. * - * @param[inout] out_pai_buffer Buffer to receive the PAI certificate. + * @param[in,out] out_pai_buffer Buffer to receive the PAI certificate. * @returns CHIP_NO_ERROR on success, CHIP_ERROR_BUFFER_TOO_SMALL if `out_pai_buffer` * is too small, or another CHIP_ERROR from the underlying implementation if * access fails. @@ -84,7 +84,7 @@ class DeviceAttestationCredentialsProvider * * @param[in] digest_to_sign The SHA256 digest to sign using the attestation private key. Must * be exactly chip::Crypto::kSHA256_Hash_Length. - * @param[inout] out_signature_buffer Buffer to receive the signature in raw format. + * @param[in,out] out_signature_buffer Buffer to receive the signature in raw format. * @returns CHIP_NO_ERROR on success, CHIP_ERROR_INVALID_ARGUMENT if `digest_to_sign` is wrong size, * CHIP_ERROR_BUFFER_TOO_SMALL if `out_signature_buffer` is too small, * or another CHIP_ERROR from the underlying implementation if signature fails. diff --git a/src/include/platform/CommissionableDataProvider.h b/src/include/platform/CommissionableDataProvider.h new file mode 100644 index 00000000000000..aea04bc833b2c8 --- /dev/null +++ b/src/include/platform/CommissionableDataProvider.h @@ -0,0 +1,165 @@ +/* + * + * Copyright (c) 2022 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. + */ +#pragma once + +#include +#include + +namespace chip { + +// The largest value of the 12-bit Payload discriminator +constexpr uint16_t kMaxDiscriminatorValue = 0xFFF; + +namespace DeviceLayer { + +class CommissionableDataProvider +{ +public: + CommissionableDataProvider() = default; + virtual ~CommissionableDataProvider() = default; + + // Not copyable + CommissionableDataProvider(const CommissionableDataProvider &) = delete; + CommissionableDataProvider & operator=(const CommissionableDataProvider &) = delete; + + /** + * @brief Obtain the default setup discriminator for the device used for commissionable advertising + * + * @param[in,out] setupDiscriminator Reference to location where discriminator will be copied + * @returns CHIP_NO_ERROR on success, or another CHIP_ERROR from the underlying implementation + * if access fails. + */ + virtual CHIP_ERROR GetSetupDiscriminator(uint16_t & setupDiscriminator) = 0; + + /** + * @brief Set the setup discriminator *if supported*. + * + * This API is optional to support, but present to support integration with some examples + * which use a common test PAKE verifier but want to disambiguate multiple instances at + * runtime. This is generally not applicable to production usecases of commissionable + * devices with nominal random discriminator. There are no guarantees that this API, + * in general, will persist the discriminator across restarts. + * + * If not supported, return CHIP_ERROR_NOT_IMPLEMENTED. + * + * @param[in] setupDiscriminator Setup discriminator to set. + * @returns CHIP_NO_ERROR on success, CHIP_ERROR_INVALID_ARGUMENT if discriminator is out of range, + * CHIP_ERROR_NOT_IMPLEMENTED if not implemented, or another CHIP_ERROR from the underlying + * implementation if storage fails. + */ + virtual CHIP_ERROR SetSetupDiscriminator(uint16_t setupDiscriminator) = 0; + + /** + * @brief Obtain the default PAKE verifier's PBKDF2 iteration count + * + * @param[in,out] iterationCount Reference to location where the iteration count will be stored + * @returns CHIP_NO_ERROR on success, or another CHIP_ERROR from the underlying implementation + * if access fails. + */ + virtual CHIP_ERROR GetSpake2pIterationCount(uint32_t & iterationCount) = 0; + + /** + * @brief Obtain the default PAKE verifier's PBKDF2 salt in the provided `saltBuf` + * + * The `saltBuf` must be large enough to contain the salt. It will be resized on success to + * reflect the actual size of the salt. + * + * @param[in,out] saltBuf Reference to buffer where the salt value will be copied. + * + * @returns CHIP_NO_ERROR on success, CHIP_ERROR_BUFFER_TOO_SMALL if saltBuf was too small, or another + * CHIP_ERROR from the underlying implementation if access fails. + */ + virtual CHIP_ERROR GetSpake2pSalt(MutableByteSpan & saltBuf) = 0; + + /** + * @brief Obtain the default PAKE verifier in the provided `verifierBuf` + * + * The `verifierBuf` must be large enough to contain the verifier. It will be resized on + * success to reflect the actual size of the verifier and match the value in verifierLen. + * + * @param[in,out] verifierBuf Reference to buffer where the verifier value will be copied. + * @param[out] outVerifierLen Reference to location where the length of the verifier will be stored, + * including if the buffer provided is too small. This value is valid + * if the return value is either CHIP_NO_ERROR or CHIP_ERROR_BUFFER_TOO_SMALL. + * + * @returns CHIP_NO_ERROR on success, CHIP_ERROR_BUFFER_TOO_SMALL if verifierBuf was too small, or another + * CHIP_ERROR from the underlying implementation if access fails. + */ + virtual CHIP_ERROR GetSpake2pVerifier(MutableByteSpan & verifierBuf, size_t & outVerifierLen) = 0; + + /** + * @brief Obtain the default setup passcode for the device *if supported* + * + * This API is optional to support, but present to support integration with some examples + * which allow runtime setting of a passcode to generate onboarding payloads and QR codes + * as well as PAKE verifier. This is generally not applicable to production usecases of + * commissionable devices with nominal random verifier/passcode and with usage of verifier + * rather than passcode (which safeguards the passcode from ever leaking). There are no + * guarantees that this API, in general, will persist the passcode across restarts. + * + * If not supported, return CHIP_ERROR_NOT_IMPLEMENTED. + * + * @param[in,out] setupPasscode Reference to location where passcode will be copied + * @returns CHIP_NO_ERROR on success, CHIP_ERROR_NOT_IMPLEMENTED if not implemented + * or not available, or another CHIP_ERROR from the underlying implementation + * if access fails. + */ + virtual CHIP_ERROR GetSetupPasscode(uint32_t & setupPasscode) = 0; + + /** + * @brief Set the setup discriminator *if supported*. + * + * This API is optional to support, but present to support integration with some examples + * which allow runtime setting of a passcode to generate onboarding payloads and QR codes + * as well as PAKE verifier. This is generally not applicable to production usecases of + * commissionable devices with nominal random verifier/passcode and with usage of verifier + * rather than passcode (which safeguards the passcode from ever leaking). There are no + * guarantees that this API, in general, will persist the passcode across restarts. + * + * If not supported, return CHIP_ERROR_NOT_IMPLEMENTED. + * + * @param[in] setupPasscode Setup passcode to set + * @returns CHIP_NO_ERROR on success, CHIP_ERROR_INVALID_ARGUMENT if discriminator is invalid + * according to spec (out of range or forbidden value), CHIP_ERROR_NOT_IMPLEMENTED + * if not implemented, or another CHIP_ERROR from the underlying implementation if + * storage fails. + */ + virtual CHIP_ERROR SetSetupPasscode(uint32_t setupPasscode) = 0; +}; + +/** + * Instance getter for the global CommissionableDataProvider. + * + * Callers have to externally synchronize usage of this function. + * + * @return The global device attestation credentials provider. Assume never null. + */ +CommissionableDataProvider * GetCommissionableDataProvider(); + +/** + * Instance setter for the global CommissionableDataProvider. + * + * Callers have to externally synchronize usage of this function. + * + * If the `provider` is nullptr, no change is done. + * + * @param[in] provider the CommissionableDataProvider to start returning with the getter + */ +void SetCommissionableDataProvider(CommissionableDataProvider * provider); + +} // namespace DeviceLayer +} // namespace chip diff --git a/src/include/platform/ConfigurationManager.h b/src/include/platform/ConfigurationManager.h index d78d04a1528d6f..c4f253e1dfccda 100644 --- a/src/include/platform/ConfigurationManager.h +++ b/src/include/platform/ConfigurationManager.h @@ -98,11 +98,6 @@ class ConfigurationManager virtual CHIP_ERROR GetManufacturingDate(uint16_t & year, uint8_t & month, uint8_t & dayOfMonth) = 0; virtual CHIP_ERROR GetSoftwareVersionString(char * buf, size_t bufSize) = 0; virtual CHIP_ERROR GetSoftwareVersion(uint32_t & softwareVer) = 0; - virtual CHIP_ERROR GetSetupPinCode(uint32_t & setupPinCode) = 0; - virtual CHIP_ERROR GetSetupDiscriminator(uint16_t & setupDiscriminator) = 0; - virtual CHIP_ERROR GetSpake2pIterationCount(uint32_t & iterationCount) = 0; - virtual CHIP_ERROR GetSpake2pSalt(uint8_t * buf, size_t bufSize, size_t & saltLen) = 0; - virtual CHIP_ERROR GetSpake2pVerifier(uint8_t * buf, size_t bufSize, size_t & verifierLen) = 0; #if CHIP_ENABLE_ROTATING_DEVICE_ID && defined(CHIP_DEVICE_CONFIG_ROTATING_DEVICE_ID_UNIQUE_ID) // Lifetime counter is monotonic counter that is incremented upon each commencement of advertising virtual CHIP_ERROR GetLifetimeCounter(uint16_t & lifetimeCounter) = 0; @@ -120,8 +115,6 @@ class ConfigurationManager virtual CHIP_ERROR StoreManufacturingDate(const char * mfgDate, size_t mfgDateLen) = 0; virtual CHIP_ERROR StoreSoftwareVersion(uint32_t softwareVer) = 0; virtual CHIP_ERROR StoreHardwareVersion(uint16_t hardwareVer) = 0; - virtual CHIP_ERROR StoreSetupPinCode(uint32_t setupPinCode) = 0; - virtual CHIP_ERROR StoreSetupDiscriminator(uint16_t setupDiscriminator) = 0; virtual CHIP_ERROR StoreRegulatoryLocation(uint8_t location) = 0; virtual CHIP_ERROR StoreCountryCode(const char * code, size_t codeLen) = 0; virtual CHIP_ERROR StoreBreadcrumb(uint64_t breadcrumb) = 0; diff --git a/src/include/platform/TestOnlyCommissionableDataProvider.h b/src/include/platform/TestOnlyCommissionableDataProvider.h new file mode 100644 index 00000000000000..86a3d0bc4798fd --- /dev/null +++ b/src/include/platform/TestOnlyCommissionableDataProvider.h @@ -0,0 +1,107 @@ +/* + * + * Copyright (c) 2022 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. + */ +#pragma once + +#include +#include +#include + +namespace chip { +namespace DeviceLayer { + +/** + * @brief Version of a CommissionableDataProvider with just enough + * support for basic tests of the minimum required CommissionableDataProvider + * features, using a default passcode and discriminator. + */ +class TestOnlyCommissionableDataProvider : public CommissionableDataProvider +{ +public: + TestOnlyCommissionableDataProvider() {} + + CHIP_ERROR GetSetupDiscriminator(uint16_t & setupDiscriminator) override + { + constexpr uint16_t kDefaultTestDiscriminator = 3840; + setupDiscriminator = kDefaultTestDiscriminator; + return CHIP_NO_ERROR; + } + + CHIP_ERROR SetSetupDiscriminator(uint16_t setupDiscriminator) override + { + (void) setupDiscriminator; + return CHIP_ERROR_NOT_IMPLEMENTED; + } + + CHIP_ERROR GetSpake2pIterationCount(uint32_t & iterationCount) override + { + constexpr uint32_t kDefaultTestVerifierIterationCount = 1000; + iterationCount = kDefaultTestVerifierIterationCount; + return CHIP_NO_ERROR; + } + + CHIP_ERROR GetSpake2pSalt(MutableByteSpan & saltBuf) override + { + const uint8_t kDefaultTestVerifierSalt[16] = { + 0x53, 0x50, 0x41, 0x4b, 0x45, 0x32, 0x50, 0x20, 0x4b, 0x65, 0x79, 0x20, 0x53, 0x61, 0x6c, 0x74, + }; + + size_t saltLen = sizeof(kDefaultTestVerifierSalt); + if (saltBuf.size() < saltLen) + { + return CHIP_ERROR_BUFFER_TOO_SMALL; + } + memcpy(saltBuf.data(), &kDefaultTestVerifierSalt[0], saltLen); + saltBuf.reduce_size(saltLen); + return CHIP_NO_ERROR; + } + + CHIP_ERROR GetSpake2pVerifier(MutableByteSpan & verifierBuf, size_t & outVerifierLen) override + { + const uint8_t kDefaultTestVerifier[97] = { + 0xb9, 0x61, 0x70, 0xaa, 0xe8, 0x03, 0x34, 0x68, 0x84, 0x72, 0x4f, 0xe9, 0xa3, 0xb2, 0x87, 0xc3, 0x03, 0x30, 0xc2, 0xa6, + 0x60, 0x37, 0x5d, 0x17, 0xbb, 0x20, 0x5a, 0x8c, 0xf1, 0xae, 0xcb, 0x35, 0x04, 0x57, 0xf8, 0xab, 0x79, 0xee, 0x25, 0x3a, + 0xb6, 0xa8, 0xe4, 0x6b, 0xb0, 0x9e, 0x54, 0x3a, 0xe4, 0x22, 0x73, 0x6d, 0xe5, 0x01, 0xe3, 0xdb, 0x37, 0xd4, 0x41, 0xfe, + 0x34, 0x49, 0x20, 0xd0, 0x95, 0x48, 0xe4, 0xc1, 0x82, 0x40, 0x63, 0x0c, 0x4f, 0xf4, 0x91, 0x3c, 0x53, 0x51, 0x38, 0x39, + 0xb7, 0xc0, 0x7f, 0xcc, 0x06, 0x27, 0xa1, 0xb8, 0x57, 0x3a, 0x14, 0x9f, 0xcd, 0x1f, 0xa4, 0x66, 0xcf, + }; + + outVerifierLen = sizeof(kDefaultTestVerifier); + if (verifierBuf.size() < outVerifierLen) + { + return CHIP_ERROR_BUFFER_TOO_SMALL; + } + memcpy(verifierBuf.data(), &kDefaultTestVerifier[0], outVerifierLen); + verifierBuf.reduce_size(outVerifierLen); + return CHIP_NO_ERROR; + } + + CHIP_ERROR GetSetupPasscode(uint32_t & setupPasscode) override + { + constexpr uint32_t kDefaultTestPasscode = 20202021; + setupPasscode = kDefaultTestPasscode; + return CHIP_NO_ERROR; + } + + CHIP_ERROR SetSetupPasscode(uint32_t setupPasscode) override + { + (void) setupPasscode; + return CHIP_ERROR_NOT_IMPLEMENTED; + } +}; + +} // namespace DeviceLayer +} // namespace chip diff --git a/src/include/platform/internal/GenericConfigurationManagerImpl.cpp b/src/include/platform/internal/GenericConfigurationManagerImpl.cpp index 54ed92f12cdb76..b30fd932c19d84 100644 --- a/src/include/platform/internal/GenericConfigurationManagerImpl.cpp +++ b/src/include/platform/internal/GenericConfigurationManagerImpl.cpp @@ -36,6 +36,7 @@ #include #include #include +#include #include #include @@ -50,6 +51,176 @@ namespace chip { namespace DeviceLayer { namespace Internal { +#if CHIP_USE_TRANSITIONAL_COMMISSIONABLE_DATA_PROVIDER + +// Legacy version of CommissionableDataProvider used for a grace period +// to a transition where all ConfigurationManager customers move to +// provide their own impl of CommissionableDataProvider interface. + +template +class LegacyTemporaryCommissionableDataProvider : public CommissionableDataProvider +{ +public: + // GenericConfigurationManagerImpl will own a LegacyTemporaryCommissionableDataProvider which + // *refers back to that GenericConfigurationManagerImpl*, due to how CRTP-based + // storage APIs are defined. This is a bit unclean, but only applicable to the + // transition path when `CHIP_USE_TRANSITIONAL_COMMISSIONABLE_DATA_PROVIDER` is true. + // This circular dependency is NOT needed by CommissionableDataProvider, but required + // to keep legacy code running. + LegacyTemporaryCommissionableDataProvider(GenericConfigurationManagerImpl & configManager) : + mGenericConfigManager(configManager) + {} + + CHIP_ERROR GetSetupDiscriminator(uint16_t & setupDiscriminator) override; + CHIP_ERROR SetSetupDiscriminator(uint16_t setupDiscriminator) override; + CHIP_ERROR GetSpake2pIterationCount(uint32_t & iterationCount) override; + CHIP_ERROR GetSpake2pSalt(MutableByteSpan & saltBuf) override; + CHIP_ERROR GetSpake2pVerifier(MutableByteSpan & verifierBuf, size_t & outVerifierLen) override; + CHIP_ERROR GetSetupPasscode(uint32_t & setupPasscode) override; + CHIP_ERROR SetSetupPasscode(uint32_t setupPasscode) override; + +private: + GenericConfigurationManagerImpl & mGenericConfigManager; +}; + +template +CHIP_ERROR LegacyTemporaryCommissionableDataProvider::GetSetupPasscode(uint32_t & setupPasscode) +{ + CHIP_ERROR err; + + err = mGenericConfigManager.ReadConfigValue(ConfigClass::kConfigKey_SetupPinCode, setupPasscode); +#if defined(CHIP_DEVICE_CONFIG_USE_TEST_SETUP_PIN_CODE) && CHIP_DEVICE_CONFIG_USE_TEST_SETUP_PIN_CODE + if (err == CHIP_DEVICE_ERROR_CONFIG_NOT_FOUND) + { + setupPasscode = CHIP_DEVICE_CONFIG_USE_TEST_SETUP_PIN_CODE; + err = CHIP_NO_ERROR; + } +#endif // defined(CHIP_DEVICE_CONFIG_USE_TEST_SETUP_PIN_CODE) && CHIP_DEVICE_CONFIG_USE_TEST_SETUP_PIN_CODE + SuccessOrExit(err); + +exit: + return err; +} + +template +CHIP_ERROR LegacyTemporaryCommissionableDataProvider::SetSetupPasscode(uint32_t setupPasscode) +{ + return mGenericConfigManager.WriteConfigValue(ConfigClass::kConfigKey_SetupPinCode, setupPasscode); +} + +template +CHIP_ERROR LegacyTemporaryCommissionableDataProvider::GetSetupDiscriminator(uint16_t & setupDiscriminator) +{ + CHIP_ERROR err; + uint32_t val; + + err = mGenericConfigManager.ReadConfigValue(ConfigClass::kConfigKey_SetupDiscriminator, val); +#if defined(CHIP_DEVICE_CONFIG_USE_TEST_SETUP_DISCRIMINATOR) && CHIP_DEVICE_CONFIG_USE_TEST_SETUP_DISCRIMINATOR + if (err == CHIP_DEVICE_ERROR_CONFIG_NOT_FOUND) + { + val = CHIP_DEVICE_CONFIG_USE_TEST_SETUP_DISCRIMINATOR; + err = CHIP_NO_ERROR; + } +#endif // defined(CHIP_DEVICE_CONFIG_USE_TEST_SETUP_DISCRIMINATOR) && CHIP_DEVICE_CONFIG_USE_TEST_SETUP_DISCRIMINATOR + SuccessOrExit(err); + + setupDiscriminator = static_cast(val); + +exit: + return err; +} + +template +CHIP_ERROR LegacyTemporaryCommissionableDataProvider::SetSetupDiscriminator(uint16_t setupDiscriminator) +{ + return mGenericConfigManager.WriteConfigValue(ConfigClass::kConfigKey_SetupDiscriminator, + static_cast(setupDiscriminator)); +} + +template +CHIP_ERROR LegacyTemporaryCommissionableDataProvider::GetSpake2pIterationCount(uint32_t & iterationCount) +{ + CHIP_ERROR err = mGenericConfigManager.ReadConfigValue(ConfigClass::kConfigKey_Spake2pIterationCount, iterationCount); + +#if defined(CHIP_DEVICE_CONFIG_USE_TEST_SPAKE2P_ITERATION_COUNT) && CHIP_DEVICE_CONFIG_USE_TEST_SPAKE2P_ITERATION_COUNT + if (err == CHIP_DEVICE_ERROR_CONFIG_NOT_FOUND) + { + iterationCount = CHIP_DEVICE_CONFIG_USE_TEST_SPAKE2P_ITERATION_COUNT; + err = CHIP_NO_ERROR; + } +#endif // defined(CHIP_DEVICE_CONFIG_USE_TEST_SPAKE2P_ITERATION_COUNT) && CHIP_DEVICE_CONFIG_USE_TEST_SPAKE2P_ITERATION_COUNT + SuccessOrExit(err); + +exit: + return err; +} + +template +CHIP_ERROR LegacyTemporaryCommissionableDataProvider::GetSpake2pSalt(MutableByteSpan & saltBuf) +{ + static constexpr size_t kSpake2pSalt_MaxBase64Len = BASE64_ENCODED_LEN(chip::Crypto::kSpake2p_Max_PBKDF_Salt_Length) + 1; + + CHIP_ERROR err = CHIP_NO_ERROR; + char saltB64[kSpake2pSalt_MaxBase64Len] = { 0 }; + size_t saltB64Len = 0; + + err = mGenericConfigManager.ReadConfigValueStr(ConfigClass::kConfigKey_Spake2pSalt, saltB64, sizeof(saltB64), saltB64Len); + +#if defined(CHIP_DEVICE_CONFIG_USE_TEST_SPAKE2P_SALT) + if (err == CHIP_DEVICE_ERROR_CONFIG_NOT_FOUND) + { + saltB64Len = strlen(CHIP_DEVICE_CONFIG_USE_TEST_SPAKE2P_SALT); + ReturnErrorCodeIf(saltB64Len > sizeof(saltB64), CHIP_ERROR_BUFFER_TOO_SMALL); + memcpy(saltB64, CHIP_DEVICE_CONFIG_USE_TEST_SPAKE2P_SALT, saltB64Len); + err = CHIP_NO_ERROR; + } +#endif // defined(CHIP_DEVICE_CONFIG_USE_TEST_SPAKE2P_SALT) + + ReturnErrorOnFailure(err); + size_t saltLen = chip::Base64Decode32(saltB64, saltB64Len, reinterpret_cast(saltB64)); + + ReturnErrorCodeIf(saltLen > saltBuf.size(), CHIP_ERROR_BUFFER_TOO_SMALL); + memcpy(saltBuf.data(), saltB64, saltLen); + saltBuf.reduce_size(saltLen); + + return CHIP_NO_ERROR; +} + +template +CHIP_ERROR LegacyTemporaryCommissionableDataProvider::GetSpake2pVerifier(MutableByteSpan & verifierBuf, + size_t & verifierLen) +{ + static constexpr size_t kSpake2pSerializedVerifier_MaxBase64Len = + BASE64_ENCODED_LEN(chip::Crypto::kSpake2p_VerifierSerialized_Length) + 1; + + CHIP_ERROR err = CHIP_NO_ERROR; + char verifierB64[kSpake2pSerializedVerifier_MaxBase64Len] = { 0 }; + size_t verifierB64Len = 0; + + err = mGenericConfigManager.ReadConfigValueStr(ConfigClass::kConfigKey_Spake2pVerifier, verifierB64, sizeof(verifierB64), + verifierB64Len); + +#if defined(CHIP_DEVICE_CONFIG_USE_TEST_SPAKE2P_VERIFIER) + if (err == CHIP_DEVICE_ERROR_CONFIG_NOT_FOUND) + { + verifierB64Len = strlen(CHIP_DEVICE_CONFIG_USE_TEST_SPAKE2P_VERIFIER); + ReturnErrorCodeIf(verifierB64Len > sizeof(verifierB64), CHIP_ERROR_BUFFER_TOO_SMALL); + memcpy(verifierB64, CHIP_DEVICE_CONFIG_USE_TEST_SPAKE2P_VERIFIER, verifierB64Len); + err = CHIP_NO_ERROR; + } +#endif // defined(CHIP_DEVICE_CONFIG_USE_TEST_SPAKE2P_VERIFIER) + + ReturnErrorOnFailure(err); + verifierLen = chip::Base64Decode32(verifierB64, verifierB64Len, reinterpret_cast(verifierB64)); + ReturnErrorCodeIf(verifierLen > verifierBuf.size(), CHIP_ERROR_BUFFER_TOO_SMALL); + memcpy(verifierBuf.data(), verifierB64, verifierLen); + verifierBuf.reduce_size(verifierLen); + + return err; +} + +#endif // CHIP_USE_TRANSITIONAL_COMMISSIONABLE_DATA_PROVIDER + template CHIP_ERROR GenericConfigurationManagerImpl::Init() { @@ -59,6 +230,15 @@ CHIP_ERROR GenericConfigurationManagerImpl::Init() mLifetimePersistedCounter.Init(CHIP_CONFIG_LIFETIIME_PERSISTED_COUNTER_KEY); #endif +#if CHIP_USE_TRANSITIONAL_COMMISSIONABLE_DATA_PROVIDER + // Using a temporary singleton here because the overall GenericConfigurationManagerImpl is + // a singleton. This is TEMPORARY code to set the table for clients to set their own + // implementation properly, without loss of functionality for legacy in the meantime. + static LegacyTemporaryCommissionableDataProvider sLegacyTemporaryCommissionableDataProvider(*this); + + SetCommissionableDataProvider(&sLegacyTemporaryCommissionableDataProvider); +#endif + char uniqueId[kMaxUniqueIDLength + 1]; // Generate Unique ID only if it is not present in the storage. @@ -324,136 +504,6 @@ void GenericConfigurationManagerImpl::NotifyOfAdvertisementStart() #endif } -template -CHIP_ERROR GenericConfigurationManagerImpl::GetSetupPinCode(uint32_t & setupPinCode) -{ - CHIP_ERROR err; - - err = ReadConfigValue(ConfigClass::kConfigKey_SetupPinCode, setupPinCode); -#if defined(CHIP_DEVICE_CONFIG_USE_TEST_SETUP_PIN_CODE) && CHIP_DEVICE_CONFIG_USE_TEST_SETUP_PIN_CODE - if (err == CHIP_DEVICE_ERROR_CONFIG_NOT_FOUND) - { - setupPinCode = CHIP_DEVICE_CONFIG_USE_TEST_SETUP_PIN_CODE; - err = CHIP_NO_ERROR; - } -#endif // defined(CHIP_DEVICE_CONFIG_USE_TEST_SETUP_PIN_CODE) && CHIP_DEVICE_CONFIG_USE_TEST_SETUP_PIN_CODE - SuccessOrExit(err); - -exit: - return err; -} - -template -CHIP_ERROR GenericConfigurationManagerImpl::StoreSetupPinCode(uint32_t setupPinCode) -{ - return WriteConfigValue(ConfigClass::kConfigKey_SetupPinCode, setupPinCode); -} - -template -CHIP_ERROR GenericConfigurationManagerImpl::GetSetupDiscriminator(uint16_t & setupDiscriminator) -{ - CHIP_ERROR err; - uint32_t val; - - err = ReadConfigValue(ConfigClass::kConfigKey_SetupDiscriminator, val); -#if defined(CHIP_DEVICE_CONFIG_USE_TEST_SETUP_DISCRIMINATOR) && CHIP_DEVICE_CONFIG_USE_TEST_SETUP_DISCRIMINATOR - if (err == CHIP_DEVICE_ERROR_CONFIG_NOT_FOUND) - { - val = CHIP_DEVICE_CONFIG_USE_TEST_SETUP_DISCRIMINATOR; - err = CHIP_NO_ERROR; - } -#endif // defined(CHIP_DEVICE_CONFIG_USE_TEST_SETUP_DISCRIMINATOR) && CHIP_DEVICE_CONFIG_USE_TEST_SETUP_DISCRIMINATOR - SuccessOrExit(err); - - setupDiscriminator = static_cast(val); - -exit: - return err; -} - -template -CHIP_ERROR GenericConfigurationManagerImpl::StoreSetupDiscriminator(uint16_t setupDiscriminator) -{ - return WriteConfigValue(ConfigClass::kConfigKey_SetupDiscriminator, static_cast(setupDiscriminator)); -} - -template -CHIP_ERROR GenericConfigurationManagerImpl::GetSpake2pIterationCount(uint32_t & iterationCount) -{ - CHIP_ERROR err = ReadConfigValue(ConfigClass::kConfigKey_Spake2pIterationCount, iterationCount); - -#if defined(CHIP_DEVICE_CONFIG_USE_TEST_SPAKE2P_ITERATION_COUNT) && CHIP_DEVICE_CONFIG_USE_TEST_SPAKE2P_ITERATION_COUNT - if (err == CHIP_DEVICE_ERROR_CONFIG_NOT_FOUND) - { - iterationCount = CHIP_DEVICE_CONFIG_USE_TEST_SPAKE2P_ITERATION_COUNT; - err = CHIP_NO_ERROR; - } -#endif // defined(CHIP_DEVICE_CONFIG_USE_TEST_SPAKE2P_ITERATION_COUNT) && CHIP_DEVICE_CONFIG_USE_TEST_SPAKE2P_ITERATION_COUNT - SuccessOrExit(err); - -exit: - return err; -} - -template -CHIP_ERROR GenericConfigurationManagerImpl::GetSpake2pSalt(uint8_t * buf, size_t bufSize, size_t & saltLen) -{ - static constexpr size_t kSpake2pSalt_MaxBase64Len = BASE64_ENCODED_LEN(chip::Crypto::kSpake2p_Max_PBKDF_Salt_Length) + 1; - - CHIP_ERROR err = CHIP_NO_ERROR; - char saltB64[kSpake2pSalt_MaxBase64Len] = { 0 }; - size_t saltB64Len = 0; - - err = ReadConfigValueStr(ConfigClass::kConfigKey_Spake2pSalt, saltB64, sizeof(saltB64), saltB64Len); - -#if defined(CHIP_DEVICE_CONFIG_USE_TEST_SPAKE2P_SALT) - if (err == CHIP_DEVICE_ERROR_CONFIG_NOT_FOUND) - { - saltB64Len = strlen(CHIP_DEVICE_CONFIG_USE_TEST_SPAKE2P_SALT); - ReturnErrorCodeIf(saltB64Len > sizeof(saltB64), CHIP_ERROR_BUFFER_TOO_SMALL); - memcpy(saltB64, CHIP_DEVICE_CONFIG_USE_TEST_SPAKE2P_SALT, saltB64Len); - err = CHIP_NO_ERROR; - } -#endif // defined(CHIP_DEVICE_CONFIG_USE_TEST_SPAKE2P_SALT) - - ReturnErrorOnFailure(err); - saltLen = chip::Base64Decode32(saltB64, saltB64Len, reinterpret_cast(saltB64)); - ReturnErrorCodeIf(saltLen > bufSize, CHIP_ERROR_BUFFER_TOO_SMALL); - memcpy(buf, saltB64, saltLen); - - return CHIP_NO_ERROR; -} - -template -CHIP_ERROR GenericConfigurationManagerImpl::GetSpake2pVerifier(uint8_t * buf, size_t bufSize, size_t & verifierLen) -{ - static constexpr size_t kSpake2pSerializedVerifier_MaxBase64Len = - BASE64_ENCODED_LEN(chip::Crypto::kSpake2p_VerifierSerialized_Length) + 1; - - CHIP_ERROR err = CHIP_NO_ERROR; - char verifierB64[kSpake2pSerializedVerifier_MaxBase64Len] = { 0 }; - size_t verifierB64Len = 0; - - err = ReadConfigValueStr(ConfigClass::kConfigKey_Spake2pVerifier, verifierB64, sizeof(verifierB64), verifierB64Len); - -#if defined(CHIP_DEVICE_CONFIG_USE_TEST_SPAKE2P_VERIFIER) - if (err == CHIP_DEVICE_ERROR_CONFIG_NOT_FOUND) - { - verifierB64Len = strlen(CHIP_DEVICE_CONFIG_USE_TEST_SPAKE2P_VERIFIER); - ReturnErrorCodeIf(verifierB64Len > sizeof(verifierB64), CHIP_ERROR_BUFFER_TOO_SMALL); - memcpy(verifierB64, CHIP_DEVICE_CONFIG_USE_TEST_SPAKE2P_VERIFIER, verifierB64Len); - err = CHIP_NO_ERROR; - } -#endif // defined(CHIP_DEVICE_CONFIG_USE_TEST_SPAKE2P_VERIFIER) - - ReturnErrorOnFailure(err); - verifierLen = chip::Base64Decode32(verifierB64, verifierB64Len, reinterpret_cast(verifierB64)); - ReturnErrorCodeIf(verifierLen > bufSize, CHIP_ERROR_BUFFER_TOO_SMALL); - memcpy(buf, verifierB64, verifierLen); - - return err; -} - template CHIP_ERROR GenericConfigurationManagerImpl::GetRegulatoryLocation(uint8_t & location) { @@ -656,7 +706,7 @@ GenericConfigurationManagerImpl::GetBLEDeviceIdentificationInfo(Ble SuccessOrExit(err); deviceIdInfo.SetProductId(id); - err = GetSetupDiscriminator(discriminator); + err = GetCommissionableDataProvider()->GetSetupDiscriminator(discriminator); SuccessOrExit(err); deviceIdInfo.SetDeviceDiscriminator(discriminator); @@ -778,22 +828,25 @@ void GenericConfigurationManagerImpl::LogDeviceConfig() ChipLogProgress(DeviceLayer, " Hardware Version: %" PRIu16, hardwareVer); } + CommissionableDataProvider * cdp = GetCommissionableDataProvider(); + { - uint32_t setupPINCode; - if (GetSetupPinCode(setupPINCode) != CHIP_NO_ERROR) + uint32_t setupPasscode; + if ((cdp == nullptr) || (cdp->GetSetupPasscode(setupPasscode) != CHIP_NO_ERROR)) { - setupPINCode = 0; + setupPasscode = 0; } - ChipLogProgress(DeviceLayer, " Setup Pin Code: %" PRIu32 "", setupPINCode); + ChipLogProgress(DeviceLayer, " Setup Pin Code (0 for UNKNOWN/ERROR): %" PRIu32 "", setupPasscode); } { uint16_t setupDiscriminator; - if (GetSetupDiscriminator(setupDiscriminator) != CHIP_NO_ERROR) + if ((cdp == nullptr) || (cdp->GetSetupDiscriminator(setupDiscriminator) != CHIP_NO_ERROR)) { - setupDiscriminator = 0; + setupDiscriminator = 0xFFFF; } - ChipLogProgress(DeviceLayer, " Setup Discriminator: %" PRIu16 " (0x%" PRIX16 ")", setupDiscriminator, setupDiscriminator); + ChipLogProgress(DeviceLayer, " Setup Discriminator (0xFFFF for UNKNOWN/ERROR): %" PRIu16 " (0x%" PRIX16 ")", + setupDiscriminator, setupDiscriminator); } { diff --git a/src/include/platform/internal/GenericConfigurationManagerImpl.h b/src/include/platform/internal/GenericConfigurationManagerImpl.h index 0fe14efaee9c9a..41f4dd856ae324 100644 --- a/src/include/platform/internal/GenericConfigurationManagerImpl.h +++ b/src/include/platform/internal/GenericConfigurationManagerImpl.h @@ -40,6 +40,11 @@ class ProvisioningDataSet; namespace Internal { +#if CHIP_USE_TRANSITIONAL_COMMISSIONABLE_DATA_PROVIDER +template +class LegacyTemporaryCommissionableDataProvider; +#endif // CHIP_USE_TRANSITIONAL_COMMISSIONABLE_DATA_PROVIDER + /** * Provides a generic implementation of ConfigurationManager features that works on multiple platforms. * @@ -73,15 +78,6 @@ class GenericConfigurationManagerImpl : public ConfigurationManager CHIP_ERROR StorePrimary802154MACAddress(const uint8_t * buf) override; CHIP_ERROR GetManufacturingDate(uint16_t & year, uint8_t & month, uint8_t & dayOfMonth) override; CHIP_ERROR StoreManufacturingDate(const char * mfgDate, size_t mfgDateLen) override; - // TODO: Remove SetupPinCode Get/Set APIs - // Device shouldn't store and access PIN Code - only Spake2p parameters and verifier - CHIP_ERROR GetSetupPinCode(uint32_t & setupPinCode) override; - CHIP_ERROR StoreSetupPinCode(uint32_t setupPinCode) override; - CHIP_ERROR GetSetupDiscriminator(uint16_t & setupDiscriminator) override; - CHIP_ERROR StoreSetupDiscriminator(uint16_t setupDiscriminator) override; - CHIP_ERROR GetSpake2pIterationCount(uint32_t & iterationCount) override; - CHIP_ERROR GetSpake2pSalt(uint8_t * buf, size_t bufSize, size_t & saltLen) override; - CHIP_ERROR GetSpake2pVerifier(uint8_t * buf, size_t bufSize, size_t & verifierLen) override; #if CHIP_ENABLE_ROTATING_DEVICE_ID && defined(CHIP_DEVICE_CONFIG_ROTATING_DEVICE_ID_UNIQUE_ID) CHIP_ERROR GetLifetimeCounter(uint16_t & lifetimeCounter) override; CHIP_ERROR IncrementLifetimeCounter() override; @@ -136,6 +132,11 @@ class GenericConfigurationManagerImpl : public ConfigurationManager #if CHIP_ENABLE_ROTATING_DEVICE_ID && defined(CHIP_DEVICE_CONFIG_ROTATING_DEVICE_ID_UNIQUE_ID) chip::LifetimePersistedCounter mLifetimePersistedCounter; #endif + +#if CHIP_USE_TRANSITIONAL_COMMISSIONABLE_DATA_PROVIDER + friend LegacyTemporaryCommissionableDataProvider; +#endif // CHIP_USE_TRANSITIONAL_COMMISSIONABLE_DATA_PROVIDER + CHIP_ERROR PersistProvisioningData(ProvisioningDataSet & provData); // Methods to read and write configuration values, as well as run the configuration unit test. diff --git a/src/lib/shell/commands/Config.cpp b/src/lib/shell/commands/Config.cpp index d8686c41bc5ba3..5a9449e21ef63d 100644 --- a/src/lib/shell/commands/Config.cpp +++ b/src/lib/shell/commands/Config.cpp @@ -24,6 +24,7 @@ #include #include #include +#include using chip::DeviceLayer::ConfigurationMgr; @@ -100,7 +101,7 @@ static CHIP_ERROR ConfigGetSetupPinCode(bool printHeader) streamer_t * sout = streamer_get(); uint32_t setupPinCode; - ReturnErrorOnFailure(ConfigurationMgr().GetSetupPinCode(setupPinCode)); + ReturnErrorOnFailure(DeviceLayer::GetCommissionableDataProvider()->GetSetupPasscode(setupPinCode)); if (printHeader) { streamer_printf(sout, "PinCode: "); @@ -119,12 +120,12 @@ static CHIP_ERROR ConfigGetSetupDiscriminator(bool printHeader) streamer_t * sout = streamer_get(); uint16_t setupDiscriminator; - ReturnErrorOnFailure(ConfigurationMgr().GetSetupDiscriminator(setupDiscriminator)); + ReturnErrorOnFailure(DeviceLayer::GetCommissionableDataProvider()->GetSetupDiscriminator(setupDiscriminator)); if (printHeader) { streamer_printf(sout, "Discriminator: "); } - streamer_printf(sout, "%03x\r\n", setupDiscriminator & 0xFFF); + streamer_printf(sout, "%03x\r\n", setupDiscriminator & chip::kMaxDiscriminatorValue); return CHIP_NO_ERROR; } @@ -134,9 +135,9 @@ static CHIP_ERROR ConfigSetSetupDiscriminator(char * argv) streamer_t * sout = streamer_get(); uint16_t setupDiscriminator = strtoull(argv, NULL, 10); - VerifyOrReturnError(setupDiscriminator != 0 && setupDiscriminator < 0xFFF, CHIP_ERROR_INVALID_ARGUMENT); + VerifyOrReturnError(setupDiscriminator != 0 && setupDiscriminator < chip::kMaxDiscriminatorValue, CHIP_ERROR_INVALID_ARGUMENT); - error = ConfigurationMgr().StoreSetupDiscriminator(setupDiscriminator); + error = DeviceLayer::GetCommissionableDataProvider()->SetSetupDiscriminator(setupDiscriminator); if (error == CHIP_NO_ERROR) { diff --git a/src/platform/Ameba/BLEManagerImpl.cpp b/src/platform/Ameba/BLEManagerImpl.cpp index 9d892bff92882f..1116db19b359ef 100755 --- a/src/platform/Ameba/BLEManagerImpl.cpp +++ b/src/platform/Ameba/BLEManagerImpl.cpp @@ -25,6 +25,7 @@ /* this file behaves like a config.h, comes first */ #include #include +#include #include #if CHIP_DEVICE_CONFIG_ENABLE_CHIPOBLE @@ -590,7 +591,7 @@ CHIP_ERROR BLEManagerImpl::ConfigureAdvertisingData(void) // If the device name is not specified, generate a CHIP-standard name based on the bottom digits of the Chip device id. uint16_t discriminator; - SuccessOrExit(err = ConfigurationMgr().GetSetupDiscriminator(discriminator)); + SuccessOrExit(err = GetCommissionableDataProvider()->GetSetupDiscriminator(discriminator)); if (!mFlags.Has(Flags::kDeviceNameSet)) { diff --git a/src/platform/BUILD.gn b/src/platform/BUILD.gn index e9c9c21aace0b1..5395d4c29a771e 100644 --- a/src/platform/BUILD.gn +++ b/src/platform/BUILD.gn @@ -56,6 +56,12 @@ if (chip_device_platform != "none") { # Enable including the additional data in the advertisement packets chip_enable_additional_data_advertising = false + # Enable default/generic test-mode CommissionableDataProvider in GenericConfigurationManagerImpl + # === FOR TRANSITION UNTIL ALL EXAMPLES PROVIDE THEIR OWN === + # Linux platform has already transitioned. + chip_use_transitional_commissionable_data_provider = + chip_device_platform != "linux" + # lock tracking: none/log/fatal or auto for a platform-dependent choice chip_stack_lock_tracking = "auto" @@ -135,6 +141,12 @@ if (chip_device_platform != "none") { defines += [ "CHIP_DEVICE_CONFIG_FIRMWARE_BUILD_TIME=\"${chip_device_config_firmware_build_time}\"" ] } + if (chip_use_transitional_commissionable_data_provider) { + defines += [ "CHIP_USE_TRANSITIONAL_COMMISSIONABLE_DATA_PROVIDER=1" ] + } else { + defines += [ "CHIP_USE_TRANSITIONAL_COMMISSIONABLE_DATA_PROVIDER=0" ] + } + if (chip_device_platform == "cc13x2_26x2") { defines += [ "CHIP_DEVICE_LAYER_TARGET_CC13X2_26X2=1", @@ -271,6 +283,7 @@ if (chip_device_platform != "none") { "../include/platform/CHIPDeviceError.h", "../include/platform/CHIPDeviceEvent.h", "../include/platform/CHIPDeviceLayer.h", + "../include/platform/CommissionableDataProvider.h", "../include/platform/ConfigurationManager.h", "../include/platform/ConnectivityManager.h", "../include/platform/DeviceControlServer.h", @@ -279,6 +292,7 @@ if (chip_device_platform != "none") { "../include/platform/KeyValueStoreManager.h", "../include/platform/PersistedStorage.h", "../include/platform/PlatformManager.h", + "../include/platform/TestOnlyCommissionableDataProvider.h", "../include/platform/ThreadStackManager.h", "../include/platform/internal/BLEManager.h", "../include/platform/internal/CHIPDeviceLayerInternal.h", @@ -297,6 +311,7 @@ if (chip_device_platform != "none") { "../include/platform/internal/GenericPlatformManagerImpl_FreeRTOS.h", "../include/platform/internal/GenericPlatformManagerImpl_POSIX.h", "../include/platform/internal/testing/ConfigUnitTest.h", + "CommissionableDataProvider.cpp", "DeviceControlServer.cpp", "DiagnosticDataProvider.cpp", "Entropy.cpp", diff --git a/src/platform/CommissionableDataProvider.cpp b/src/platform/CommissionableDataProvider.cpp new file mode 100644 index 00000000000000..f385971544419e --- /dev/null +++ b/src/platform/CommissionableDataProvider.cpp @@ -0,0 +1,47 @@ +/* + * + * Copyright (c) 2021 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 + +namespace chip { +namespace DeviceLayer { + +namespace { + +CommissionableDataProvider * gCommissionableDataProvider = nullptr; + +} // namespace + +CommissionableDataProvider * GetCommissionableDataProvider() +{ + VerifyOrDie(gCommissionableDataProvider != nullptr); + return gCommissionableDataProvider; +} + +void SetCommissionableDataProvider(CommissionableDataProvider * provider) +{ + if (provider == nullptr) + { + return; + } + + gCommissionableDataProvider = provider; +} + +} // namespace Credentials +} // namespace chip diff --git a/src/platform/ESP32/ConnectivityManagerImpl_WiFi.cpp b/src/platform/ESP32/ConnectivityManagerImpl_WiFi.cpp index 6b683d916a44e0..f2e5156ca532de 100644 --- a/src/platform/ESP32/ConnectivityManagerImpl_WiFi.cpp +++ b/src/platform/ESP32/ConnectivityManagerImpl_WiFi.cpp @@ -19,6 +19,7 @@ /* this file behaves like a config.h, comes first */ #include +#include #include #include @@ -837,7 +838,7 @@ CHIP_ERROR ConnectivityManagerImpl::ConfigureWiFiAP() memset(&wifiConfig, 0, sizeof(wifiConfig)); uint16_t discriminator; - ReturnErrorOnFailure(ConfigurationMgr().GetSetupDiscriminator(discriminator)); + ReturnErrorOnFailure(GetCommissionableDataProvider()->GetSetupDiscriminator(discriminator)); snprintf((char *) wifiConfig.ap.ssid, sizeof(wifiConfig.ap.ssid), "%s%03X-%04X-%04X", CHIP_DEVICE_CONFIG_WIFI_AP_SSID_PREFIX, discriminator, CHIP_DEVICE_CONFIG_DEVICE_VENDOR_ID, CHIP_DEVICE_CONFIG_DEVICE_PRODUCT_ID); wifiConfig.ap.channel = CHIP_DEVICE_CONFIG_WIFI_AP_CHANNEL; diff --git a/src/platform/ESP32/bluedroid/BLEManagerImpl.cpp b/src/platform/ESP32/bluedroid/BLEManagerImpl.cpp index 808a6ba0b029bd..d5609a129116da 100644 --- a/src/platform/ESP32/bluedroid/BLEManagerImpl.cpp +++ b/src/platform/ESP32/bluedroid/BLEManagerImpl.cpp @@ -35,6 +35,7 @@ #include #include #include +#include #include "esp_bt.h" #include "esp_bt_main.h" @@ -689,7 +690,7 @@ CHIP_ERROR BLEManagerImpl::ConfigureAdvertisingData(void) // If a custom device name has not been specified, generate a CHIP-standard name based on the // discriminator value uint16_t discriminator; - SuccessOrExit(err = ConfigurationMgr().GetSetupDiscriminator(discriminator)); + SuccessOrExit(err = GetCommissionableDataProvider()->GetSetupDiscriminator(discriminator)); if (!mFlags.Has(Flags::kUseCustomDeviceName)) { diff --git a/src/platform/ESP32/nimble/BLEManagerImpl.cpp b/src/platform/ESP32/nimble/BLEManagerImpl.cpp index 8c40ec28c09619..b64789373c88b6 100644 --- a/src/platform/ESP32/nimble/BLEManagerImpl.cpp +++ b/src/platform/ESP32/nimble/BLEManagerImpl.cpp @@ -34,6 +34,7 @@ #include #include #include +#include #include #include @@ -699,7 +700,7 @@ CHIP_ERROR BLEManagerImpl::ConfigureAdvertisingData(void) // If a custom device name has not been specified, generate a CHIP-standard name based on the // bottom digits of the Chip device id. uint16_t discriminator; - SuccessOrExit(err = ConfigurationMgr().GetSetupDiscriminator(discriminator)); + SuccessOrExit(err = GetCommissionableDataProvider()->GetSetupDiscriminator(discriminator)); if (!mFlags.Has(Flags::kUseCustomDeviceName)) { diff --git a/src/platform/Linux/BLEManagerImpl.cpp b/src/platform/Linux/BLEManagerImpl.cpp index 020783698b18d4..2a37b98a50e5eb 100644 --- a/src/platform/Linux/BLEManagerImpl.cpp +++ b/src/platform/Linux/BLEManagerImpl.cpp @@ -28,6 +28,7 @@ #include #include #include +#include #include #include @@ -175,7 +176,7 @@ CHIP_ERROR BLEManagerImpl::_SetDeviceName(const char * deviceName) else { uint16_t discriminator; - SuccessOrExit(err = ConfigurationMgr().GetSetupDiscriminator(discriminator)); + SuccessOrExit(err = GetCommissionableDataProvider()->GetSetupDiscriminator(discriminator)); snprintf(mDeviceName, sizeof(mDeviceName), "%s%04u", CHIP_DEVICE_CONFIG_BLE_DEVICE_NAME_PREFIX, discriminator); mDeviceName[kMaxDeviceNameLength] = 0; mFlags.Clear(Flags::kUseCustomDeviceName); diff --git a/src/platform/Linux/ConnectivityManagerImpl.cpp b/src/platform/Linux/ConnectivityManagerImpl.cpp index d5fd4e4a0b1143..8b8f3059d338c8 100644 --- a/src/platform/Linux/ConnectivityManagerImpl.cpp +++ b/src/platform/Linux/ConnectivityManagerImpl.cpp @@ -18,6 +18,7 @@ #include +#include #include #include #include @@ -805,7 +806,7 @@ CHIP_ERROR ConnectivityManagerImpl::ConfigureWiFiAP() channel = ConnectivityUtils::MapChannelToFrequency(kWiFi_BAND_2_4_GHZ, CHIP_DEVICE_CONFIG_WIFI_AP_CHANNEL); - if (ConfigurationMgr().GetSetupDiscriminator(discriminator) != CHIP_NO_ERROR) + if (GetCommissionableDataProvider()->GetSetupDiscriminator(discriminator) != CHIP_NO_ERROR) discriminator = 0; snprintf(ssid, 32, "%s%04u", CHIP_DEVICE_CONFIG_WIFI_AP_SSID_PREFIX, discriminator); diff --git a/src/platform/OpenThread/GenericThreadStackManagerImpl_OpenThread.cpp b/src/platform/OpenThread/GenericThreadStackManagerImpl_OpenThread.cpp index 52d85196b3cb6c..7c80e508483b32 100644 --- a/src/platform/OpenThread/GenericThreadStackManagerImpl_OpenThread.cpp +++ b/src/platform/OpenThread/GenericThreadStackManagerImpl_OpenThread.cpp @@ -1799,9 +1799,10 @@ CHIP_ERROR GenericThreadStackManagerImpl_OpenThread::_JoinerStart(voi { otJoinerDiscerner discerner; - uint16_t discriminator; + // This is dead code to remove, so the placeholder value is OK. + // See ThreadStackManagerImpl. + uint16_t discriminator = 3840; - SuccessOrExit(error = ConfigurationMgr().GetSetupDiscriminator(discriminator)); discerner.mLength = 12; discerner.mValue = discriminator; @@ -1811,9 +1812,10 @@ CHIP_ERROR GenericThreadStackManagerImpl_OpenThread::_JoinerStart(voi { otJoinerPskd pskd; - uint32_t pincode; + // This is dead code to remove, so the placeholder value is OK.d + // See ThreadStackManagerImpl. + uint32_t pincode = 20202021; - SuccessOrExit(error = ConfigurationMgr().GetSetupPinCode(pincode)); snprintf(pskd.m8, sizeof(pskd.m8) - 1, "%09" PRIu32, pincode); ChipLogProgress(DeviceLayer, "Joiner PSKd: %s", pskd.m8); diff --git a/src/platform/fake/ConfigurationManagerImpl.h b/src/platform/fake/ConfigurationManagerImpl.h index 331c2441ecb1e8..6348d20a98f996 100644 --- a/src/platform/fake/ConfigurationManagerImpl.h +++ b/src/platform/fake/ConfigurationManagerImpl.h @@ -57,16 +57,6 @@ class ConfigurationManagerImpl : public ConfigurationManager return CHIP_ERROR_NOT_IMPLEMENTED; } CHIP_ERROR StoreManufacturingDate(const char * mfgDate, size_t mfgDateLen) override { return CHIP_ERROR_NOT_IMPLEMENTED; } - CHIP_ERROR GetSetupPinCode(uint32_t & setupPinCode) override { return CHIP_ERROR_NOT_IMPLEMENTED; } - CHIP_ERROR StoreSetupPinCode(uint32_t setupPinCode) override { return CHIP_ERROR_NOT_IMPLEMENTED; } - CHIP_ERROR GetSetupDiscriminator(uint16_t & setupDiscriminator) override { return CHIP_ERROR_NOT_IMPLEMENTED; } - CHIP_ERROR StoreSetupDiscriminator(uint16_t setupDiscriminator) override { return CHIP_ERROR_NOT_IMPLEMENTED; } - CHIP_ERROR GetSpake2pIterationCount(uint32_t & iterationCount) override { return CHIP_ERROR_NOT_IMPLEMENTED; } - CHIP_ERROR GetSpake2pSalt(uint8_t * buf, size_t bufSize, size_t & saltLen) override { return CHIP_ERROR_NOT_IMPLEMENTED; } - CHIP_ERROR GetSpake2pVerifier(uint8_t * buf, size_t bufSize, size_t & verifierLen) override - { - return CHIP_ERROR_NOT_IMPLEMENTED; - } #if CHIP_ENABLE_ROTATING_DEVICE_ID && defined(CHIP_DEVICE_CONFIG_ROTATING_DEVICE_ID_UNIQUE_ID) CHIP_ERROR GetLifetimeCounter(uint16_t & lifetimeCounter) override { return CHIP_ERROR_NOT_IMPLEMENTED; } CHIP_ERROR IncrementLifetimeCounter() override { return CHIP_ERROR_NOT_IMPLEMENTED; } diff --git a/src/platform/mbed/BLEManagerImpl.cpp b/src/platform/mbed/BLEManagerImpl.cpp index 0dfa816c246264..8d28a12fc6f300 100644 --- a/src/platform/mbed/BLEManagerImpl.cpp +++ b/src/platform/mbed/BLEManagerImpl.cpp @@ -34,6 +34,7 @@ #include #include #include +#include // Show BLE status with LEDs #define _BLEMGRIMPL_USE_LEDS 0 @@ -771,7 +772,7 @@ CHIP_ERROR BLEManagerImpl::StartAdvertising(void) if (!mFlags.Has(kFlag_UseCustomDeviceName)) { uint16_t discriminator; - SuccessOrExit(err = ConfigurationMgr().GetSetupDiscriminator(discriminator)); + SuccessOrExit(err = GetCommissionableDataProvider()->GetSetupDiscriminator(discriminator)); memset(mDeviceName, 0, kMaxDeviceNameLength); snprintf(mDeviceName, kMaxDeviceNameLength, "%s%04u", CHIP_DEVICE_CONFIG_BLE_DEVICE_NAME_PREFIX, discriminator); } diff --git a/src/platform/nxp/k32w/k32w0/BLEManagerImpl.cpp b/src/platform/nxp/k32w/k32w0/BLEManagerImpl.cpp index c1d0c7bdd1aaf7..00229438b1616c 100644 --- a/src/platform/nxp/k32w/k32w0/BLEManagerImpl.cpp +++ b/src/platform/nxp/k32w/k32w0/BLEManagerImpl.cpp @@ -26,6 +26,8 @@ /* this file behaves like a config.h, comes first */ #include +#include + #include #if CHIP_DEVICE_CONFIG_ENABLE_CHIPOBLE @@ -799,7 +801,7 @@ CHIP_ERROR BLEManagerImpl::ConfigureAdvertisingData(void) ChipBLEDeviceIdentificationInfo mDeviceIdInfo = { 0 }; uint8_t mDeviceIdInfoLength = 0; - chipErr = ConfigurationMgr().GetSetupDiscriminator(discriminator); + chipErr = GetCommissionableDataProvider()->GetSetupDiscriminator(discriminator); if (chipErr != CHIP_NO_ERROR) { return chipErr; diff --git a/src/platform/tests/TestConfigurationMgr.cpp b/src/platform/tests/TestConfigurationMgr.cpp index 1285a291742322..05496319702588 100644 --- a/src/platform/tests/TestConfigurationMgr.cpp +++ b/src/platform/tests/TestConfigurationMgr.cpp @@ -147,38 +147,6 @@ static void TestConfigurationMgr_HardwareVersion(nlTestSuite * inSuite, void * i NL_TEST_ASSERT(inSuite, hardwareVer == 1234); } -static void TestConfigurationMgr_SetupPinCode(nlTestSuite * inSuite, void * inContext) -{ - CHIP_ERROR err = CHIP_NO_ERROR; - - const uint32_t setSetupPinCode = 34567890; - uint32_t getSetupPinCode = 0; - - err = ConfigurationMgr().StoreSetupPinCode(setSetupPinCode); - NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR); - - err = ConfigurationMgr().GetSetupPinCode(getSetupPinCode); - NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR); - - NL_TEST_ASSERT(inSuite, getSetupPinCode == setSetupPinCode); -} - -static void TestConfigurationMgr_SetupDiscriminator(nlTestSuite * inSuite, void * inContext) -{ - CHIP_ERROR err = CHIP_NO_ERROR; - - const uint16_t setSetupDiscriminator = 0xBA0; - uint16_t getSetupDiscriminator = 0; - - err = ConfigurationMgr().StoreSetupDiscriminator(setSetupDiscriminator); - NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR); - - err = ConfigurationMgr().GetSetupDiscriminator(getSetupDiscriminator); - NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR); - - NL_TEST_ASSERT(inSuite, getSetupDiscriminator == setSetupDiscriminator); -} - static void TestConfigurationMgr_CountryCode(nlTestSuite * inSuite, void * inContext) { CHIP_ERROR err = CHIP_NO_ERROR; @@ -250,8 +218,6 @@ static const nlTest sTests[] = { NL_TEST_DEF("Test ConfigurationMgr::UniqueId", TestConfigurationMgr_UniqueId), NL_TEST_DEF("Test ConfigurationMgr::ManufacturingDate", TestConfigurationMgr_ManufacturingDate), NL_TEST_DEF("Test ConfigurationMgr::HardwareVersion", TestConfigurationMgr_HardwareVersion), - NL_TEST_DEF("Test ConfigurationMgr::SetupPinCode", TestConfigurationMgr_SetupPinCode), - NL_TEST_DEF("Test ConfigurationMgr::SetupDiscriminator", TestConfigurationMgr_SetupDiscriminator), NL_TEST_DEF("Test ConfigurationMgr::CountryCode", TestConfigurationMgr_CountryCode), NL_TEST_DEF("Test ConfigurationMgr::Breadcrumb", TestConfigurationMgr_Breadcrumb), NL_TEST_DEF("Test ConfigurationMgr::GetPrimaryMACAddress", TestConfigurationMgr_GetPrimaryMACAddress), diff --git a/src/setup_payload/SetupPayload.h b/src/setup_payload/SetupPayload.h index 298dd54ea12a69..5e30de27fda089 100644 --- a/src/setup_payload/SetupPayload.h +++ b/src/setup_payload/SetupPayload.h @@ -67,9 +67,6 @@ const int kManualSetupProductIdCharLength = 5; const uint8_t kSerialNumberTag = 128; -// The largest value of the 12-bit Payload discriminator -const uint16_t kMaxDiscriminatorValue = 0xFFF; - // clang-format off const int kTotalPayloadDataSizeInBits = kVersionFieldLengthInBits +