HSM key store to handle AddNOC / UpdateNOC (#21667)
* draft code for hsm integration in key store
* updated crypto build file
* updated keystore hsm file
* updated keystore file
* code cleanup
* code cleanup
* restyler
* using hsm util file
* bug fixes
* removed hsm key store. Will be moved to application specific code.
* reseting pending slot
* restyler
* review comments - update
* draft code for hsm integration in key store
* updated crypto build file
* updated keystore hsm file
* updated keystore file
* code cleanup
* code cleanup
* restyler
* using hsm util file
* bug fixes
* removed hsm key store. Will be moved to application specific code.
* reseting pending slot
* restyler
* review comments - update
* review comments - updated
* declaring variable where it is used
diff --git a/src/credentials/FabricTable.cpp b/src/credentials/FabricTable.cpp
index 5814f91..1bb3b8b 100644
--- a/src/credentials/FabricTable.cpp
+++ b/src/credentials/FabricTable.cpp
@@ -28,9 +28,6 @@
#include <lib/support/DefaultStorageKeyAllocator.h>
#include <lib/support/SafeInt.h>
#include <lib/support/ScopedBuffer.h>
-#if CHIP_CRYPTO_HSM
-#include <crypto/hsm/CHIPCryptoPALHsm.h>
-#endif
namespace chip {
using namespace Credentials;
@@ -257,11 +254,7 @@
if (mOperationalKey == nullptr)
{
-#ifdef ENABLE_HSM_CASE_OPS_KEY
- mOperationalKey = chip::Platform::New<P256KeypairHSM>();
-#else
mOperationalKey = chip::Platform::New<P256Keypair>();
-#endif
}
VerifyOrReturnError(mOperationalKey != nullptr, CHIP_ERROR_NO_MEMORY);
return mOperationalKey->Deserialize(serialized);
diff --git a/src/credentials/FabricTable.h b/src/credentials/FabricTable.h
index d5c3a39..7dbc84c 100644
--- a/src/credentials/FabricTable.h
+++ b/src/credentials/FabricTable.h
@@ -230,13 +230,8 @@
VendorId mVendorId = VendorId::NotSpecified;
char mFabricLabel[kFabricLabelMaxLengthInBytes + 1] = { '\0' };
-
-#ifdef ENABLE_HSM_CASE_OPS_KEY
- mutable Crypto::P256KeypairHSM * mOperationalKey = nullptr;
-#else
- mutable Crypto::P256Keypair * mOperationalKey = nullptr;
-#endif
- bool mHasExternallyOwnedOperationalKey = false;
+ mutable Crypto::P256Keypair * mOperationalKey = nullptr;
+ bool mHasExternallyOwnedOperationalKey = false;
CHIP_ERROR CommitToStorage(PersistentStorageDelegate * storage) const;
CHIP_ERROR LoadFromStorage(PersistentStorageDelegate * storage, FabricIndex newFabricIndex, const ByteSpan & rcac,
diff --git a/src/crypto/BUILD.gn b/src/crypto/BUILD.gn
index 61672d3..e06ab28 100644
--- a/src/crypto/BUILD.gn
+++ b/src/crypto/BUILD.gn
@@ -167,6 +167,8 @@
"hsm/nxp/CHIPCryptoPALHsm_SE05X_PBKDF.cpp",
"hsm/nxp/CHIPCryptoPALHsm_SE05X_Spake2p.cpp",
"hsm/nxp/CHIPCryptoPALHsm_SE05X_utils.cpp",
+ "hsm/nxp/PersistentStorageOperationalKeystoreHSM.cpp",
+ "hsm/nxp/PersistentStorageOperationalKeystoreHSM.h",
]
public_deps += [ "${chip_root}/third_party/simw-top-mini:se05x" ]
public_configs += [ "${chip_root}/third_party/simw-top-mini:se05x_config" ]
diff --git a/src/crypto/hsm/CHIPCryptoPALHsm.h b/src/crypto/hsm/CHIPCryptoPALHsm.h
index 0b1c0a9..a1212da 100644
--- a/src/crypto/hsm/CHIPCryptoPALHsm.h
+++ b/src/crypto/hsm/CHIPCryptoPALHsm.h
@@ -145,8 +145,6 @@
uint32_t GetKeyId(void) { return keyid; }
- CHIP_ERROR CreateOperationalKey(FabricIndex fabricIdx);
-
private:
uint32_t keyid;
P256PublicKeyHSM mPublicKeyHSM;
diff --git a/src/crypto/hsm/CHIPCryptoPALHsm_config.h b/src/crypto/hsm/CHIPCryptoPALHsm_config.h
index 7a4bd41..1c3b611 100644
--- a/src/crypto/hsm/CHIPCryptoPALHsm_config.h
+++ b/src/crypto/hsm/CHIPCryptoPALHsm_config.h
@@ -25,7 +25,7 @@
/*
* Enable HSM for SPAKE VERIFIER
*/
-#define ENABLE_HSM_SPAKE_VERIFIER 0
+#define ENABLE_HSM_SPAKE_VERIFIER 1
/*
* Enable HSM for SPAKE PROVER
@@ -58,8 +58,6 @@
#if ((CHIP_CRYPTO_HSM) && (ENABLE_HSM_GENERATE_EC_KEY))
#define ENABLE_HSM_EC_KEY
-#define ENABLE_HSM_CASE_EPHEMERAL_KEY
-//#define ENABLE_HSM_CASE_OPS_KEY
//#define ENABLE_HSM_ECDSA_VERIFY
#endif
diff --git a/src/crypto/hsm/nxp/CHIPCryptoPALHsm_SE05X_P256.cpp b/src/crypto/hsm/nxp/CHIPCryptoPALHsm_SE05X_P256.cpp
index 1007ba2..0d27c5a 100644
--- a/src/crypto/hsm/nxp/CHIPCryptoPALHsm_SE05X_P256.cpp
+++ b/src/crypto/hsm/nxp/CHIPCryptoPALHsm_SE05X_P256.cpp
@@ -693,19 +693,6 @@
return error;
}
-CHIP_ERROR P256KeypairHSM::CreateOperationalKey(FabricIndex fabricIdx)
-{
- (void) fabricIdx;
- // TBD - Map fabric index to operational keys
- SetKeyId(kKeyId_operational_key_keyid);
- if (Initialize() == CHIP_NO_ERROR)
- {
- provisioned_key = true;
- return CHIP_NO_ERROR;
- }
- return CHIP_ERROR_INTERNAL;
-}
-
} // namespace Crypto
} // namespace chip
diff --git a/src/crypto/hsm/nxp/CHIPCryptoPALHsm_SE05X_Spake2p.cpp b/src/crypto/hsm/nxp/CHIPCryptoPALHsm_SE05X_Spake2p.cpp
index f62691d..346ff83 100644
--- a/src/crypto/hsm/nxp/CHIPCryptoPALHsm_SE05X_Spake2p.cpp
+++ b/src/crypto/hsm/nxp/CHIPCryptoPALHsm_SE05X_Spake2p.cpp
@@ -27,13 +27,13 @@
#if ((ENABLE_HSM_SPAKE_VERIFIER) || (ENABLE_HSM_SPAKE_PROVER))
#if ENABLE_HSM_SPAKE_VERIFIER
-const uint32_t w0in_id_v = 0x2347;
-const uint32_t Lin_id_v = 0x2348;
+const uint32_t w0in_id_v = 0x7D200001;
+const uint32_t Lin_id_v = 0x7D200002;
#endif
#if ENABLE_HSM_SPAKE_PROVER
-const uint32_t w0in_id_p = 0x2349;
-const uint32_t w1in_id_p = 0x2350;
+const uint32_t w0in_id_p = 0x7D200003;
+const uint32_t w1in_id_p = 0x7D200004;
#endif
void Spake2p_Finish_HSM(hsm_pake_context_t * phsm_pake_context)
@@ -71,7 +71,7 @@
uint8_t create_crypto_obj = 1;
#endif
- ChipLogProgress(Crypto, "Using Object Id --> %d \n", spakeObjectId);
+ ChipLogProgress(Crypto, "SE05x: Using Object Id --> %d", spakeObjectId);
if (spakeObjectId != 0)
{
@@ -124,7 +124,7 @@
{
SE05x_CryptoObjectID_t spakeObjectId = phsm_pake_context->spake_objId;
- ChipLogProgress(Crypto, "Using HSM for spake2p ComputeRoundOne \n");
+ ChipLogProgress(Crypto, "SE05x: Using HSM for spake2p ComputeRoundOne");
VerifyOrReturnError(out != nullptr, CHIP_ERROR_INVALID_ARGUMENT);
VerifyOrReturnError(out_len != nullptr, CHIP_ERROR_INVALID_ARGUMENT);
@@ -156,7 +156,7 @@
VerifyOrReturnError(pKeyKe != nullptr, CHIP_ERROR_INVALID_ARGUMENT);
VerifyOrReturnError(pkeyKeLen != nullptr, CHIP_ERROR_INVALID_ARGUMENT);
- ChipLogProgress(Crypto, "Using HSM for spake2p ComputeRoundTwo \n");
+ ChipLogProgress(Crypto, "SE05x: Using HSM for spake2p ComputeRoundTwo");
const uint8_t * const pab = (role == chip::Crypto::CHIP_SPAKE2P_ROLE::VERIFIER) ? NULL : in;
const size_t pab_len = (role == chip::Crypto::CHIP_SPAKE2P_ROLE::VERIFIER) ? 0 : in_len;
@@ -178,7 +178,7 @@
VerifyOrReturnError(in != nullptr, CHIP_ERROR_INVALID_ARGUMENT);
VerifyOrReturnError(gex_sss_chip_ctx.ks.session != NULL, CHIP_ERROR_INTERNAL);
- ChipLogProgress(Crypto, "Using HSM for spake2p KeyConfirm \n");
+ ChipLogProgress(Crypto, "SE05x: Using HSM for spake2p KeyConfirm");
uint8_t presult = 0;
const SE05x_CryptoObjectID_t spakeObjectId = phsm_pake_context->spake_objId;
@@ -251,7 +251,7 @@
VerifyOrReturnError(peer_identity != nullptr, CHIP_ERROR_INVALID_ARGUMENT);
}
- ChipLogProgress(Crypto, "HSM - BeginVerifier \n");
+ ChipLogProgress(Crypto, "SE05x: HSM - BeginVerifier");
ReturnErrorOnFailure(FELoad(w0in, w0in_len, w0));
ReturnErrorOnFailure(FEWrite(w0, w0in_mod, w0in_mod_len));
@@ -309,7 +309,7 @@
VerifyOrReturnError(state == CHIP_SPAKE2P_STATE::INIT, CHIP_ERROR_INTERNAL);
- ChipLogProgress(Crypto, "HSM - BeginProver \n");
+ ChipLogProgress(Crypto, "SE05x: HSM - BeginProver");
ReturnErrorOnFailure(FELoad(w0in, w0in_len, w0));
ReturnErrorOnFailure(FEWrite(w0, w0in_mod, w0in_mod_len));
diff --git a/src/crypto/hsm/nxp/CHIPCryptoPALHsm_SE05X_utils.h b/src/crypto/hsm/nxp/CHIPCryptoPALHsm_SE05X_utils.h
index 2169ffd..e5e3bb1 100644
--- a/src/crypto/hsm/nxp/CHIPCryptoPALHsm_SE05X_utils.h
+++ b/src/crypto/hsm/nxp/CHIPCryptoPALHsm_SE05X_utils.h
@@ -42,11 +42,11 @@
enum keyid_values
{
kKeyId_NotInitialized = 0,
- kKeyId_pbkdf2_sha256_hmac_keyid = 0xBCBCBCBC,
+ kKeyId_pbkdf2_sha256_hmac_keyid = 0x7D000000,
kKeyId_hkdf_sha256_hmac_keyid,
kKeyId_hmac_sha256_keyid,
kKeyId_sha256_ecc_pub_keyid,
- kKeyId_operational_key_keyid,
+ kKeyId_case_ephemeral_keyid,
};
// Enable the below macro to make spake HSM imlementation reentrant.
diff --git a/src/crypto/hsm/nxp/PersistentStorageOperationalKeystoreHSM.cpp b/src/crypto/hsm/nxp/PersistentStorageOperationalKeystoreHSM.cpp
new file mode 100644
index 0000000..abe0f8e
--- /dev/null
+++ b/src/crypto/hsm/nxp/PersistentStorageOperationalKeystoreHSM.cpp
@@ -0,0 +1,274 @@
+/*
+ * Copyright (c) 2022 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 "PersistentStorageOperationalKeystoreHSM.h"
+#include "CHIPCryptoPALHsm_SE05X_utils.h"
+#include <crypto/hsm/CHIPCryptoPALHsm.h>
+
+#if ENABLE_HSM_GENERATE_EC_KEY
+
+namespace chip {
+
+using namespace chip::Crypto;
+
+#define MAX_KEYID_SLOTS_FOR_FABRICS 32
+#define FABRIC_SE05X_KEYID_START 0x7D100000
+
+/**
+ * Known issues:
+ * 1. The current HSM keystore implementation is tested only with one fabric. To be tested with multiple fabrics.
+ * 2. Logic to read the HSM and create the fabricTable from the persistent keys after reboot is missing .
+ */
+
+struct keyidFabIdMapping_t
+{
+ uint32_t keyId;
+ FabricIndex fabricIndex;
+ bool isPending;
+ Crypto::P256KeypairHSM * pkeyPair;
+} keyidFabIdMapping[MAX_KEYID_SLOTS_FOR_FABRICS] = {
+ 0,
+};
+
+uint8_t getEmpytSlotId()
+{
+ uint8_t i = 0;
+ for (auto & mapping : keyidFabIdMapping)
+ {
+ if (mapping.keyId == kKeyId_NotInitialized && mapping.isPending == false)
+ {
+ break;
+ }
+ i++;
+ }
+ return i;
+}
+
+void PersistentStorageOperationalKeystoreHSM::ResetPendingSlot()
+{
+ uint32_t slotId = mPendingKeypair->GetKeyId() - FABRIC_SE05X_KEYID_START;
+ if (slotId < MAX_KEYID_SLOTS_FOR_FABRICS)
+ {
+ keyidFabIdMapping[slotId].keyId = kKeyId_NotInitialized;
+ keyidFabIdMapping[slotId].fabricIndex = kUndefinedFabricIndex;
+ keyidFabIdMapping[slotId].isPending = false;
+ }
+}
+
+bool PersistentStorageOperationalKeystoreHSM::HasOpKeypairForFabric(FabricIndex fabricIndex) const
+{
+ VerifyOrReturnError(IsValidFabricIndex(fabricIndex), false);
+
+ // If there was a pending keypair, then there's really a usable key
+ if (mIsPendingKeypairActive && (fabricIndex == mPendingFabricIndex) && (mPendingKeypair != nullptr))
+ {
+ ChipLogProgress(Crypto, "SE05x: HasOpKeypairForFabric ==> mPendingKeypair found");
+ return true;
+ }
+
+ for (auto & mapping : keyidFabIdMapping)
+ {
+ if (mapping.fabricIndex == fabricIndex)
+ {
+ ChipLogProgress(Crypto, "SE05x: HasOpKeypairForFabric ==> stored keyPair found");
+ return true;
+ }
+ }
+
+ ChipLogProgress(Crypto, "SE05x: HasOpKeypairForFabric ==> No key found");
+ return false;
+}
+
+CHIP_ERROR PersistentStorageOperationalKeystoreHSM::NewOpKeypairForFabric(FabricIndex fabricIndex,
+ MutableByteSpan & outCertificateSigningRequest)
+{
+ CHIP_ERROR err = CHIP_NO_ERROR;
+
+ VerifyOrReturnError(IsValidFabricIndex(fabricIndex), CHIP_ERROR_INVALID_FABRIC_INDEX);
+
+ ChipLogProgress(Crypto, "SE05x: New Op Keypair for Fabric %02x", fabricIndex);
+
+ // Replace previous pending keypair, if any was previously allocated
+ ResetPendingKey();
+
+ uint8_t slotId = getEmpytSlotId();
+ VerifyOrReturnError(slotId < MAX_KEYID_SLOTS_FOR_FABRICS, CHIP_ERROR_NO_MEMORY);
+
+ mPendingKeypair = Platform::New<Crypto::P256KeypairHSM>();
+ VerifyOrReturnError(mPendingKeypair != nullptr, CHIP_ERROR_NO_MEMORY);
+
+ // Key id is created as slotid + start offset of ops key id
+ mPendingKeypair->SetKeyId(FABRIC_SE05X_KEYID_START + slotId);
+
+ err = mPendingKeypair->Initialize();
+ VerifyOrReturnError(err == CHIP_NO_ERROR, CHIP_ERROR_NO_MEMORY);
+
+ mPendingFabricIndex = fabricIndex;
+
+ keyidFabIdMapping[slotId].isPending = true;
+
+ size_t csrLength = outCertificateSigningRequest.size();
+ err = mPendingKeypair->NewCertificateSigningRequest(outCertificateSigningRequest.data(), csrLength);
+ if (err != CHIP_NO_ERROR)
+ {
+ ResetPendingKey();
+ return err;
+ }
+ outCertificateSigningRequest.reduce_size(csrLength);
+
+ return CHIP_NO_ERROR;
+}
+
+CHIP_ERROR PersistentStorageOperationalKeystoreHSM::ActivateOpKeypairForFabric(FabricIndex fabricIndex,
+ const Crypto::P256PublicKey & nocPublicKey)
+{
+ ChipLogProgress(Crypto, "SE05x: ActivateOpKeypair for Fabric %02x", fabricIndex);
+
+ VerifyOrReturnError(mPendingKeypair != nullptr, CHIP_ERROR_INVALID_FABRIC_INDEX);
+ VerifyOrReturnError(IsValidFabricIndex(fabricIndex) && (fabricIndex == mPendingFabricIndex), CHIP_ERROR_INVALID_FABRIC_INDEX);
+
+ // Validate public key being activated matches last generated pending keypair
+ VerifyOrReturnError(mPendingKeypair->Pubkey().Matches(nocPublicKey), CHIP_ERROR_INVALID_PUBLIC_KEY);
+
+ mIsPendingKeypairActive = true;
+
+ return CHIP_NO_ERROR;
+}
+
+CHIP_ERROR PersistentStorageOperationalKeystoreHSM::CommitOpKeypairForFabric(FabricIndex fabricIndex)
+{
+ VerifyOrReturnError(mPendingKeypair != nullptr, CHIP_ERROR_INVALID_FABRIC_INDEX);
+ VerifyOrReturnError(IsValidFabricIndex(fabricIndex) && (fabricIndex == mPendingFabricIndex), CHIP_ERROR_INVALID_FABRIC_INDEX);
+ VerifyOrReturnError(mIsPendingKeypairActive == true, CHIP_ERROR_INCORRECT_STATE);
+
+ uint32_t slotId = mPendingKeypair->GetKeyId() - FABRIC_SE05X_KEYID_START;
+
+ VerifyOrReturnError(slotId < MAX_KEYID_SLOTS_FOR_FABRICS, CHIP_ERROR_NO_MEMORY);
+
+ ChipLogProgress(Crypto, "SE05x: CommitOpKeypair for Fabric %02x", fabricIndex);
+
+ for (auto & mapping : keyidFabIdMapping)
+ {
+ if (mapping.fabricIndex == fabricIndex)
+ {
+ // Delete the previous keyPair associated with the fabric
+ mapping.isPending = false;
+ Platform::Delete<Crypto::P256KeypairHSM>(mapping.pkeyPair);
+ mapping.pkeyPair = NULL;
+ mapping.keyId = kKeyId_NotInitialized;
+ mapping.fabricIndex = kUndefinedFabricIndex;
+ }
+ }
+
+ keyidFabIdMapping[slotId].pkeyPair = mPendingKeypair;
+ keyidFabIdMapping[slotId].keyId = mPendingKeypair->GetKeyId();
+ keyidFabIdMapping[slotId].fabricIndex = mPendingFabricIndex;
+ keyidFabIdMapping[slotId].isPending = false;
+
+ // If we got here, we succeeded and can reset the pending key: next `SignWithOpKeypair` will use the stored key.
+ mPendingKeypair = nullptr;
+ mIsPendingKeypairActive = false;
+ mPendingFabricIndex = kUndefinedFabricIndex;
+
+ return CHIP_NO_ERROR;
+}
+
+CHIP_ERROR PersistentStorageOperationalKeystoreHSM::RemoveOpKeypairForFabric(FabricIndex fabricIndex)
+{
+ VerifyOrReturnError(IsValidFabricIndex(fabricIndex), CHIP_ERROR_INVALID_FABRIC_INDEX);
+
+ ChipLogProgress(Crypto, "SE05x: RemoveOpKeypair for Fabric %02x", fabricIndex);
+
+ // Remove pending state if matching
+ if ((mPendingKeypair != nullptr) && (fabricIndex == mPendingFabricIndex))
+ {
+ RevertPendingKeypair();
+ }
+
+ for (auto & mapping : keyidFabIdMapping)
+ {
+ if (mapping.fabricIndex == fabricIndex)
+ {
+ // Delete the keyPair associated with the fabric
+ mapping.isPending = false;
+ Platform::Delete<Crypto::P256KeypairHSM>(mapping.pkeyPair);
+ mapping.pkeyPair = NULL;
+ mapping.keyId = kKeyId_NotInitialized;
+ mapping.fabricIndex = kUndefinedFabricIndex;
+ }
+ }
+
+ return CHIP_NO_ERROR;
+}
+
+void PersistentStorageOperationalKeystoreHSM::RevertPendingKeypair()
+{
+ ChipLogProgress(Crypto, "SE05x: RevertPendingKeypair");
+ // Just reset the pending key, we never stored anything
+ ResetPendingKey();
+}
+
+CHIP_ERROR PersistentStorageOperationalKeystoreHSM::SignWithOpKeypair(FabricIndex fabricIndex, const ByteSpan & message,
+ Crypto::P256ECDSASignature & outSignature) const
+{
+ ChipLogProgress(Crypto, "SE05x: SignWithOpKeypair");
+
+ if (mIsPendingKeypairActive && (fabricIndex == mPendingFabricIndex))
+ {
+ VerifyOrReturnError(mPendingKeypair != nullptr, CHIP_ERROR_INTERNAL);
+ // We have an override key: sign with it!
+ ChipLogProgress(Crypto, "SE05x: SignWithOpKeypair ==> using mPendingKeypair");
+ return mPendingKeypair->ECDSA_sign_msg(message.data(), message.size(), outSignature);
+ }
+ else
+ {
+ for (auto & mapping : keyidFabIdMapping)
+ {
+ if ((mapping.fabricIndex == fabricIndex) && (mapping.isPending == false))
+ {
+ ChipLogProgress(Crypto, "SE05x: SignWithOpKeypair ==> using stored keyPair");
+ return mapping.pkeyPair->ECDSA_sign_msg(message.data(), message.size(), outSignature);
+ }
+ }
+ }
+
+ ChipLogProgress(Crypto, "SE05x: SignWithOpKeypair ==> No keyPair found");
+ return CHIP_ERROR_INVALID_FABRIC_INDEX;
+}
+
+Crypto::P256Keypair * PersistentStorageOperationalKeystoreHSM::AllocateEphemeralKeypairForCASE()
+{
+ ChipLogProgress(Crypto, "SE05x: AllocateEphemeralKeypairForCASE using se05x");
+ Crypto::P256KeypairHSM * pkeyPair = Platform::New<Crypto::P256KeypairHSM>();
+
+ if (pkeyPair != nullptr)
+ {
+ pkeyPair->SetKeyId(kKeyId_case_ephemeral_keyid);
+ }
+
+ return pkeyPair;
+}
+
+void PersistentStorageOperationalKeystoreHSM::ReleaseEphemeralKeypair(Crypto::P256Keypair * keypair)
+{
+ ChipLogProgress(Crypto, "SE05x: ReleaseEphemeralKeypair using se05x");
+ Platform::Delete(static_cast<Crypto::P256KeypairHSM *>(keypair));
+}
+
+} // namespace chip
+
+#endif //#if ENABLE_HSM_GENERATE_EC_KEY
diff --git a/src/crypto/hsm/nxp/PersistentStorageOperationalKeystoreHSM.h b/src/crypto/hsm/nxp/PersistentStorageOperationalKeystoreHSM.h
new file mode 100644
index 0000000..bc00fea
--- /dev/null
+++ b/src/crypto/hsm/nxp/PersistentStorageOperationalKeystoreHSM.h
@@ -0,0 +1,99 @@
+/*
+ * Copyright (c) 2022 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 "CHIPCryptoPALHsm_SE05X_utils.h"
+#include <crypto/OperationalKeystore.h>
+#include <lib/core/CHIPError.h>
+#include <lib/core/CHIPPersistentStorageDelegate.h>
+#include <lib/core/DataModelTypes.h>
+#include <lib/support/CHIPMem.h>
+#include <lib/support/CodeUtils.h>
+
+#if ENABLE_HSM_GENERATE_EC_KEY
+
+namespace chip {
+
+class PersistentStorageOperationalKeystoreHSM : public Crypto::OperationalKeystore
+{
+public:
+ PersistentStorageOperationalKeystoreHSM() = default;
+ virtual ~PersistentStorageOperationalKeystoreHSM() { Finish(); }
+
+ // Non-copyable
+ PersistentStorageOperationalKeystoreHSM(PersistentStorageOperationalKeystoreHSM const &) = delete;
+ void operator=(PersistentStorageOperationalKeystoreHSM const &) = delete;
+
+ /**
+ * @brief Initialize the Operational Keystore for HSM.
+ *
+ * @param storage Pointer to persistent storage delegate to use. Must outlive this instance.
+ * @retval CHIP_NO_ERROR on success
+ * @retval CHIP_ERROR_INCORRECT_STATE if already initialized
+ */
+ CHIP_ERROR Init(PersistentStorageDelegate * storage)
+ {
+ IgnoreUnusedVariable(storage);
+ mPendingFabricIndex = kUndefinedFabricIndex;
+ mPendingKeypair = nullptr;
+ mIsPendingKeypairActive = false;
+ return CHIP_NO_ERROR;
+ }
+
+ /**
+ * @brief Finalize the keystore, so that subsequent operations fail
+ */
+ void Finish() { ResetPendingKey(); }
+
+ bool HasPendingOpKeypair() const override { return (mPendingKeypair != nullptr); }
+
+ bool HasOpKeypairForFabric(FabricIndex fabricIndex) const override;
+ CHIP_ERROR NewOpKeypairForFabric(FabricIndex fabricIndex, MutableByteSpan & outCertificateSigningRequest) override;
+ CHIP_ERROR ActivateOpKeypairForFabric(FabricIndex fabricIndex, const Crypto::P256PublicKey & nocPublicKey) override;
+ CHIP_ERROR CommitOpKeypairForFabric(FabricIndex fabricIndex) override;
+ CHIP_ERROR RemoveOpKeypairForFabric(FabricIndex fabricIndex) override;
+ void RevertPendingKeypair() override;
+ CHIP_ERROR SignWithOpKeypair(FabricIndex fabricIndex, const ByteSpan & message,
+ Crypto::P256ECDSASignature & outSignature) const override;
+ Crypto::P256Keypair * AllocateEphemeralKeypairForCASE() override;
+ void ReleaseEphemeralKeypair(Crypto::P256Keypair * keypair) override;
+
+protected:
+ void ResetPendingSlot();
+
+ void ResetPendingKey()
+ {
+ if (mPendingKeypair != nullptr)
+ {
+ ResetPendingSlot();
+ Platform::Delete(mPendingKeypair);
+ }
+ mPendingKeypair = nullptr;
+ mIsPendingKeypairActive = false;
+ mPendingFabricIndex = kUndefinedFabricIndex;
+ }
+
+ // This pending fabric index is `kUndefinedFabricIndex` if there isn't a pending keypair override for a given fabric.
+ FabricIndex mPendingFabricIndex = kUndefinedFabricIndex;
+ Crypto::P256KeypairHSM * mPendingKeypair = nullptr;
+ bool mIsPendingKeypairActive = false;
+};
+
+} // namespace chip
+
+#endif //#if ENABLE_HSM_GENERATE_EC_KEY