/* * * Copyright (c) 2023 Project CHIP Authors * Copyright 2023 NXP * * 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 "FactoryDataProviderFwkImpl.h" #include "fwk_factory_data_provider.h" namespace chip { namespace DeviceLayer { FactoryDataProviderImpl FactoryDataProviderImpl::sInstance; CHIP_ERROR FactoryDataProviderImpl::SearchForId(uint8_t searchedType, uint8_t * pBuf, size_t bufLength, uint16_t & length, uint32_t * contentAddr) { CHIP_ERROR err = CHIP_ERROR_NOT_FOUND; uint32_t readLen = 0; uint8_t * ramBufferAddr = FDP_SearchForId(searchedType, pBuf, bufLength, &readLen); if (ramBufferAddr != NULL) { if (contentAddr != NULL) *contentAddr = (uint32_t) ramBufferAddr; err = CHIP_NO_ERROR; } length = readLen; return err; } CHIP_ERROR FactoryDataProviderImpl::SignWithDacKey(const ByteSpan & digestToSign, MutableByteSpan & outSignBuffer) { Crypto::P256ECDSASignature signature; Crypto::P256Keypair keypair; VerifyOrReturnError(IsSpanUsable(outSignBuffer), CHIP_ERROR_INVALID_ARGUMENT); VerifyOrReturnError(IsSpanUsable(digestToSign), CHIP_ERROR_INVALID_ARGUMENT); VerifyOrReturnError(outSignBuffer.size() >= signature.Capacity(), CHIP_ERROR_BUFFER_TOO_SMALL); // In a non-exemplary implementation, the public key is not needed here. It is used here merely because // Crypto::P256Keypair is only (currently) constructable from raw keys if both private/public keys are present. Crypto::P256PublicKey dacPublicKey; uint16_t certificateSize = 0; uint32_t certificateAddr; ReturnErrorOnFailure(SearchForId(FactoryDataId::kDacCertificateId, NULL, 0, certificateSize, &certificateAddr)); MutableByteSpan dacCertSpan((uint8_t *) certificateAddr, certificateSize); /* Extract Public Key of DAC certificate from itself */ ReturnErrorOnFailure(Crypto::ExtractPubkeyFromX509Cert(dacCertSpan, dacPublicKey)); /* Get private key of DAC certificate from reserved section */ uint16_t keySize = 0; uint32_t keyAddr; ReturnErrorOnFailure(SearchForId(FactoryDataId::kDacPrivateKeyId, NULL, 0, keySize, &keyAddr)); MutableByteSpan dacPrivateKeySpan((uint8_t *) keyAddr, keySize); ReturnErrorOnFailure(LoadKeypairFromRaw(ByteSpan(dacPrivateKeySpan.data(), dacPrivateKeySpan.size()), ByteSpan(dacPublicKey.Bytes(), dacPublicKey.Length()), keypair)); ReturnErrorOnFailure(keypair.ECDSA_sign_msg(digestToSign.data(), digestToSign.size(), signature)); return CopySpanToMutableSpan(ByteSpan{ signature.ConstBytes(), signature.Length() }, outSignBuffer); } CHIP_ERROR FactoryDataProviderImpl::LoadKeypairFromRaw(ByteSpan privateKey, ByteSpan publicKey, Crypto::P256Keypair & keypair) { Crypto::P256SerializedKeypair serialized_keypair; ReturnErrorOnFailure(serialized_keypair.SetLength(privateKey.size() + publicKey.size())); memcpy(serialized_keypair.Bytes(), publicKey.data(), publicKey.size()); memcpy(serialized_keypair.Bytes() + publicKey.size(), privateKey.data(), privateKey.size()); return keypair.Deserialize(serialized_keypair); } CHIP_ERROR FactoryDataProviderImpl::Init(void) { /* * Currently the fwk_factory_data_provider module supports only ecb mode. * Therefore return an error if encrypt mode is not ecb */ if (pAesKey == NULL || encryptMode != encrypt_ecb) { return CHIP_ERROR_INVALID_ARGUMENT; } if (FDP_Init(pAesKey) < 0) { return CHIP_ERROR_INTERNAL; } return CHIP_NO_ERROR; } CHIP_ERROR FactoryDataProviderImpl::SetAes128Key(const uint8_t * keyAes128) { CHIP_ERROR error = CHIP_ERROR_INVALID_ARGUMENT; if (keyAes128 != nullptr) { pAesKey = keyAes128; error = CHIP_NO_ERROR; } return error; } CHIP_ERROR FactoryDataProviderImpl::SetEncryptionMode(EncryptionMode mode) { CHIP_ERROR error = CHIP_ERROR_INVALID_ARGUMENT; /* * Currently the fwk_factory_data_provider module supports only ecb mode. * Therefore return an error if encrypt mode is not ecb */ if (mode == encrypt_ecb) { encryptMode = mode; error = CHIP_NO_ERROR; } return error; } } // namespace DeviceLayer } // namespace chip