blob: a23deaa6ee04714a919438cced4a4ee0bbcc2654 [file] [log] [blame]
/*
*
* 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 <crypto/CHIPCryptoPAL.h>
#include <lib/support/CodeUtils.h>
#include <lib/support/logging/CHIPLogging.h>
#include "CommissionableInit.h"
namespace chip {
namespace examples {
using namespace chip::DeviceLayer;
using namespace chip::DeviceLayer::Internal;
namespace {
bool IsNotFound(CHIP_ERROR err)
{
// PosixConfig should probably return CHIP_DEVICE_ERROR_CONFIG_NOT_FOUND, but some implementations use other error codes.
return (err == CHIP_DEVICE_ERROR_CONFIG_NOT_FOUND || err == CHIP_ERROR_PERSISTED_STORAGE_VALUE_NOT_FOUND ||
err == CHIP_ERROR_NOT_FOUND || err == CHIP_ERROR_KEY_NOT_FOUND);
}
template <typename T>
CHIP_ERROR ReadOptionalConfigValue(PosixConfig::Key key, Optional<T> & outValue)
{
CHIP_ERROR err = PosixConfig::ReadConfigValue(key, outValue.Emplace());
if (err != CHIP_NO_ERROR)
{
outValue.ClearValue();
if (IsNotFound(err))
{
err = CHIP_NO_ERROR; // value is optional, not found is OK
}
}
return err;
}
CHIP_ERROR ReadOptionalConfigValueBin(PosixConfig::Key key, size_t bufSize, chip::Optional<std::vector<uint8_t>> & outValue)
{
size_t length;
outValue.Emplace(bufSize);
CHIP_ERROR err = PosixConfig::ReadConfigValueBin(key, outValue.Value().data(), outValue.Value().size(), length);
if (err == CHIP_NO_ERROR)
{
outValue.Value().resize(length);
}
else
{
outValue.ClearValue();
if (IsNotFound(err))
{
err = CHIP_NO_ERROR; // value is optional, not found is OK
}
}
return err;
}
CHIP_ERROR GetPinCodeAndVerifier(const LinuxDeviceOptions & options, chip::Optional<uint32_t> & outPinCode,
chip::Optional<std::vector<uint8_t>> & outVerifier)
{
// Command line options take precedence
outPinCode = (options.payload.setUpPINCode != 0 ? MakeOptional(options.payload.setUpPINCode) : NullOptional);
outVerifier = options.spake2pVerifier;
if (outPinCode.HasValue() || outVerifier.HasValue())
{
return CHIP_NO_ERROR;
}
// Read from PosixConfig
ReturnErrorOnFailure(ReadOptionalConfigValue(PosixConfig::kConfigKey_SetupPinCode, outPinCode));
ReturnErrorOnFailure(ReadOptionalConfigValueBin(PosixConfig::kConfigKey_Spake2pVerifier,
Crypto::kSpake2p_VerifierSerialized_Length, outVerifier));
if (outPinCode.HasValue() || outVerifier.HasValue())
{
return CHIP_NO_ERROR;
}
#if CHIP_DEVICE_CONFIG_ENABLE_TEST_SETUP_PARAMS
// Fall back to test parameters. Note: CHIP_DEVICE_CONFIG_USE_TEST_SPAKE2P_VERIFIER is not supported.
outPinCode.SetValue(CHIP_DEVICE_CONFIG_USE_TEST_SETUP_PIN_CODE);
ChipLogError(NotSpecified,
"*** WARNING: Using temporary passcode %u due to no neither --passcode or --spake2p-verifier-base64 "
"given on command line or factory configuration. This is temporary and will disappear. "
"Please update your scripts to explicitly configure onboarding credentials. ***",
static_cast<unsigned>(outPinCode.Value()));
return CHIP_NO_ERROR;
#endif // CHIP_DEVICE_CONFIG_ENABLE_TEST_SETUP_PARAMS
ChipLogError(NotSpecified, "Unable to initialize commissionable device, no passcode or verifier configured");
return CHIP_DEVICE_ERROR_CONFIG_NOT_FOUND;
}
CHIP_ERROR GetSpake2pSalt(const LinuxDeviceOptions & options, chip::Optional<std::vector<uint8_t>> & outSalt)
{
// Command line options take precedence
if (options.spake2pSalt.HasValue())
{
outSalt = options.spake2pSalt;
return CHIP_NO_ERROR;
}
// Read from PosixConfig. If not set a random salt will be generated by LinuxCommissionableDataProvider.
// Note: CHIP_DEVICE_CONFIG_USE_TEST_SPAKE2P_SALT is no longer supported.
return ReadOptionalConfigValueBin(PosixConfig::kConfigKey_Spake2pSalt, Crypto::kSpake2p_Max_PBKDF_Salt_Length, outSalt);
}
CHIP_ERROR GetIterationCount(const LinuxDeviceOptions & options, uint32_t & outIterationCount)
{
// Command line options take precedence
if (options.spake2pIterations != 0)
{
outIterationCount = options.spake2pIterations;
return CHIP_NO_ERROR;
}
// Read from PosixConfig
CHIP_ERROR err = PosixConfig::ReadConfigValue(PosixConfig::kConfigKey_Spake2pIterationCount, outIterationCount);
VerifyOrReturnError(IsNotFound(err), err);
// CHIP_DEVICE_CONFIG_USE_TEST_SPAKE2P_ITERATION_COUNT is no longer supported, default to minimum PBKDF iterations
outIterationCount = Crypto::kSpake2p_Min_PBKDF_Iterations;
return CHIP_NO_ERROR;
}
CHIP_ERROR GetDiscriminator(const LinuxDeviceOptions & options, uint16_t & outDiscriminator)
{
// Command line options take precedence
if (options.discriminator.HasValue())
{
outDiscriminator = options.discriminator.Value();
return CHIP_NO_ERROR;
}
// Read from PosixConfig
CHIP_ERROR err = PosixConfig::ReadConfigValue(PosixConfig::kConfigKey_SetupDiscriminator, outDiscriminator);
VerifyOrReturnError(IsNotFound(err), err);
#if CHIP_DEVICE_CONFIG_ENABLE_TEST_SETUP_PARAMS
// Fall back to test parameters
outDiscriminator = CHIP_DEVICE_CONFIG_USE_TEST_SETUP_DISCRIMINATOR;
ChipLogError(NotSpecified,
"*** WARNING: Using temporary test discriminator %u due to --discriminator not "
"given on command line or factory configuration. This is temporary and will disappear. "
"Please update your scripts to explicitly configure onboarding credentials. ***",
static_cast<unsigned>(outDiscriminator));
return CHIP_NO_ERROR;
#endif // CHIP_DEVICE_CONFIG_ENABLE_TEST_SETUP_PARAMS
ChipLogError(NotSpecified, "Unable to initialize commissionable device, no discriminator configured");
return CHIP_DEVICE_ERROR_CONFIG_NOT_FOUND;
}
} // namespace
CHIP_ERROR InitCommissionableDataProvider(LinuxCommissionableDataProvider & provider, const LinuxDeviceOptions & options)
{
chip::Optional<uint32_t> setupPasscode;
chip::Optional<std::vector<uint8_t>> spake2pVerifier;
ReturnErrorOnFailure(GetPinCodeAndVerifier(options, setupPasscode, spake2pVerifier));
chip::Optional<std::vector<uint8_t>> spake2pSalt;
ReturnErrorOnFailure(GetSpake2pSalt(options, spake2pSalt));
uint32_t spake2pIterationCount;
ReturnErrorOnFailure(GetIterationCount(options, spake2pIterationCount));
uint16_t discriminator;
ReturnErrorOnFailure(GetDiscriminator(options, discriminator));
return provider.Init(spake2pVerifier, spake2pSalt, spake2pIterationCount, setupPasscode, discriminator);
}
CHIP_ERROR InitConfigurationManager(ConfigurationManagerImpl & configManager, const LinuxDeviceOptions & options)
{
if (options.payload.vendorID != 0)
{
configManager.StoreVendorId(options.payload.vendorID);
}
if (options.payload.productID != 0)
{
configManager.StoreProductId(options.payload.productID);
}
return CHIP_NO_ERROR;
}
} // namespace examples
} // namespace chip