blob: 11995faccd82722df3642684844005825481df89 [file] [log] [blame]
/*
*
* 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.
*/
#include "FactoryDataProvider.h"
#include "CHIPDevicePlatformConfig.h"
#include <crypto/CHIPCryptoPAL.h>
#ifdef CONFIG_CHIP_CERTIFICATION_DECLARATION_STORAGE
#include <credentials/CertificationDeclaration.h>
#include <platform/Zephyr/ZephyrConfig.h>
#endif
#include <zephyr/logging/log.h>
namespace chip {
namespace {
CHIP_ERROR LoadKeypairFromRaw(ByteSpan privateKey, ByteSpan publicKey, Crypto::P256Keypair & keypair)
{
Crypto::P256SerializedKeypair serializedKeypair;
ReturnErrorOnFailure(serializedKeypair.SetLength(privateKey.size() + publicKey.size()));
memcpy(serializedKeypair.Bytes(), publicKey.data(), publicKey.size());
memcpy(serializedKeypair.Bytes() + publicKey.size(), privateKey.data(), privateKey.size());
return keypair.Deserialize(serializedKeypair);
}
CHIP_ERROR GetFactoryDataString(const FactoryDataString & str, char * buf, size_t bufSize)
{
ReturnErrorCodeIf(bufSize < str.len + 1, CHIP_ERROR_BUFFER_TOO_SMALL);
ReturnErrorCodeIf(!str.data, CHIP_ERROR_PERSISTED_STORAGE_VALUE_NOT_FOUND);
memcpy(buf, str.data, str.len);
buf[str.len] = 0;
return CHIP_NO_ERROR;
}
} // namespace
namespace DeviceLayer {
template <class FlashFactoryData>
CHIP_ERROR FactoryDataProvider<FlashFactoryData>::Init()
{
uint8_t * factoryData = nullptr;
size_t factoryDataSize;
CHIP_ERROR error = mFlashFactoryData.ProtectFactoryDataPartitionAgainstWrite();
// Protection against write for external storage is not supported.
if (error == CHIP_ERROR_NOT_IMPLEMENTED)
{
ChipLogProgress(DeviceLayer, "The device does not support hardware protection against write.");
error = CHIP_NO_ERROR;
}
else if (error != CHIP_NO_ERROR)
{
ChipLogError(DeviceLayer, "Failed to protect the factory data partition.");
return error;
}
error = mFlashFactoryData.GetFactoryDataPartition(factoryData, factoryDataSize);
if (error != CHIP_NO_ERROR)
{
ChipLogError(DeviceLayer, "Failed to read factory data partition");
return error;
}
if (!ParseFactoryData(factoryData, static_cast<uint16_t>(factoryDataSize), &mFactoryData))
{
ChipLogError(DeviceLayer, "Failed to parse factory data");
return CHIP_ERROR_PERSISTED_STORAGE_VALUE_NOT_FOUND;
}
// Check if factory data version is correct
if (mFactoryData.version != CONFIG_CHIP_FACTORY_DATA_VERSION)
{
ChipLogError(DeviceLayer, "Factory data version mismatch. Flash version: %d vs code version: %d", mFactoryData.version,
CONFIG_CHIP_FACTORY_DATA_VERSION);
return CHIP_ERROR_VERSION_MISMATCH;
}
return CHIP_NO_ERROR;
}
template <class FlashFactoryData>
CHIP_ERROR FactoryDataProvider<FlashFactoryData>::GetCertificationDeclaration(MutableByteSpan & outBuffer)
{
#ifdef CONFIG_CHIP_CERTIFICATION_DECLARATION_STORAGE
size_t cdLen = 0;
if (Internal::ZephyrConfig::ReadConfigValueBin(Internal::ZephyrConfig::kConfigKey_CertificationDeclaration,
reinterpret_cast<uint8_t *>(outBuffer.data()), outBuffer.size(),
cdLen) == CHIP_NO_ERROR)
{
outBuffer.reduce_size(cdLen);
return CHIP_NO_ERROR;
}
#endif
constexpr uint8_t kCdForAllExamples[] = CHIP_DEVICE_CONFIG_CERTIFICATION_DECLARATION;
return CopySpanToMutableSpan(ByteSpan{ kCdForAllExamples }, outBuffer);
}
template <class FlashFactoryData>
CHIP_ERROR FactoryDataProvider<FlashFactoryData>::GetFirmwareInformation(MutableByteSpan & out_firmware_info_buffer)
{
out_firmware_info_buffer.reduce_size(0);
return CHIP_NO_ERROR;
}
template <class FlashFactoryData>
CHIP_ERROR FactoryDataProvider<FlashFactoryData>::GetDeviceAttestationCert(MutableByteSpan & outBuffer)
{
ReturnErrorCodeIf(outBuffer.size() < mFactoryData.dac_cert.len, CHIP_ERROR_BUFFER_TOO_SMALL);
ReturnErrorCodeIf(!mFactoryData.dac_cert.data, CHIP_ERROR_PERSISTED_STORAGE_VALUE_NOT_FOUND);
memcpy(outBuffer.data(), mFactoryData.dac_cert.data, mFactoryData.dac_cert.len);
outBuffer.reduce_size(mFactoryData.dac_cert.len);
return CHIP_NO_ERROR;
}
template <class FlashFactoryData>
CHIP_ERROR FactoryDataProvider<FlashFactoryData>::GetProductAttestationIntermediateCert(MutableByteSpan & outBuffer)
{
ReturnErrorCodeIf(outBuffer.size() < mFactoryData.pai_cert.len, CHIP_ERROR_BUFFER_TOO_SMALL);
ReturnErrorCodeIf(!mFactoryData.pai_cert.data, CHIP_ERROR_PERSISTED_STORAGE_VALUE_NOT_FOUND);
memcpy(outBuffer.data(), mFactoryData.pai_cert.data, mFactoryData.pai_cert.len);
outBuffer.reduce_size(mFactoryData.pai_cert.len);
return CHIP_NO_ERROR;
}
template <class FlashFactoryData>
CHIP_ERROR FactoryDataProvider<FlashFactoryData>::SignWithDeviceAttestationKey(const ByteSpan & messageToSign,
MutableByteSpan & outSignBuffer)
{
Crypto::P256ECDSASignature signature;
Crypto::P256Keypair keypair;
CHIP_ERROR err = CHIP_NO_ERROR;
#ifdef CONFIG_CHIP_CRYPTO_PSA
psa_key_id_t keyId = 0;
#endif
VerifyOrExit(outSignBuffer.size() >= signature.Capacity(), err = CHIP_ERROR_BUFFER_TOO_SMALL);
VerifyOrExit(mFactoryData.dac_cert.data, err = CHIP_ERROR_PERSISTED_STORAGE_VALUE_NOT_FOUND);
VerifyOrExit(mFactoryData.dac_priv_key.data, err = CHIP_ERROR_PERSISTED_STORAGE_VALUE_NOT_FOUND);
#ifdef CONFIG_CHIP_CRYPTO_PSA
{
psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
psa_reset_key_attributes(&attributes);
psa_set_key_type(&attributes, PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_FAMILY_SECP_R1));
psa_set_key_bits(&attributes, kDACPrivateKeyLength * 8);
psa_set_key_algorithm(&attributes, PSA_ALG_ECDSA(PSA_ALG_SHA_256));
psa_set_key_usage_flags(&attributes, PSA_KEY_USAGE_SIGN_MESSAGE);
VerifyOrExit(psa_import_key(&attributes, reinterpret_cast<uint8_t *>(mFactoryData.dac_priv_key.data), kDACPrivateKeyLength,
&keyId) == PSA_SUCCESS,
err = CHIP_ERROR_INTERNAL);
size_t outputLen = 0;
psa_status_t status = psa_sign_message(keyId, PSA_ALG_ECDSA(PSA_ALG_SHA_256), messageToSign.data(), messageToSign.size(),
signature.Bytes(), signature.Capacity(), &outputLen);
VerifyOrExit(!status, err = CHIP_ERROR_INTERNAL);
VerifyOrExit(outputLen == chip::Crypto::kP256_ECDSA_Signature_Length_Raw, err = CHIP_ERROR_INTERNAL);
err = signature.SetLength(outputLen);
VerifyOrExit(err == CHIP_NO_ERROR, );
}
#else
{
// Extract public key from DAC cert.
ByteSpan dacCertSpan{ reinterpret_cast<uint8_t *>(mFactoryData.dac_cert.data), mFactoryData.dac_cert.len };
chip::Crypto::P256PublicKey dacPublicKey;
err = chip::Crypto::ExtractPubkeyFromX509Cert(dacCertSpan, dacPublicKey);
VerifyOrExit(err == CHIP_NO_ERROR, );
err =
LoadKeypairFromRaw(ByteSpan(reinterpret_cast<uint8_t *>(mFactoryData.dac_priv_key.data), mFactoryData.dac_priv_key.len),
ByteSpan(dacPublicKey.Bytes(), dacPublicKey.Length()), keypair);
VerifyOrExit(err == CHIP_NO_ERROR, );
err = keypair.ECDSA_sign_msg(messageToSign.data(), messageToSign.size(), signature);
VerifyOrExit(err == CHIP_NO_ERROR, );
}
#endif
exit:
#ifdef CONFIG_CHIP_CRYPTO_PSA
psa_destroy_key(keyId);
#endif
if (err != CHIP_NO_ERROR)
{
return err;
}
return CopySpanToMutableSpan(ByteSpan{ signature.ConstBytes(), signature.Length() }, outSignBuffer);
}
template <class FlashFactoryData>
CHIP_ERROR FactoryDataProvider<FlashFactoryData>::GetSetupDiscriminator(uint16_t & setupDiscriminator)
{
VerifyOrReturnError(mFactoryData.discriminatorPresent, CHIP_ERROR_PERSISTED_STORAGE_VALUE_NOT_FOUND);
setupDiscriminator = mFactoryData.discriminator;
return CHIP_NO_ERROR;
}
template <class FlashFactoryData>
CHIP_ERROR FactoryDataProvider<FlashFactoryData>::SetSetupDiscriminator(uint16_t setupDiscriminator)
{
return CHIP_ERROR_NOT_IMPLEMENTED;
}
template <class FlashFactoryData>
CHIP_ERROR FactoryDataProvider<FlashFactoryData>::GetSpake2pIterationCount(uint32_t & iterationCount)
{
ReturnErrorCodeIf(mFactoryData.spake2_it == 0, CHIP_ERROR_PERSISTED_STORAGE_VALUE_NOT_FOUND);
iterationCount = mFactoryData.spake2_it;
return CHIP_NO_ERROR;
}
template <class FlashFactoryData>
CHIP_ERROR FactoryDataProvider<FlashFactoryData>::GetSpake2pSalt(MutableByteSpan & saltBuf)
{
ReturnErrorCodeIf(saltBuf.size() < mFactoryData.spake2_salt.len, CHIP_ERROR_BUFFER_TOO_SMALL);
ReturnErrorCodeIf(!mFactoryData.spake2_salt.data, CHIP_ERROR_PERSISTED_STORAGE_VALUE_NOT_FOUND);
memcpy(saltBuf.data(), mFactoryData.spake2_salt.data, mFactoryData.spake2_salt.len);
saltBuf.reduce_size(mFactoryData.spake2_salt.len);
return CHIP_NO_ERROR;
}
template <class FlashFactoryData>
CHIP_ERROR FactoryDataProvider<FlashFactoryData>::GetSpake2pVerifier(MutableByteSpan & verifierBuf, size_t & verifierLen)
{
ReturnErrorCodeIf(verifierBuf.size() < mFactoryData.spake2_verifier.len, CHIP_ERROR_BUFFER_TOO_SMALL);
ReturnErrorCodeIf(!mFactoryData.spake2_verifier.data, CHIP_ERROR_PERSISTED_STORAGE_VALUE_NOT_FOUND);
memcpy(verifierBuf.data(), mFactoryData.spake2_verifier.data, mFactoryData.spake2_verifier.len);
verifierLen = mFactoryData.spake2_verifier.len;
verifierBuf.reduce_size(verifierLen);
return CHIP_NO_ERROR;
}
template <class FlashFactoryData>
CHIP_ERROR FactoryDataProvider<FlashFactoryData>::GetSetupPasscode(uint32_t & setupPasscode)
{
ReturnErrorCodeIf(mFactoryData.passcode == 0, CHIP_ERROR_PERSISTED_STORAGE_VALUE_NOT_FOUND);
setupPasscode = mFactoryData.passcode;
return CHIP_NO_ERROR;
}
template <class FlashFactoryData>
CHIP_ERROR FactoryDataProvider<FlashFactoryData>::SetSetupPasscode(uint32_t setupPasscode)
{
return CHIP_ERROR_NOT_IMPLEMENTED;
}
template <class FlashFactoryData>
CHIP_ERROR FactoryDataProvider<FlashFactoryData>::GetVendorName(char * buf, size_t bufSize)
{
return GetFactoryDataString(mFactoryData.vendor_name, buf, bufSize);
}
template <class FlashFactoryData>
CHIP_ERROR FactoryDataProvider<FlashFactoryData>::GetVendorId(uint16_t & vendorId)
{
VerifyOrReturnError(mFactoryData.vendorIdPresent, CHIP_ERROR_PERSISTED_STORAGE_VALUE_NOT_FOUND);
vendorId = mFactoryData.vendor_id;
return CHIP_NO_ERROR;
}
template <class FlashFactoryData>
CHIP_ERROR FactoryDataProvider<FlashFactoryData>::GetProductName(char * buf, size_t bufSize)
{
return GetFactoryDataString(mFactoryData.product_name, buf, bufSize);
}
template <class FlashFactoryData>
CHIP_ERROR FactoryDataProvider<FlashFactoryData>::GetProductId(uint16_t & productId)
{
VerifyOrReturnError(mFactoryData.productIdPresent, CHIP_ERROR_PERSISTED_STORAGE_VALUE_NOT_FOUND);
productId = mFactoryData.product_id;
return CHIP_NO_ERROR;
}
template <class FlashFactoryData>
CHIP_ERROR FactoryDataProvider<FlashFactoryData>::GetPartNumber(char * buf, size_t bufSize)
{
return GetFactoryDataString(mFactoryData.part_number, buf, bufSize);
}
template <class FlashFactoryData>
CHIP_ERROR FactoryDataProvider<FlashFactoryData>::GetProductURL(char * buf, size_t bufSize)
{
return GetFactoryDataString(mFactoryData.product_url, buf, bufSize);
}
template <class FlashFactoryData>
CHIP_ERROR FactoryDataProvider<FlashFactoryData>::GetProductLabel(char * buf, size_t bufSize)
{
return GetFactoryDataString(mFactoryData.product_label, buf, bufSize);
}
template <class FlashFactoryData>
CHIP_ERROR FactoryDataProvider<FlashFactoryData>::GetSerialNumber(char * buf, size_t bufSize)
{
return GetFactoryDataString(mFactoryData.sn, buf, bufSize);
}
template <class FlashFactoryData>
CHIP_ERROR FactoryDataProvider<FlashFactoryData>::GetManufacturingDate(uint16_t & year, uint8_t & month, uint8_t & day)
{
VerifyOrReturnError(mFactoryData.date_year != 0, CHIP_ERROR_PERSISTED_STORAGE_VALUE_NOT_FOUND);
year = mFactoryData.date_year;
month = mFactoryData.date_month;
day = mFactoryData.date_day;
return CHIP_NO_ERROR;
}
template <class FlashFactoryData>
CHIP_ERROR FactoryDataProvider<FlashFactoryData>::GetHardwareVersion(uint16_t & hardwareVersion)
{
VerifyOrReturnError(mFactoryData.hwVerPresent, CHIP_ERROR_PERSISTED_STORAGE_VALUE_NOT_FOUND);
hardwareVersion = mFactoryData.hw_ver;
return CHIP_NO_ERROR;
}
template <class FlashFactoryData>
CHIP_ERROR FactoryDataProvider<FlashFactoryData>::GetHardwareVersionString(char * buf, size_t bufSize)
{
return GetFactoryDataString(mFactoryData.hw_ver_str, buf, bufSize);
}
template <class FlashFactoryData>
CHIP_ERROR FactoryDataProvider<FlashFactoryData>::GetRotatingDeviceIdUniqueId(MutableByteSpan & uniqueIdSpan)
{
ReturnErrorCodeIf(uniqueIdSpan.size() < mFactoryData.rd_uid.len, CHIP_ERROR_BUFFER_TOO_SMALL);
ReturnErrorCodeIf(!mFactoryData.rd_uid.data, CHIP_ERROR_PERSISTED_STORAGE_VALUE_NOT_FOUND);
memcpy(uniqueIdSpan.data(), mFactoryData.rd_uid.data, mFactoryData.rd_uid.len);
uniqueIdSpan.reduce_size(mFactoryData.rd_uid.len);
return CHIP_NO_ERROR;
}
template <class FlashFactoryData>
CHIP_ERROR FactoryDataProvider<FlashFactoryData>::GetEnableKey(MutableByteSpan & enableKey)
{
ReturnErrorCodeIf(!mFactoryData.enable_key.data, CHIP_ERROR_PERSISTED_STORAGE_VALUE_NOT_FOUND);
ReturnErrorCodeIf(enableKey.size() < mFactoryData.enable_key.len, CHIP_ERROR_BUFFER_TOO_SMALL);
memcpy(enableKey.data(), mFactoryData.enable_key.data, mFactoryData.enable_key.len);
enableKey.reduce_size(mFactoryData.enable_key.len);
return CHIP_NO_ERROR;
}
template <class FlashFactoryData>
CHIP_ERROR FactoryDataProvider<FlashFactoryData>::GetProductFinish(app::Clusters::BasicInformation::ProductFinishEnum * finish)
{
ReturnErrorCodeIf(!finish, CHIP_ERROR_INVALID_ARGUMENT);
ReturnErrorCodeIf(!mFactoryData.productFinishPresent, CHIP_ERROR_NOT_IMPLEMENTED);
*finish = static_cast<app::Clusters::BasicInformation::ProductFinishEnum>(mFactoryData.product_finish);
return CHIP_NO_ERROR;
}
template <class FlashFactoryData>
CHIP_ERROR FactoryDataProvider<FlashFactoryData>::GetProductPrimaryColor(app::Clusters::BasicInformation::ColorEnum * primaryColor)
{
ReturnErrorCodeIf(!primaryColor, CHIP_ERROR_INVALID_ARGUMENT);
ReturnErrorCodeIf(!mFactoryData.primaryColorPresent, CHIP_ERROR_NOT_IMPLEMENTED);
*primaryColor = static_cast<app::Clusters::BasicInformation::ColorEnum>(mFactoryData.primary_color);
return CHIP_NO_ERROR;
}
template <class FlashFactoryData>
CHIP_ERROR FactoryDataProvider<FlashFactoryData>::GetUserData(MutableByteSpan & userData)
{
ReturnErrorCodeIf(!mFactoryData.user.data, CHIP_ERROR_PERSISTED_STORAGE_VALUE_NOT_FOUND);
ReturnErrorCodeIf(userData.size() < mFactoryData.user.len, CHIP_ERROR_BUFFER_TOO_SMALL);
memcpy(userData.data(), mFactoryData.user.data, mFactoryData.user.len);
userData.reduce_size(mFactoryData.user.len);
return CHIP_NO_ERROR;
}
template <class FlashFactoryData>
CHIP_ERROR FactoryDataProvider<FlashFactoryData>::GetUserKey(const char * userKey, void * buf, size_t & len)
{
ReturnErrorCodeIf(!mFactoryData.user.data, CHIP_ERROR_PERSISTED_STORAGE_VALUE_NOT_FOUND);
ReturnErrorCodeIf(!buf, CHIP_ERROR_BUFFER_TOO_SMALL);
bool success = FindUserDataEntry(&mFactoryData, userKey, buf, len, &len);
ReturnErrorCodeIf(!success, CHIP_ERROR_PERSISTED_STORAGE_VALUE_NOT_FOUND);
return CHIP_NO_ERROR;
}
// Fully instantiate the template class in whatever compilation unit includes this file.
template class FactoryDataProvider<InternalFlashFactoryData>;
template class FactoryDataProvider<ExternalFlashFactoryData>;
} // namespace DeviceLayer
} // namespace chip