blob: dc6acd3b619272297e4b0820109ffb67c1705158 [file] [log] [blame]
/*
*
* Copyright (c) 2023 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 <crypto/CHIPCryptoPAL.h>
#include <lib/core/CHIPError.h>
#include <platform/nxp/k32w/k32w0/FactoryDataProviderImpl.h>
#if CONFIG_CHIP_K32W0_OTA_FACTORY_DATA_PROCESSOR
extern "C" {
#include "Flash_Adapter.h"
}
extern "C" WEAK CHIP_ERROR FactoryDataDefaultRestoreMechanism();
#endif
namespace chip {
namespace DeviceLayer {
FactoryDataProviderImpl::FactoryDataProviderImpl()
{
#if CONFIG_CHIP_K32W0_OTA_FACTORY_DATA_PROCESSOR
RegisterRestoreMechanism(FactoryDataDefaultRestoreMechanism);
#endif
}
CHIP_ERROR FactoryDataProviderImpl::Init()
{
CHIP_ERROR error = CHIP_NO_ERROR;
#if CONFIG_CHIP_K32W0_OTA_FACTORY_DATA_PROCESSOR
error = ValidateWithRestore();
#else
error = Validate();
#endif
if (error != CHIP_NO_ERROR)
{
ChipLogError(DeviceLayer, "Factory data init failed with: %s", ErrorStr(error));
}
return error;
}
CHIP_ERROR FactoryDataProviderImpl::SignWithDacKey(const ByteSpan & messageToSign, MutableByteSpan & outSignBuffer)
{
CHIP_ERROR error = CHIP_NO_ERROR;
Crypto::P256ECDSASignature signature;
Crypto::P256Keypair keypair;
Crypto::P256SerializedKeypair serializedKeypair;
uint8_t keyBuf[Crypto::kP256_PrivateKey_Length];
MutableByteSpan dacPrivateKeySpan(keyBuf);
uint16_t keySize = 0;
VerifyOrExit(!outSignBuffer.empty(), error = CHIP_ERROR_INVALID_ARGUMENT);
VerifyOrExit(!messageToSign.empty(), error = CHIP_ERROR_INVALID_ARGUMENT);
VerifyOrExit(outSignBuffer.size() >= signature.Capacity(), error = CHIP_ERROR_BUFFER_TOO_SMALL);
/* Get private key of DAC certificate from reserved section */
error = SearchForId(FactoryDataId::kDacPrivateKeyId, dacPrivateKeySpan.data(), dacPrivateKeySpan.size(), keySize);
SuccessOrExit(error);
dacPrivateKeySpan.reduce_size(keySize);
/* Only the private key is used when signing */
error = serializedKeypair.SetLength(Crypto::kP256_PublicKey_Length + dacPrivateKeySpan.size());
SuccessOrExit(error);
memcpy(serializedKeypair.Bytes() + Crypto::kP256_PublicKey_Length, dacPrivateKeySpan.data(), dacPrivateKeySpan.size());
error = keypair.Deserialize(serializedKeypair);
SuccessOrExit(error);
error = keypair.ECDSA_sign_msg(messageToSign.data(), messageToSign.size(), signature);
SuccessOrExit(error);
error = CopySpanToMutableSpan(ByteSpan{ signature.ConstBytes(), signature.Length() }, outSignBuffer);
exit:
/* Sanitize temporary buffer */
memset(keyBuf, 0, Crypto::kP256_PrivateKey_Length);
return error;
}
#if CONFIG_CHIP_K32W0_OTA_FACTORY_DATA_PROCESSOR
extern "C" WEAK CHIP_ERROR FactoryDataDefaultRestoreMechanism()
{
CHIP_ERROR error = CHIP_NO_ERROR;
uint16_t backupLength = 0;
// Check if PDM id related to factory data backup exists.
// If it does, it means an external event (such as a power loss)
// interrupted the factory data update process and the section
// from internal flash is most likely erased and should be restored.
if (PDM_bDoesDataExist(kNvmId_FactoryDataBackup, &backupLength))
{
chip::Platform::ScopedMemoryBuffer<uint8_t> buffer;
buffer.Calloc(FactoryDataProvider::kFactoryDataSize);
ReturnErrorCodeIf(buffer.Get() == nullptr, CHIP_ERROR_NO_MEMORY);
auto status = PDM_eReadDataFromRecord(kNvmId_FactoryDataBackup, (void *) buffer.Get(),
FactoryDataProvider::kFactoryDataSize, &backupLength);
ReturnErrorCodeIf(PDM_E_STATUS_OK != status, CHIP_FACTORY_DATA_PDM_RESTORE);
error = FactoryDataProviderImpl::UpdateData(buffer.Get());
if (error == CHIP_NO_ERROR)
{
ChipLogProgress(DeviceLayer, "Factory data was restored successfully");
}
}
return error;
}
CHIP_ERROR FactoryDataProviderImpl::ValidateWithRestore()
{
CHIP_ERROR error = CHIP_NO_ERROR;
VerifyOrReturnError(mRestoreMechanisms.size() > 0, CHIP_FACTORY_DATA_RESTORE_MECHANISM);
for (auto & restore : mRestoreMechanisms)
{
error = restore();
if (error != CHIP_NO_ERROR)
{
continue;
}
error = Validate();
if (error != CHIP_NO_ERROR)
{
continue;
}
break;
}
if (error == CHIP_NO_ERROR)
{
PDM_vDeleteDataRecord(kNvmId_FactoryDataBackup);
}
return error;
}
CHIP_ERROR FactoryDataProviderImpl::UpdateData(uint8_t * pBuf)
{
NV_Init();
auto status = NV_FlashEraseSector(kFactoryDataStart, kFactoryDataSize);
ReturnErrorCodeIf(status != kStatus_FLASH_Success, CHIP_FACTORY_DATA_FLASH_ERASE);
Header * header = (Header *) pBuf;
status = NV_FlashProgramUnaligned(kFactoryDataStart, sizeof(Header) + header->size, pBuf);
ReturnErrorCodeIf(status != kStatus_FLASH_Success, CHIP_FACTORY_DATA_FLASH_PROGRAM);
return CHIP_NO_ERROR;
}
void FactoryDataProviderImpl::RegisterRestoreMechanism(RestoreMechanism restore)
{
mRestoreMechanisms.insert(mRestoreMechanisms.end(), restore);
}
#endif // CONFIG_CHIP_K32W0_OTA_FACTORY_DATA_PROCESSOR
} // namespace DeviceLayer
} // namespace chip