-
Notifications
You must be signed in to change notification settings - Fork 60
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
[nrfconnect] Add platform crypto for KMU usage
Added a platform crypto implementation to store crypto materials in KMU(Key management unit) for devices that use it.
- Loading branch information
1 parent
29a63e3
commit a35590d
Showing
10 changed files
with
436 additions
and
5 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
138 changes: 138 additions & 0 deletions
138
src/platform/nrfconnect/crypto/KMUOperationalKeystore.cpp
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,138 @@ | ||
/* | ||
* 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. | ||
*/ | ||
|
||
#include "KMUOperationalKeystore.h" | ||
#include "KMUSlotDefinitions.h" | ||
|
||
#include <lib/support/CHIPMem.h> | ||
|
||
#include <cracen_psa_kmu.h> | ||
#include <psa/crypto.h> | ||
|
||
namespace chip { | ||
namespace Crypto { | ||
|
||
KMUOperationalKeystore::KMUPersistentP256Keypair::KMUPersistentP256Keypair(FabricIndex fabricIndex) : | ||
PSAOperationalKeystore::PersistentP256Keypair(0) | ||
{ | ||
if (IsValidFabricIndex(fabricIndex)) | ||
{ | ||
// Decrease fabricIndex by 1 to match the 0-based index used by the KMU slot definitions. | ||
ToPsaContext(mKeypair).key_id = | ||
static_cast<psa_key_id_t>(KMU_MATTER_NOC_SLOT_START + ((fabricIndex - 1) * KMU_MATTER_SLOTS_PER_NOC_KEY)); | ||
|
||
mInitialized = true; | ||
} | ||
} | ||
|
||
KMUOperationalKeystore::KMUPersistentP256Keypair::~KMUPersistentP256Keypair() | ||
{ | ||
// This class requires explicit control of the key lifetime. Therefore, clear the key ID | ||
// to prevent it from being destroyed by the base class destructor. | ||
ToPsaContext(mKeypair).key_id = 0; | ||
} | ||
|
||
CHIP_ERROR KMUOperationalKeystore::NewOpKeypairForFabric(FabricIndex fabricIndex, MutableByteSpan & outCertificateSigningRequest) | ||
{ | ||
VerifyOrReturnError(IsValidFabricIndex(fabricIndex), CHIP_ERROR_INVALID_FABRIC_INDEX); | ||
|
||
if (HasPendingOpKeypair()) | ||
{ | ||
VerifyOrReturnError(fabricIndex == mPendingFabricIndex, CHIP_ERROR_INVALID_FABRIC_INDEX); | ||
} | ||
|
||
if (mPendingKeypair == nullptr) | ||
{ | ||
mPendingKeypair = Platform::New<PersistentP256Keypair>(fabricIndex); | ||
} | ||
|
||
VerifyOrReturnError(mPendingKeypair != nullptr, CHIP_ERROR_NO_MEMORY); | ||
ReturnErrorOnFailure(mPendingKeypair->Generate()); | ||
|
||
size_t csrLength = outCertificateSigningRequest.size(); | ||
ReturnErrorOnFailure(mPendingKeypair->NewCertificateSigningRequest(outCertificateSigningRequest.data(), csrLength)); | ||
outCertificateSigningRequest.reduce_size(csrLength); | ||
mPendingFabricIndex = fabricIndex; | ||
|
||
return CHIP_NO_ERROR; | ||
} | ||
|
||
CHIP_ERROR KMUOperationalKeystore::KMUPersistentP256Keypair::Deserialize(P256SerializedKeypair & input) | ||
{ | ||
CHIP_ERROR error = CHIP_NO_ERROR; | ||
psa_status_t status = PSA_SUCCESS; | ||
psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT; | ||
psa_key_id_t keyId = 0; | ||
VerifyOrReturnError(input.Length() == mPublicKey.Length() + kP256_PrivateKey_Length, CHIP_ERROR_INVALID_ARGUMENT); | ||
|
||
Destroy(); | ||
|
||
// Type based on ECC with the elliptic curve SECP256r1 -> PSA_ECC_FAMILY_SECP_R1 | ||
psa_set_key_type(&attributes, PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_FAMILY_SECP_R1)); | ||
psa_set_key_bits(&attributes, kP256_PrivateKey_Length * 8); | ||
psa_set_key_algorithm(&attributes, PSA_ALG_ECDSA(PSA_ALG_ANY_HASH)); | ||
psa_set_key_usage_flags(&attributes, PSA_KEY_USAGE_SIGN_MESSAGE); | ||
psa_set_key_lifetime(&attributes, | ||
PSA_KEY_LIFETIME_FROM_PERSISTENCE_AND_LOCATION(PSA_KEY_PERSISTENCE_DEFAULT, PSA_KEY_LOCATION_CRACEN_KMU)); | ||
psa_set_key_id(&attributes, GetKeyId()); | ||
|
||
status = psa_import_key(&attributes, input.ConstBytes() + mPublicKey.Length(), kP256_PrivateKey_Length, &keyId); | ||
VerifyOrExit(status == PSA_SUCCESS, error = CHIP_ERROR_INTERNAL); | ||
|
||
memcpy(mPublicKey.Bytes(), input.ConstBytes(), mPublicKey.Length()); | ||
|
||
exit: | ||
LogPsaError(status); | ||
psa_reset_key_attributes(&attributes); | ||
|
||
return error; | ||
} | ||
|
||
CHIP_ERROR KMUOperationalKeystore::KMUPersistentP256Keypair::Generate() | ||
{ | ||
CHIP_ERROR error = CHIP_NO_ERROR; | ||
psa_status_t status = PSA_SUCCESS; | ||
psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT; | ||
psa_key_id_t keyId = 0; | ||
size_t publicKeyLength; | ||
|
||
Destroy(); | ||
|
||
// Type based on ECC with the elliptic curve SECP256r1 -> PSA_ECC_FAMILY_SECP_R1 | ||
psa_set_key_type(&attributes, PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_FAMILY_SECP_R1)); | ||
psa_set_key_bits(&attributes, kP256_PrivateKey_Length * 8); | ||
psa_set_key_algorithm(&attributes, PSA_ALG_ECDSA(PSA_ALG_ANY_HASH)); | ||
psa_set_key_usage_flags(&attributes, PSA_KEY_USAGE_SIGN_MESSAGE); | ||
psa_set_key_lifetime(&attributes, | ||
PSA_KEY_LIFETIME_FROM_PERSISTENCE_AND_LOCATION(PSA_KEY_PERSISTENCE_DEFAULT, PSA_KEY_LOCATION_CRACEN_KMU)); | ||
psa_set_key_id(&attributes, GetKeyId()); | ||
|
||
status = psa_generate_key(&attributes, &keyId); | ||
VerifyOrExit(status == PSA_SUCCESS, error = CHIP_ERROR_INTERNAL); | ||
|
||
status = psa_export_public_key(keyId, mPublicKey.Bytes(), mPublicKey.Length(), &publicKeyLength); | ||
VerifyOrExit(status == PSA_SUCCESS, error = CHIP_ERROR_INTERNAL); | ||
VerifyOrExit(publicKeyLength == kP256_PublicKey_Length, error = CHIP_ERROR_INTERNAL); | ||
|
||
exit: | ||
psa_reset_key_attributes(&attributes); | ||
|
||
return error; | ||
} | ||
|
||
} // namespace Crypto | ||
} // namespace chip |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,43 @@ | ||
/* | ||
* Copyright (c) 2023 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 <crypto/PSAOperationalKeystore.h> | ||
|
||
namespace chip { | ||
namespace Crypto { | ||
|
||
class KMUOperationalKeystore : public PSAOperationalKeystore | ||
{ | ||
public: | ||
CHIP_ERROR NewOpKeypairForFabric(FabricIndex fabricIndex, MutableByteSpan & outCertificateSigningRequest) override; | ||
|
||
protected: | ||
class KMUPersistentP256Keypair : public PSAOperationalKeystore::PersistentP256Keypair | ||
{ | ||
public: | ||
KMUPersistentP256Keypair(FabricIndex fabricIndex); | ||
~KMUPersistentP256Keypair() override; | ||
|
||
CHIP_ERROR Generate() override; | ||
CHIP_ERROR Deserialize(P256SerializedKeypair & input) override; | ||
}; | ||
}; | ||
|
||
} // namespace Crypto | ||
} // namespace chip |
Oops, something went wrong.