diff --git a/src/crypto/PSAOperationalKeystore.cpp b/src/crypto/PSAOperationalKeystore.cpp index 275fd5b247..f1006489b3 100644 --- a/src/crypto/PSAOperationalKeystore.cpp +++ b/src/crypto/PSAOperationalKeystore.cpp @@ -39,7 +39,7 @@ PSAOperationalKeystore::PersistentP256Keypair::~PersistentP256Keypair() ToPsaContext(mKeypair).key_id = 0; } -inline psa_key_id_t PSAOperationalKeystore::PersistentP256Keypair::GetKeyId() const +psa_key_id_t PSAOperationalKeystore::PersistentP256Keypair::GetKeyId() const { return ToConstPsaContext(mKeypair).key_id; } @@ -68,6 +68,8 @@ CHIP_ERROR PSAOperationalKeystore::PersistentP256Keypair::Generate() psa_set_key_algorithm(&attributes, PSA_ALG_ECDSA(PSA_ALG_SHA_256)); psa_set_key_usage_flags(&attributes, PSA_KEY_USAGE_SIGN_MESSAGE | PSA_KEY_USAGE_COPY); + GetPSAKeyAllocator().UpdateKeyAttributes(attributes); + status = psa_generate_key(&attributes, &keyId); VerifyOrExit(status == PSA_SUCCESS, error = CHIP_ERROR_INTERNAL); diff --git a/src/crypto/PSAOperationalKeystore.h b/src/crypto/PSAOperationalKeystore.h index b61927b617..35dcf90022 100644 --- a/src/crypto/PSAOperationalKeystore.h +++ b/src/crypto/PSAOperationalKeystore.h @@ -24,7 +24,7 @@ namespace chip { namespace Crypto { -class PSAOperationalKeystore final : public OperationalKeystore +class PSAOperationalKeystore : public OperationalKeystore { public: bool HasPendingOpKeypair() const override; diff --git a/src/platform/nrfconnect/BUILD.gn b/src/platform/nrfconnect/BUILD.gn index 8389219c13..d7c4c7fe11 100644 --- a/src/platform/nrfconnect/BUILD.gn +++ b/src/platform/nrfconnect/BUILD.gn @@ -140,6 +140,7 @@ static_library("nrfconnect") { if (chip_use_cracen_kmu) { sources += [ "KMUKeyAllocator.h", + "KMUOperationalKeystore.h", "KMUSessionKeystore.h", ] } diff --git a/src/platform/nrfconnect/KMUKeyAllocator.h b/src/platform/nrfconnect/KMUKeyAllocator.h index 12b77d614a..2016cfd6be 100644 --- a/src/platform/nrfconnect/KMUKeyAllocator.h +++ b/src/platform/nrfconnect/KMUKeyAllocator.h @@ -32,7 +32,7 @@ CONFIG_CHIP_KMU_SLOT_RANGE_END - CONFIG_CHIP_KMU_SLOT_RANGE_START) { #pragma message("NOC keys: " STRINGIFY(KMU_SLOTS_NOC_MAX_NUMBER) "+ ICD keys: " STRINGIFY( \ - KMU_SLOTS_ICD_MAX_NUMBER) "+ GROUP keys: " STRINGIFY(KMU_SLOTS_GROUP_MAX_NUMBER) ">" STRINGIFY(KMU_AVAILABLE_MATTER_SLOTS)) + KMU_SLOTS_ICD_MAX_NUMBER) "+ GROUP keys: " STRINGIFY(KMU_SLOTS_GROUP_MAX_NUMBER) ">" STRINGIFY(KMU_AVAILABLE_MATTER_SLOTS)) #error \ "The number of slots exceeds the range of the KMU defined in CONFIG_CHIP_KMU_SLOT_RANGE_START and CONFIG_CHIP_KMU_SLOT_RANGE_END" } @@ -91,6 +91,7 @@ class KMUKeyAllocator : public chip::Crypto::PSAKeyAllocator if (psa_get_key_algorithm(&attrs) == PSA_ALG_ECDSA(PSA_ALG_SHA_256)) { psa_set_key_algorithm(&attrs, PSA_ALG_ECDSA(PSA_ALG_ANY_HASH)); + psa_set_key_usage_flags(&attrs, psa_get_key_usage_flags(&attrs) | PSA_KEY_USAGE_EXPORT); } // TODO: Change PSA_ALG_AEAD_WITH_AT_LEAST_THIS_LENGTH_TAG(PSA_ALG_CCM, 8) to PSA_ALG_CCM diff --git a/src/platform/nrfconnect/KMUOperationalKeystore.h b/src/platform/nrfconnect/KMUOperationalKeystore.h new file mode 100644 index 0000000000..d25dc29b33 --- /dev/null +++ b/src/platform/nrfconnect/KMUOperationalKeystore.h @@ -0,0 +1,76 @@ +/* + * Copyright (c) 2025 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. + */ + +#pragma once + +#include "KMUKeyAllocator.h" +#include + +namespace chip { +namespace DeviceLayer { + +class KMUOperationalKeystore : public chip::Crypto::PSAOperationalKeystore +{ +public: + CHIP_ERROR CommitOpKeypairForFabric(FabricIndex fabricIndex) override + { + VerifyOrReturnError(IsValidFabricIndex(fabricIndex) && mPendingFabricIndex == fabricIndex, CHIP_ERROR_INVALID_FABRIC_INDEX); + VerifyOrReturnError(mIsPendingKeypairActive, CHIP_ERROR_INCORRECT_STATE); + + psa_status_t status = PSA_SUCCESS; + CHIP_ERROR error = CHIP_NO_ERROR; + psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT; + psa_key_id_t keyId = 0; + uint8_t keyEx[chip::Crypto::kP256_FE_Length]; + size_t keyExSize = sizeof(keyEx); + + PersistentP256Keypair keyPairToCommit(fabricIndex); + + psa_destroy_key(keyPairToCommit.GetKeyId()); + + // We cannot use psa_copy_key here because the source and target keys are stored in different locations. + // Instead we need to export this key and import once again. + status = psa_export_key(mPendingKeypair->GetKeyId(), keyEx, sizeof(keyEx), &keyExSize); + VerifyOrExit(status == PSA_SUCCESS, error = CHIP_ERROR_INTERNAL); + + // Switch to the persistent key + 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, chip::Crypto::kP256_PrivateKey_Length * 8); + psa_set_key_algorithm(&attributes, PSA_ALG_ECDSA(PSA_ALG_SHA_256)); + psa_set_key_usage_flags(&attributes, PSA_KEY_USAGE_SIGN_MESSAGE); + psa_set_key_lifetime(&attributes, PSA_KEY_LIFETIME_PERSISTENT); + psa_set_key_id(&attributes, keyPairToCommit.GetKeyId()); + + status = psa_import_key(&attributes, keyEx, keyExSize, &keyId); + VerifyOrExit(status == PSA_SUCCESS, error = CHIP_ERROR_INTERNAL); + VerifyOrExit(keyId == keyPairToCommit.GetKeyId(), error = CHIP_ERROR_INTERNAL); + + // Copied was done, so we can revert the pending keypair + RevertPendingKeypair(); + + exit: + chip::Crypto::LogPsaError(status); + psa_reset_key_attributes(&attributes); + memset(keyEx, 0, sizeof(keyEx)); + + return error; + } +}; + +} // namespace DeviceLayer +} // namespace chip