| /* |
| * |
| * 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 |