From 2e6bd54363435198500c9fd620b0a5718f8a85f9 Mon Sep 17 00:00:00 2001 From: ATmobica Date: Fri, 23 Jun 2023 12:28:43 +0000 Subject: [PATCH] [crypto] Keep PSA private keys in secure storage To keep keys secure, when PSA is used. It is recommended to keep the private key in the secure partition; in the secure storage. Keys are then referred to with an ID rather than a value. This requires few changes regards to how keys are copied and imported. Previously the serialize/deserialize methods were used for that effect. This patch introduces two specific operations for a P256Keypair: - Copy: copy a keypair into another keypair. - ImportRawKeypair: Import a keypair from raw bytes. Such function was already defined in some of the unit tests as LoadKeypairFromRaw. It is now rationalised and available from the P256KeyPair class. The functions serialize/deserialize when implemented with PSA do not get the raw keypair. They rather serialize the reference ID of the private key and the public key. The internal mechanism to commit operational fabric key has been reworked in the PSA implementation to fix an issue where the pending keypair is reverted. Signed-off-by: Vincent Coubard --- src/app/server/Server.cpp | 4 + src/app/server/Server.h | 12 ++ src/app/tests/integration/common.cpp | 12 ++ .../credentials/TestHarnessDACProvider.cpp | 13 +- src/credentials/FabricTable.cpp | 15 +-- .../TestOnlyLocalCertificateAuthority.h | 2 +- .../DeviceAttestationCredsExample.cpp | 12 +- .../tests/TestCertificationDeclaration.cpp | 7 +- src/credentials/tests/TestFabricTable.cpp | 102 +++++++++++---- src/crypto/CHIPCryptoPAL.h | 21 +++ src/crypto/CHIPCryptoPALOpenSSL.cpp | 40 ++++++ src/crypto/CHIPCryptoPALPSA.cpp | 123 +++++++++++++++--- src/crypto/CHIPCryptoPALmbedTLS.cpp | 43 +++++- src/crypto/PSAOperationalKeystore.cpp | 75 +++++------ src/crypto/PSAOperationalKeystore.h | 14 +- src/crypto/tests/CHIPCryptoPALTest.cpp | 60 +++++++++ src/crypto/tests/TestPSAOpKeyStore.cpp | 2 +- src/messaging/tests/MessagingContext.cpp | 4 + src/messaging/tests/MessagingContext.h | 10 ++ src/platform/Ameba/FactoryDataProvider.cpp | 18 +-- .../ESP32/ESP32FactoryDataProvider.cpp | 10 +- .../nrfconnect/FactoryDataProvider.cpp | 15 +-- .../nxp/mw320/FactoryDataProvider.cpp | 15 +-- src/platform/qpg/FactoryDataProvider.cpp | 14 +- src/platform/telink/FactoryDataProvider.cpp | 15 +-- .../secure_channel/tests/TestCASESession.cpp | 10 +- src/transport/tests/TestSessionManager.cpp | 12 ++ .../tests/TestSessionManagerDispatch.cpp | 12 ++ 28 files changed, 487 insertions(+), 205 deletions(-) diff --git a/src/app/server/Server.cpp b/src/app/server/Server.cpp index 0793832d17271c..585598025b1b70 100644 --- a/src/app/server/Server.cpp +++ b/src/app/server/Server.cpp @@ -548,7 +548,11 @@ void Server::ResumeSubscriptions() Credentials::IgnoreCertificateValidityPeriodPolicy Server::sDefaultCertValidityPolicy; KvsPersistentStorageDelegate CommonCaseDeviceServerInitParams::sKvsPersistenStorageDelegate; +#if CHIP_CRYPTO_PSA +Crypto::PSAOperationalKeystore CommonCaseDeviceServerInitParams::sPersistentStorageOperationalKeystore; +#else PersistentStorageOperationalKeystore CommonCaseDeviceServerInitParams::sPersistentStorageOperationalKeystore; +#endif Credentials::PersistentStorageOpCertStore CommonCaseDeviceServerInitParams::sPersistentStorageOpCertStore; Credentials::GroupDataProviderImpl CommonCaseDeviceServerInitParams::sGroupDataProvider; #if CHIP_CONFIG_ENABLE_SESSION_RESUMPTION diff --git a/src/app/server/Server.h b/src/app/server/Server.h index d2cdaacb7f48ea..89fd536415cd9a 100644 --- a/src/app/server/Server.h +++ b/src/app/server/Server.h @@ -40,7 +40,11 @@ #include #include #include +#if CHIP_CRYPTO_PSA +#include +#else #include +#endif #include #include #include @@ -202,7 +206,11 @@ struct CommonCaseDeviceServerInitParams : public ServerInitParams { // WARNING: PersistentStorageOperationalKeystore::Finish() is never called. It's fine for // for examples and for now. +#if !CHIP_CRYPTO_PSA ReturnErrorOnFailure(sPersistentStorageOperationalKeystore.Init(this->persistentStorageDelegate)); +#else + // Note: PSA Operational keystore does not require initialization +#endif this->operationalKeystore = &sPersistentStorageOperationalKeystore; } @@ -251,7 +259,11 @@ struct CommonCaseDeviceServerInitParams : public ServerInitParams private: static KvsPersistentStorageDelegate sKvsPersistenStorageDelegate; +#if CHIP_CRYPTO_PSA + static Crypto::PSAOperationalKeystore sPersistentStorageOperationalKeystore; +#else static PersistentStorageOperationalKeystore sPersistentStorageOperationalKeystore; +#endif static Credentials::PersistentStorageOpCertStore sPersistentStorageOpCertStore; static Credentials::GroupDataProviderImpl sGroupDataProvider; #if CHIP_CONFIG_ENABLE_SESSION_RESUMPTION diff --git a/src/app/tests/integration/common.cpp b/src/app/tests/integration/common.cpp index 87627aeb9fddf0..49e7f7c1158fc3 100644 --- a/src/app/tests/integration/common.cpp +++ b/src/app/tests/integration/common.cpp @@ -26,7 +26,11 @@ #include #include +#if CHIP_CRYPTO_PSA +#include +#else #include +#endif #include #include #include @@ -41,7 +45,11 @@ chip::SessionManager gSessionManager; chip::secure_channel::MessageCounterManager gMessageCounterManager; chip::SessionHolder gSession; chip::TestPersistentStorageDelegate gStorage; +#if CHIP_CRYPTO_PSA +chip::Crypto::PSAOperationalKeystore gOperationalKeystore; +#else chip::PersistentStorageOperationalKeystore gOperationalKeystore; +#endif chip::Credentials::PersistentStorageOpCertStore gOpCertStore; chip::Crypto::DefaultSessionKeystore gSessionKeystore; @@ -64,8 +72,10 @@ void InitializeChip() err = gOpCertStore.Init(&gStorage); SuccessOrExit(err); +#if !CHIP_CRYPTO_PSA err = gOperationalKeystore.Init(&gStorage); SuccessOrExit(err); +#endif fabricTableInitParams.storage = &gStorage; fabricTableInitParams.operationalKeystore = &gOperationalKeystore; @@ -92,7 +102,9 @@ void ShutdownChip() gSessionManager.Shutdown(); gFabricTable.Shutdown(); +#if !CHIP_CRYPTO_PSA gOperationalKeystore.Finish(); +#endif gOpCertStore.Finish(); chip::DeviceLayer::PlatformMgr().Shutdown(); diff --git a/src/app/tests/suites/credentials/TestHarnessDACProvider.cpp b/src/app/tests/suites/credentials/TestHarnessDACProvider.cpp index dd53e81178bb49..8ce748d75ab2aa 100644 --- a/src/app/tests/suites/credentials/TestHarnessDACProvider.cpp +++ b/src/app/tests/suites/credentials/TestHarnessDACProvider.cpp @@ -176,16 +176,6 @@ bool ReadValue(Json::Value jsonValue) return false; } -// TODO: This should be moved to a method of P256Keypair -CHIP_ERROR LoadKeypairFromRaw(ByteSpan private_key, ByteSpan public_key, Crypto::P256Keypair & keypair) -{ - Crypto::P256SerializedKeypair serialized_keypair; - ReturnErrorOnFailure(serialized_keypair.SetLength(private_key.size() + public_key.size())); - memcpy(serialized_keypair.Bytes(), public_key.data(), public_key.size()); - memcpy(serialized_keypair.Bytes() + public_key.size(), private_key.data(), private_key.size()); - return keypair.Deserialize(serialized_keypair); -} - } // namespace TestHarnessDACProvider::TestHarnessDACProvider() @@ -321,7 +311,8 @@ CHIP_ERROR TestHarnessDACProvider::SignWithDeviceAttestationKey(const ByteSpan & // 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. - ReturnErrorOnFailure(LoadKeypairFromRaw(mDacPrivateKey, mDacPublicKey, keypair)); + ReturnErrorOnFailure(keypair.ImportRawKeypair(mDacPrivateKey, mDacPublicKey)); + ReturnErrorOnFailure(keypair.ECDSA_sign_msg(message_to_sign.data(), message_to_sign.size(), signature)); return CopySpanToMutableSpan(ByteSpan{ signature.ConstBytes(), signature.Length() }, out_signature_buffer); diff --git a/src/credentials/FabricTable.cpp b/src/credentials/FabricTable.cpp index 6d9f4781fff576..d0c606ab731d15 100644 --- a/src/credentials/FabricTable.cpp +++ b/src/credentials/FabricTable.cpp @@ -239,9 +239,6 @@ CHIP_ERROR FabricInfo::SetOperationalKeypair(const P256Keypair * keyPair) { VerifyOrReturnError(keyPair != nullptr, CHIP_ERROR_INVALID_ARGUMENT); - P256SerializedKeypair serialized; - ReturnErrorOnFailure(keyPair->Serialize(serialized)); - if (mHasExternallyOwnedOperationalKey) { // Drop it, so we will allocate an internally owned one. @@ -254,7 +251,7 @@ CHIP_ERROR FabricInfo::SetOperationalKeypair(const P256Keypair * keyPair) mOperationalKey = chip::Platform::New(); } VerifyOrReturnError(mOperationalKey != nullptr, CHIP_ERROR_NO_MEMORY); - return mOperationalKey->Deserialize(serialized); + return mOperationalKey->Copy(*keyPair); } CHIP_ERROR FabricInfo::SetExternallyOwnedOperationalKeypair(P256Keypair * keyPair) @@ -683,16 +680,12 @@ CHIP_ERROR FabricTable::AddNewFabricForTest(const ByteSpan & rootCert, const Byt CHIP_ERROR err = CHIP_ERROR_INTERNAL; Crypto::P256Keypair injectedOpKey; - Crypto::P256SerializedKeypair injectedOpKeysSerialized; - Crypto::P256Keypair * opKey = nullptr; + if (!opKeySpan.empty()) { - VerifyOrReturnError(opKeySpan.size() == injectedOpKeysSerialized.Capacity(), CHIP_ERROR_INVALID_ARGUMENT); - - memcpy(injectedOpKeysSerialized.Bytes(), opKeySpan.data(), opKeySpan.size()); - SuccessOrExit(err = injectedOpKeysSerialized.SetLength(opKeySpan.size())); - SuccessOrExit(err = injectedOpKey.Deserialize(injectedOpKeysSerialized)); + VerifyOrReturnError(opKeySpan.size() == kP256_PublicKey_Length + kP256_PrivateKey_Length, CHIP_ERROR_INVALID_ARGUMENT); + SuccessOrExit(err = injectedOpKey.ImportRawKeypair(opKeySpan)); opKey = &injectedOpKey; } diff --git a/src/credentials/TestOnlyLocalCertificateAuthority.h b/src/credentials/TestOnlyLocalCertificateAuthority.h index 6444d5676556dc..1288f3c15ab712 100644 --- a/src/credentials/TestOnlyLocalCertificateAuthority.h +++ b/src/credentials/TestOnlyLocalCertificateAuthority.h @@ -69,7 +69,7 @@ class TestOnlyLocalCertificateAuthority if (rootKeyPair.Length() != 0) { - mCurrentStatus = mRootKeypair->Deserialize(rootKeyPair); + mCurrentStatus = mRootKeypair->ImportRawKeypair(rootKeyPair.Span()); SuccessOrExit(mCurrentStatus); } else diff --git a/src/credentials/examples/DeviceAttestationCredsExample.cpp b/src/credentials/examples/DeviceAttestationCredsExample.cpp index a487dcef1926f9..8bf998fa53ef89 100644 --- a/src/credentials/examples/DeviceAttestationCredsExample.cpp +++ b/src/credentials/examples/DeviceAttestationCredsExample.cpp @@ -31,16 +31,6 @@ namespace Examples { namespace { -// TODO: This should be moved to a method of P256Keypair -CHIP_ERROR LoadKeypairFromRaw(ByteSpan private_key, ByteSpan public_key, Crypto::P256Keypair & keypair) -{ - Crypto::P256SerializedKeypair serialized_keypair; - ReturnErrorOnFailure(serialized_keypair.SetLength(private_key.size() + public_key.size())); - memcpy(serialized_keypair.Bytes(), public_key.data(), public_key.size()); - memcpy(serialized_keypair.Bytes() + public_key.size(), private_key.data(), private_key.size()); - return keypair.Deserialize(serialized_keypair); -} - class ExampleDACProvider : public DeviceAttestationCredentialsProvider { public: @@ -196,7 +186,7 @@ CHIP_ERROR ExampleDACProvider::SignWithDeviceAttestationKey(const ByteSpan & mes // 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. - ReturnErrorOnFailure(LoadKeypairFromRaw(DevelopmentCerts::kDacPrivateKey, DevelopmentCerts::kDacPublicKey, keypair)); + ReturnErrorOnFailure(keypair.ImportRawKeypair(DevelopmentCerts::kDacPrivateKey, DevelopmentCerts::kDacPublicKey)); ReturnErrorOnFailure(keypair.ECDSA_sign_msg(message_to_sign.data(), message_to_sign.size(), signature)); return CopySpanToMutableSpan(ByteSpan{ signature.ConstBytes(), signature.Length() }, out_signature_buffer); diff --git a/src/credentials/tests/TestCertificationDeclaration.cpp b/src/credentials/tests/TestCertificationDeclaration.cpp index 4fc4426668acbe..d7dab94d3d24e4 100644 --- a/src/credentials/tests/TestCertificationDeclaration.cpp +++ b/src/credentials/tests/TestCertificationDeclaration.cpp @@ -363,12 +363,11 @@ static void TestCD_CMSSignAndVerify(nlTestSuite * inSuite, void * inContext) // Test with known key P256Keypair keypair2; - P256SerializedKeypair serializedKeypair; - memcpy(serializedKeypair.Bytes(), sTestCMS_SignerSerializedKeypair, sizeof(sTestCMS_SignerSerializedKeypair)); - serializedKeypair.SetLength(sizeof(sTestCMS_SignerSerializedKeypair)); cdContentIn = ByteSpan(sTestCMS_CDContent02); signedMessage = MutableByteSpan(signedMessageBuf); - NL_TEST_ASSERT(inSuite, keypair2.Deserialize(serializedKeypair) == CHIP_NO_ERROR); + NL_TEST_ASSERT(inSuite, + keypair2.ImportRawKeypair(sTestCMS_SignerSerializedKeypair, sizeof(sTestCMS_SignerSerializedKeypair)) == + CHIP_NO_ERROR); NL_TEST_ASSERT(inSuite, CMS_Sign(cdContentIn, signerKeyId, keypair2, signedMessage) == CHIP_NO_ERROR); NL_TEST_ASSERT(inSuite, CMS_Verify(signedMessage, keypair2.Pubkey(), cdContentOut) == CHIP_NO_ERROR); NL_TEST_ASSERT(inSuite, cdContentIn.data_equal(cdContentOut)); diff --git a/src/credentials/tests/TestFabricTable.cpp b/src/credentials/tests/TestFabricTable.cpp index c6e7998f0c1788..59d8d1fa5706de 100644 --- a/src/credentials/tests/TestFabricTable.cpp +++ b/src/credentials/tests/TestFabricTable.cpp @@ -32,7 +32,11 @@ #include #include #include +#if CHIP_CRYPTO_PSA +#include +#else #include +#endif #include #include #include @@ -57,7 +61,9 @@ class ScopedFabricTable { mFabricTable.Shutdown(); mOpCertStore.Finish(); +#if !CHIP_CRYPTO_PSA mOpKeyStore.Finish(); +#endif } CHIP_ERROR Init(chip::TestPersistentStorageDelegate * storage) @@ -67,7 +73,9 @@ class ScopedFabricTable initParams.operationalKeystore = &mOpKeyStore; initParams.opCertStore = &mOpCertStore; +#if !CHIP_CRYPTO_PSA ReturnErrorOnFailure(mOpKeyStore.Init(storage)); +#endif ReturnErrorOnFailure(mOpCertStore.Init(storage)); return mFabricTable.Init(initParams); } @@ -76,7 +84,11 @@ class ScopedFabricTable private: chip::FabricTable mFabricTable; +#if CHIP_CRYPTO_PSA + chip::Crypto::PSAOperationalKeystore mOpKeyStore; +#else chip::PersistentStorageOperationalKeystore mOpKeyStore; +#endif chip::Credentials::PersistentStorageOpCertStore mOpCertStore; }; @@ -85,21 +97,18 @@ class ScopedFabricTable */ static CHIP_ERROR LoadTestFabric_Node01_01(nlTestSuite * inSuite, FabricTable & fabricTable, bool doCommit) { - Crypto::P256SerializedKeypair opKeysSerialized; static Crypto::P256Keypair opKey_Node01_01; FabricIndex fabricIndex; - memcpy(opKeysSerialized.Bytes(), TestCerts::sTestCert_Node01_01_PublicKey, TestCerts::sTestCert_Node01_01_PublicKey_Len); - memcpy(opKeysSerialized.Bytes() + TestCerts::sTestCert_Node01_01_PublicKey_Len, TestCerts::sTestCert_Node01_01_PrivateKey, - TestCerts::sTestCert_Node01_01_PrivateKey_Len); ByteSpan rcacSpan(TestCerts::sTestCert_Root01_Chip, TestCerts::sTestCert_Root01_Chip_Len); ByteSpan icacSpan(TestCerts::sTestCert_ICA01_Chip, TestCerts::sTestCert_ICA01_Chip_Len); ByteSpan nocSpan(TestCerts::sTestCert_Node01_01_Chip, TestCerts::sTestCert_Node01_01_Chip_Len); ReturnErrorOnFailure( - opKeysSerialized.SetLength(TestCerts::sTestCert_Node01_01_PublicKey_Len + TestCerts::sTestCert_Node01_01_PrivateKey_Len)); - ReturnErrorOnFailure(opKey_Node01_01.Deserialize(opKeysSerialized)); + opKey_Node01_01.ImportRawKeypair(TestCerts::sTestCert_Node01_01_PrivateKey, TestCerts::sTestCert_Node01_01_PrivateKey_Len, + TestCerts::sTestCert_Node01_01_PublicKey, TestCerts::sTestCert_Node01_01_PublicKey_Len)); + ReturnErrorOnFailure(fabricTable.AddNewPendingTrustedRootCert(rcacSpan)); ReturnErrorOnFailure(fabricTable.AddNewPendingFabricWithProvidedOpKey(nocSpan, icacSpan, VendorId::TestVendor1, @@ -115,20 +124,15 @@ static CHIP_ERROR LoadTestFabric_Node01_01(nlTestSuite * inSuite, FabricTable & static CHIP_ERROR LoadTestFabric_Node01_02(nlTestSuite * inSuite, FabricTable & fabricTable, bool doCommit) { - Crypto::P256SerializedKeypair opKeysSerialized; FabricIndex fabricIndex; static Crypto::P256Keypair opKey_Node01_02; - memcpy(opKeysSerialized.Bytes(), TestCerts::sTestCert_Node01_02_PublicKey, TestCerts::sTestCert_Node01_02_PublicKey_Len); - memcpy(opKeysSerialized.Bytes() + TestCerts::sTestCert_Node01_02_PublicKey_Len, TestCerts::sTestCert_Node01_02_PrivateKey, - TestCerts::sTestCert_Node01_02_PrivateKey_Len); - ByteSpan rcacSpan(TestCerts::sTestCert_Root01_Chip, TestCerts::sTestCert_Root01_Chip_Len); ByteSpan nocSpan(TestCerts::sTestCert_Node01_02_Chip, TestCerts::sTestCert_Node01_02_Chip_Len); ReturnErrorOnFailure( - opKeysSerialized.SetLength(TestCerts::sTestCert_Node01_02_PublicKey_Len + TestCerts::sTestCert_Node01_02_PrivateKey_Len)); - ReturnErrorOnFailure(opKey_Node01_02.Deserialize(opKeysSerialized)); + opKey_Node01_02.ImportRawKeypair(TestCerts::sTestCert_Node01_02_PrivateKey, TestCerts::sTestCert_Node01_02_PrivateKey_Len, + TestCerts::sTestCert_Node01_02_PublicKey, TestCerts::sTestCert_Node01_02_PublicKey_Len)); ReturnErrorOnFailure(fabricTable.AddNewPendingTrustedRootCert(rcacSpan)); @@ -147,22 +151,17 @@ static CHIP_ERROR LoadTestFabric_Node01_02(nlTestSuite * inSuite, FabricTable & */ static CHIP_ERROR LoadTestFabric_Node02_01(nlTestSuite * inSuite, FabricTable & fabricTable, bool doCommit) { - Crypto::P256SerializedKeypair opKeysSerialized; FabricIndex fabricIndex; static Crypto::P256Keypair opKey_Node02_01; - memcpy(opKeysSerialized.Bytes(), TestCerts::sTestCert_Node02_01_PublicKey, TestCerts::sTestCert_Node02_01_PublicKey_Len); - memcpy(opKeysSerialized.Bytes() + TestCerts::sTestCert_Node02_01_PublicKey_Len, TestCerts::sTestCert_Node02_01_PrivateKey, - TestCerts::sTestCert_Node02_01_PrivateKey_Len); - ByteSpan rcacSpan(TestCerts::sTestCert_Root02_Chip, TestCerts::sTestCert_Root02_Chip_Len); ByteSpan icacSpan(TestCerts::sTestCert_ICA02_Chip, TestCerts::sTestCert_ICA02_Chip_Len); ByteSpan nocSpan(TestCerts::sTestCert_Node02_01_Chip, TestCerts::sTestCert_Node02_01_Chip_Len); NL_TEST_ASSERT(inSuite, - opKeysSerialized.SetLength(TestCerts::sTestCert_Node02_01_PublicKey_Len + - TestCerts::sTestCert_Node02_01_PrivateKey_Len) == CHIP_NO_ERROR); - NL_TEST_ASSERT(inSuite, opKey_Node02_01.Deserialize(opKeysSerialized) == CHIP_NO_ERROR); + opKey_Node02_01.ImportRawKeypair( + TestCerts::sTestCert_Node02_01_PrivateKey, TestCerts::sTestCert_Node02_01_PrivateKey_Len, + TestCerts::sTestCert_Node02_01_PublicKey, TestCerts::sTestCert_Node02_01_PublicKey_Len) == CHIP_NO_ERROR); NL_TEST_ASSERT(inSuite, fabricTable.AddNewPendingTrustedRootCert(rcacSpan) == CHIP_NO_ERROR); @@ -694,8 +693,13 @@ void TestBasicAddNocUpdateNocFlow(nlTestSuite * inSuite, void * inContext) NL_TEST_ASSERT_SUCCESS(inSuite, fabricTable.CommitPendingFabricData()); NL_TEST_ASSERT_EQUALS(inSuite, fabricTable.FabricCount(), 2); +#if !CHIP_CRYPTO_PSA NL_TEST_ASSERT_EQUALS(inSuite, storage.GetNumKeys(), (numStorageAfterFirstAdd + 5)); // 3 opcerts + fabric metadata + 1 operational key +#else + NL_TEST_ASSERT_EQUALS(inSuite, storage.GetNumKeys(), + (numStorageAfterFirstAdd + 4)); // 3 opcerts + fabric metadata +#endif // Validate contents const auto * fabricInfo = fabricTable.FindFabricWithIndex(2); @@ -1037,8 +1041,13 @@ void TestAddMultipleSameRootDifferentFabricId(nlTestSuite * inSuite, void * inCo NL_TEST_ASSERT(inSuite, fabricInfo->GetFabricLabel().size() == 0); } } + size_t numStorageKeysAfterFirstAdd = storage.GetNumKeys(); +#if !CHIP_CRYPTO_PSA NL_TEST_ASSERT(inSuite, numStorageKeysAfterFirstAdd == 7); // Metadata, index, 3 certs, 1 opkey, last known good time +#else + NL_TEST_ASSERT(inSuite, numStorageKeysAfterFirstAdd == 6); // Metadata, index, 3 certs, last known good time +#endif // Second scope: add FabricID 2222, node ID 66, same root as first { @@ -1079,8 +1088,13 @@ void TestAddMultipleSameRootDifferentFabricId(nlTestSuite * inSuite, void * inCo NL_TEST_ASSERT(inSuite, fabricInfo->GetFabricLabel().size() == 0); } } + size_t numStorageKeysAfterSecondAdd = storage.GetNumKeys(); +#if !CHIP_CRYPTO_PSA NL_TEST_ASSERT(inSuite, numStorageKeysAfterSecondAdd == (numStorageKeysAfterFirstAdd + 5)); // Add 3 certs, 1 metadata, 1 opkey +#else + NL_TEST_ASSERT(inSuite, numStorageKeysAfterSecondAdd == (numStorageKeysAfterFirstAdd + 4)); // Add 3 certs, 1 metadata, 1 opkey +#endif } void TestAddMultipleSameFabricIdDifferentRoot(nlTestSuite * inSuite, void * inContext) @@ -1144,8 +1158,13 @@ void TestAddMultipleSameFabricIdDifferentRoot(nlTestSuite * inSuite, void * inCo NL_TEST_ASSERT(inSuite, fabricInfo->GetFabricLabel().size() == 0); } } + size_t numStorageKeysAfterFirstAdd = storage.GetNumKeys(); +#if !CHIP_CRYPTO_PSA NL_TEST_ASSERT(inSuite, numStorageKeysAfterFirstAdd == 7); // Metadata, index, 3 certs, 1 opkey, last known good time +#else + NL_TEST_ASSERT(inSuite, numStorageKeysAfterFirstAdd == 6); // Metadata, index, 3 certs, last known good time +#endif // Second scope: add FabricID 1111, node ID 66, different root from first { @@ -1186,8 +1205,13 @@ void TestAddMultipleSameFabricIdDifferentRoot(nlTestSuite * inSuite, void * inCo NL_TEST_ASSERT(inSuite, fabricInfo->GetFabricLabel().size() == 0); } } + size_t numStorageKeysAfterSecondAdd = storage.GetNumKeys(); +#if !CHIP_CRYPTO_PSA NL_TEST_ASSERT(inSuite, numStorageKeysAfterSecondAdd == (numStorageKeysAfterFirstAdd + 5)); // Add 3 certs, 1 metadata, 1 opkey +#else + NL_TEST_ASSERT(inSuite, numStorageKeysAfterSecondAdd == (numStorageKeysAfterFirstAdd + 4)); // Add 3 certs, 1 metadata +#endif } void TestPersistence(nlTestSuite * inSuite, void * inContext) @@ -1376,10 +1400,17 @@ void TestPersistence(nlTestSuite * inSuite, void * inContext) } } +#if !CHIP_CRYPTO_PSA // Global: Last known good time + fabric index = 2 // Fabric 1111: Metadata, 1 opkey, RCAC/ICAC/NOC = 5 // Fabric 2222: Metadata, 1 opkey, RCAC/NOC = 4 NL_TEST_ASSERT(inSuite, storage.GetNumKeys() == (2 + 5 + 4)); +#else + // Global: Last known good time + fabric index = 2 + // Fabric 1111: Metadata, RCAC/ICAC/NOC = 4 + // Fabric 2222: Metadata, RCAC/NOC = 3 + NL_TEST_ASSERT(inSuite, storage.GetNumKeys() == (2 + 4 + 3)); +#endif // Second scope: Validate that a fresh FabricTable loads the previously committed fabrics on Init. { @@ -1631,8 +1662,13 @@ void TestAddNocFailSafe(nlTestSuite * inSuite, void * inContext) NL_TEST_ASSERT_SUCCESS(inSuite, fabricTable.CommitPendingFabricData()); NL_TEST_ASSERT_EQUALS(inSuite, fabricTable.FabricCount(), 1); +#if !CHIP_CRYPTO_PSA NL_TEST_ASSERT_EQUALS(inSuite, storage.GetNumKeys(), (numStorageAfterRevert + 5)); // 3 opcerts + fabric metadata + 1 operational key +#else + NL_TEST_ASSERT_EQUALS(inSuite, storage.GetNumKeys(), + (numStorageAfterRevert + 4)); // 3 opcerts + fabric metadata +#endif // Validate contents const auto * fabricInfo = fabricTable.FindFabricWithIndex(1); @@ -1777,8 +1813,13 @@ void TestUpdateNocFailSafe(nlTestSuite * inSuite, void * inContext) NL_TEST_ASSERT_SUCCESS(inSuite, fabricTable.CommitPendingFabricData()); NL_TEST_ASSERT_EQUALS(inSuite, fabricTable.FabricCount(), 1); +#if !CHIP_CRYPTO_PSA NL_TEST_ASSERT_EQUALS(inSuite, storage.GetNumKeys(), (numStorageKeysAtStart + 6)); // 3 opcerts + fabric metadata + 1 operational key + LKGT + fabric index +#else + NL_TEST_ASSERT_EQUALS(inSuite, storage.GetNumKeys(), + (numStorageKeysAtStart + 5)); // 3 opcerts + fabric metadata + LKGT + fabric index +#endif // Validate contents const auto * fabricInfo = fabricTable.FindFabricWithIndex(1); @@ -2155,8 +2196,13 @@ void TestFabricLabelChange(nlTestSuite * inSuite, void * inContext) NL_TEST_ASSERT(inSuite, fabricInfo->GetFabricLabel().size() == 0); } } + size_t numStorageKeysAfterFirstAdd = storage.GetNumKeys(); +#if !CHIP_CRYPTO_PSA NL_TEST_ASSERT(inSuite, numStorageKeysAfterFirstAdd == 7); // Metadata, index, 3 certs, 1 opkey, last known good time +#else + NL_TEST_ASSERT(inSuite, numStorageKeysAfterFirstAdd == 6); // Metadata, index, 3 certs, last known good time +#endif // Second scope: set FabricLabel to "acme fabric", make sure it cannot be reverted { @@ -2386,7 +2432,11 @@ void TestAddNocRootCollision(nlTestSuite * inSuite, void * inContext) } } size_t numStorageKeysAfterFirstAdd = storage.GetNumKeys(); +#if !CHIP_CRYPTO_PSA NL_TEST_ASSERT(inSuite, numStorageKeysAfterFirstAdd == 7); // Metadata, index, 3 certs, 1 opkey, last known good time +#else + NL_TEST_ASSERT(inSuite, numStorageKeysAfterFirstAdd == 6); // Metadata, index, 3 certs, last known good time +#endif // Second scope: add FabricID 1111, node ID 55 *again* --> Collision of Root/FabricID with existing { @@ -2490,8 +2540,11 @@ void TestAddNocRootCollision(nlTestSuite * inSuite, void * inContext) } } size_t numStorageKeysAfterSecondAdd = storage.GetNumKeys(); - +#if !CHIP_CRYPTO_PSA NL_TEST_ASSERT(inSuite, numStorageKeysAfterSecondAdd == (numStorageKeysAfterFirstAdd + 5)); // Metadata, 3 certs, 1 opkey +#else + NL_TEST_ASSERT(inSuite, numStorageKeysAfterSecondAdd == (numStorageKeysAfterFirstAdd + 4)); // Metadata, 3 certs +#endif } void TestInvalidChaining(nlTestSuite * inSuite, void * inContext) @@ -2760,8 +2813,11 @@ void TestCommitMarker(nlTestSuite * inSuite, void * inContext) } numStorageKeysAfterFirstAdd = storage.GetNumKeys(); +#if !CHIP_CRYPTO_PSA NL_TEST_ASSERT(inSuite, numStorageKeysAfterFirstAdd == 7); // Metadata, index, 3 certs, 1 opkey, last known good time - +#else + NL_TEST_ASSERT(inSuite, numStorageKeysAfterFirstAdd == 6); // Metadata, index, 3 certs, last known good time +#endif // The following test requires test methods not available on all builds. // TODO: Debug why some CI jobs don't set it properly. #if CONFIG_BUILD_FOR_HOST_UNIT_TEST diff --git a/src/crypto/CHIPCryptoPAL.h b/src/crypto/CHIPCryptoPAL.h index a5e2c080f012a6..bab60a3a8200df 100644 --- a/src/crypto/CHIPCryptoPAL.h +++ b/src/crypto/CHIPCryptoPAL.h @@ -492,6 +492,20 @@ class P256Keypair : public P256KeypairBase **/ CHIP_ERROR Initialize(ECPKeyTarget key_target) override; + /** + * @brief Import a raw key pair (bytes) into the keypair + * @return Returns a CHIP_ERROR on error, CHIP_NO_ERROR otherwise + **/ + CHIP_ERROR ImportRawKeypair(const uint8_t * key_data, size_t key_data_size); + CHIP_ERROR ImportRawKeypair(ByteSpan private_key, ByteSpan public_key) + { + return ImportRawKeypair(private_key.data(), private_key.size(), public_key.data(), public_key.size()); + } + + CHIP_ERROR ImportRawKeypair(const uint8_t * private_key, const size_t private_key_size, const uint8_t * public_key, + const size_t public_key_size); + CHIP_ERROR ImportRawKeypair(const ByteSpan & key_pair) { return ImportRawKeypair(key_pair.data(), key_pair.size()); } + /** * @brief Serialize the keypair. * @return Returns a CHIP_ERROR on error, CHIP_NO_ERROR otherwise @@ -545,6 +559,13 @@ class P256Keypair : public P256KeypairBase /** Release resources associated with this key pair */ void Clear(); + /** + * @brief Copy the keypair in input into this keypair. + * @param other The keypair to copy + * @return Returns a CHIP_ERROR on error, CHIP_NO_ERROR otherwise + **/ + CHIP_ERROR Copy(const P256Keypair & other); + protected: P256PublicKey mPublicKey; mutable P256KeypairContext mKeypair; diff --git a/src/crypto/CHIPCryptoPALOpenSSL.cpp b/src/crypto/CHIPCryptoPALOpenSSL.cpp index e181190a109bb6..ce5db3b3e1ccf5 100644 --- a/src/crypto/CHIPCryptoPALOpenSSL.cpp +++ b/src/crypto/CHIPCryptoPALOpenSSL.cpp @@ -1055,6 +1055,24 @@ CHIP_ERROR P256Keypair::Initialize(ECPKeyTarget key_target) return error; } +CHIP_ERROR P256Keypair::ImportRawKeypair(const uint8_t * private_key, const size_t private_key_size, const uint8_t * public_key, + const size_t public_key_size) +{ + Crypto::P256SerializedKeypair serialized_keypair; + ReturnErrorOnFailure(serialized_keypair.SetLength(private_key_size + public_key_size)); + memcpy(serialized_keypair.Bytes(), public_key, public_key_size); + memcpy(serialized_keypair.Bytes() + public_key_size, private_key, private_key_size); + return this->Deserialize(serialized_keypair); +} + +CHIP_ERROR P256Keypair::ImportRawKeypair(const uint8_t * key_data, size_t key_data_size) +{ + Crypto::P256SerializedKeypair serialized_keypair; + memcpy(serialized_keypair.Bytes(), key_data, key_data_size); + serialized_keypair.SetLength(key_data_size); + return this->Deserialize(serialized_keypair); +} + CHIP_ERROR P256Keypair::Serialize(P256SerializedKeypair & output) const { CHIP_ERROR error = CHIP_NO_ERROR; @@ -1177,6 +1195,28 @@ void P256Keypair::Clear() } } +CHIP_ERROR P256Keypair::Copy(const P256Keypair & other) +{ + CHIP_ERROR error = CHIP_NO_ERROR; + P256SerializedKeypair serialized; + + if (this == &other) + { + return error; + } + + error = other.Serialize(serialized); + VerifyOrExit(error == CHIP_NO_ERROR, error = CHIP_ERROR_INTERNAL); + + error = this->Deserialize(serialized); + VerifyOrExit(error == CHIP_NO_ERROR, error = CHIP_ERROR_INTERNAL); + + mInitialized = true; + +exit: + return error; +} + P256Keypair::~P256Keypair() { Clear(); diff --git a/src/crypto/CHIPCryptoPALPSA.cpp b/src/crypto/CHIPCryptoPALPSA.cpp index e8d4b75c9221b1..34cdff86d46875 100644 --- a/src/crypto/CHIPCryptoPALPSA.cpp +++ b/src/crypto/CHIPCryptoPALPSA.cpp @@ -100,6 +100,18 @@ bool isValidTag(const uint8_t * tag, size_t tag_length) return tag != nullptr && (tag_length == 8 || tag_length == 12 || tag_length == 16); } +psa_key_attributes_t configure_ecc_key_pair_attributes() +{ + psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT; + + 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_SHA_256)); + psa_set_key_usage_flags(&attributes, PSA_KEY_USAGE_SIGN_MESSAGE | PSA_KEY_USAGE_COPY); + + return attributes; +} + } // namespace CHIP_ERROR AES_CCM_encrypt(const uint8_t * plaintext, size_t plaintext_length, const uint8_t * aad, size_t aad_length, @@ -667,6 +679,8 @@ CHIP_ERROR P256Keypair::Initialize(ECPKeyTarget key_target) 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_lifetime(&attributes, PSA_KEY_PERSISTENCE_VOLATILE); + if (key_target == ECPKeyTarget::ECDH) { psa_set_key_algorithm(&attributes, PSA_ALG_ECDH); @@ -675,7 +689,7 @@ CHIP_ERROR P256Keypair::Initialize(ECPKeyTarget key_target) else if (key_target == ECPKeyTarget::ECDSA) { psa_set_key_algorithm(&attributes, PSA_ALG_ECDSA(PSA_ALG_SHA_256)); - psa_set_key_usage_flags(&attributes, PSA_KEY_USAGE_EXPORT | PSA_KEY_USAGE_SIGN_MESSAGE); + psa_set_key_usage_flags(&attributes, PSA_KEY_USAGE_SIGN_MESSAGE | PSA_KEY_USAGE_COPY); } else { @@ -698,22 +712,61 @@ CHIP_ERROR P256Keypair::Initialize(ECPKeyTarget key_target) return error; } +CHIP_ERROR P256Keypair::ImportRawKeypair(const uint8_t * private_key, const size_t private_key_size, const uint8_t * public_key, + const size_t public_key_size) +{ + psa_key_attributes_t attributes = configure_ecc_key_pair_attributes(); + psa_key_id_t key_id; + psa_status_t status; + + status = psa_import_key(&attributes, private_key, private_key_size, &key_id); + VerifyOrReturnError(status == PSA_SUCCESS, CHIP_ERROR_INTERNAL); + + memcpy(mPublicKey.Bytes(), public_key, public_key_size); + memcpy(mKeypair.mBytes, &key_id, sizeof(psa_key_id_t)); + mInitialized = true; + + return CHIP_NO_ERROR; +} + +CHIP_ERROR P256Keypair::ImportRawKeypair(const uint8_t * key_data, size_t key_data_size) +{ + CHIP_ERROR error = CHIP_NO_ERROR; + psa_key_attributes_t attributes = configure_ecc_key_pair_attributes(); + PsaP256KeypairContext & context = ToPsaContext(mKeypair); + psa_status_t status; + + VerifyOrExit(key_data_size == kP256_PublicKey_Length + kP256_PrivateKey_Length, error = CHIP_ERROR_INTERNAL); + + status = psa_import_key(&attributes, key_data + kP256_PublicKey_Length, kP256_PrivateKey_Length, &context.key_id); + VerifyOrExit(status == PSA_SUCCESS, error = CHIP_ERROR_INTERNAL); + + memcpy(mPublicKey.Bytes(), key_data, kP256_PublicKey_Length); + memcpy(mKeypair.mBytes, &context.key_id, sizeof(psa_key_id_t)); + mInitialized = true; + +exit: + logPsaError(status); + + return error; +} + CHIP_ERROR P256Keypair::Serialize(P256SerializedKeypair & output) const { - CHIP_ERROR error = CHIP_NO_ERROR; - psa_status_t status = PSA_SUCCESS; - const PsaP256KeypairContext & context = ToConstPsaContext(mKeypair); - const size_t outputSize = output.Length() == 0 ? output.Capacity() : output.Length(); + CHIP_ERROR error = CHIP_NO_ERROR; + psa_status_t status = PSA_SUCCESS; + const size_t outputSize = output.Length() == 0 ? output.Capacity() : output.Length(); Encoding::BufferWriter bbuf(output.Bytes(), outputSize); - uint8_t privateKey[kP256_PrivateKey_Length]; - size_t privateKeyLength = 0; + size_t privateKeyLength = sizeof(psa_key_id_t); - status = psa_export_key(context.key_id, privateKey, sizeof(privateKey), &privateKeyLength); - VerifyOrExit(status == PSA_SUCCESS, error = CHIP_ERROR_INTERNAL); - VerifyOrExit(privateKeyLength == kP256_PrivateKey_Length, error = CHIP_ERROR_INTERNAL); + // For PSA, private keys should not be passed around directly and thus + // the key id should be serialized, alongside the public key, instead. + // The key id is guaranteed to be smaller than the full private key size + // and thus no changes are required to the default sizes in the + // P256SerializedKeypair type. bbuf.Put(mPublicKey, mPublicKey.Length()); - bbuf.Put(privateKey, privateKeyLength); + bbuf.Put(mKeypair.mBytes, privateKeyLength); VerifyOrExit(bbuf.Fit(), error = CHIP_ERROR_BUFFER_TOO_SMALL); error = output.SetLength(bbuf.Needed()); @@ -725,23 +778,28 @@ CHIP_ERROR P256Keypair::Serialize(P256SerializedKeypair & output) const CHIP_ERROR P256Keypair::Deserialize(P256SerializedKeypair & input) { - VerifyOrReturnError(input.Length() == mPublicKey.Length() + kP256_PrivateKey_Length, CHIP_ERROR_INVALID_ARGUMENT); - CHIP_ERROR error = CHIP_NO_ERROR; psa_status_t status = PSA_SUCCESS; - psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT; PsaP256KeypairContext & context = ToPsaContext(mKeypair); + size_t publicKeyLength = 0; Encoding::BufferWriter bbuf(mPublicKey, mPublicKey.Length()); Clear(); - 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_SHA_256)); - psa_set_key_usage_flags(&attributes, PSA_KEY_USAGE_EXPORT | PSA_KEY_USAGE_SIGN_MESSAGE); + // The serialized data for PSA will provide us with the public key and the private key id. + // The private key itself will still be in secure storage and thus we only need to ensure + // that the deserialized key id corresponds to a valid, stored key. + + // Store the deserialized private key id to the keypair. + // This is guaranteed to fit due to the checks made during the serialize function. + memcpy(mKeypair.mBytes, input.ConstBytes() + mPublicKey.Length(), sizeof(psa_key_id_t)); - status = psa_import_key(&attributes, input.ConstBytes() + mPublicKey.Length(), kP256_PrivateKey_Length, &context.key_id); + // Check that the deserialized private key id is valid. We can do this by attempting to + // export the corresponding public key. We can then also verify that the exported key + // matches the deserialized one. + status = psa_export_public_key(context.key_id, mPublicKey.Bytes(), mPublicKey.Length(), &publicKeyLength); VerifyOrExit(status == PSA_SUCCESS, error = CHIP_ERROR_INTERNAL); + VerifyOrExit(publicKeyLength == mPublicKey.Length(), error = CHIP_ERROR_INTERNAL); bbuf.Put(input.ConstBytes(), mPublicKey.Length()); VerifyOrExit(bbuf.Fit(), error = CHIP_ERROR_NO_MEMORY); @@ -765,6 +823,33 @@ void P256Keypair::Clear() } } +CHIP_ERROR P256Keypair::Copy(const P256Keypair & other) +{ + CHIP_ERROR error = CHIP_NO_ERROR; + psa_status_t status = PSA_SUCCESS; + + if (this == &other) + { + return error; + } + + psa_key_attributes_t attributes = configure_ecc_key_pair_attributes(); + + Clear(); + + status = psa_copy_key(ToPsaContext(other.mKeypair).key_id, &attributes, &ToPsaContext(mKeypair).key_id); + VerifyOrExit(status == PSA_SUCCESS, error = CHIP_ERROR_INTERNAL); + + memcpy(mPublicKey.Bytes(), other.mPublicKey.ConstBytes(), other.mPublicKey.Length()); + + mInitialized = true; + +exit: + psa_reset_key_attributes(&attributes); + + return error; +} + P256Keypair::~P256Keypair() { Clear(); diff --git a/src/crypto/CHIPCryptoPALmbedTLS.cpp b/src/crypto/CHIPCryptoPALmbedTLS.cpp index 92ec3048fe8de6..840dd09a2d1bd0 100644 --- a/src/crypto/CHIPCryptoPALmbedTLS.cpp +++ b/src/crypto/CHIPCryptoPALmbedTLS.cpp @@ -736,6 +736,24 @@ CHIP_ERROR P256Keypair::Initialize(ECPKeyTarget key_target) return error; } +CHIP_ERROR P256Keypair::ImportRawKeypair(const uint8_t * private_key, const size_t private_key_size, const uint8_t * public_key, + const size_t public_key_size) +{ + Crypto::P256SerializedKeypair serialized_keypair; + ReturnErrorOnFailure(serialized_keypair.SetLength(private_key_size + public_key_size)); + memcpy(serialized_keypair.Bytes(), public_key, public_key_size); + memcpy(serialized_keypair.Bytes() + public_key_size, private_key, private_key_size); + return this->Deserialize(serialized_keypair); +} + +CHIP_ERROR P256Keypair::ImportRawKeypair(const uint8_t * key_data, size_t key_data_size) +{ + Crypto::P256SerializedKeypair serialized_keypair; + memcpy(serialized_keypair.Bytes(), key_data, key_data_size); + serialized_keypair.SetLength(key_data_size); + return this->Deserialize(serialized_keypair); +} + CHIP_ERROR P256Keypair::Serialize(P256SerializedKeypair & output) const { const mbedtls_ecp_keypair * keypair = to_const_keypair(&mKeypair); @@ -812,6 +830,28 @@ void P256Keypair::Clear() } } +CHIP_ERROR P256Keypair::Copy(const P256Keypair & other) +{ + CHIP_ERROR error = CHIP_NO_ERROR; + P256SerializedKeypair serialized; + + if (this == &other) + { + return error; + } + + error = other.Serialize(serialized); + VerifyOrExit(error == CHIP_NO_ERROR, error = CHIP_ERROR_INTERNAL); + + error = this->Deserialize(serialized); + VerifyOrExit(error == CHIP_NO_ERROR, error = CHIP_ERROR_INTERNAL); + + mInitialized = true; + +exit: + return error; +} + P256Keypair::~P256Keypair() { Clear(); @@ -878,7 +918,8 @@ CHIP_ERROR VerifyCertificateSigningRequest(const uint8_t * csr_buf, size_t csr_l #if defined(MBEDTLS_X509_CSR_PARSE_C) ReturnErrorOnFailure(VerifyCertificateSigningRequestFormat(csr_buf, csr_length)); - // TODO: For some embedded targets, mbedTLS library doesn't have mbedtls_x509_csr_parse_der, and mbedtls_x509_csr_parse_free. + // TODO: For some embedded targets, mbedTLS library doesn't have mbedtls_x509_csr_parse_der, and + // mbedtls_x509_csr_parse_free. // Taking a step back, embedded targets likely will not process CSR requests. Adding this action item to reevaluate // this if there's a need for this processing for embedded targets. CHIP_ERROR error = CHIP_NO_ERROR; diff --git a/src/crypto/PSAOperationalKeystore.cpp b/src/crypto/PSAOperationalKeystore.cpp index 980994696e3047..0b961c08653377 100644 --- a/src/crypto/PSAOperationalKeystore.cpp +++ b/src/crypto/PSAOperationalKeystore.cpp @@ -24,43 +24,49 @@ namespace chip { namespace Crypto { -PSAOperationalKeystore::PersistentP256Keypair::PersistentP256Keypair(FabricIndex fabricIndex) +PSAOperationalKeystore::PersistentP256Keypair::PersistentP256Keypair(FabricIndex fabricIndex) : + mKeyId(ToPsaContext(mKeypair).key_id) { - ToPsaContext(mKeypair).key_id = MakeOperationalKeyId(fabricIndex); - mInitialized = true; + mKeyId = MakeOperationalKeyId(fabricIndex); + mInitialized = true; } PSAOperationalKeystore::PersistentP256Keypair::~PersistentP256Keypair() { // 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; -} - -inline psa_key_id_t PSAOperationalKeystore::PersistentP256Keypair::GetKeyId() const -{ - return ToConstPsaContext(mKeypair).key_id; + mKeyId = 0; } bool PSAOperationalKeystore::PersistentP256Keypair::Exists() const { psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT; - psa_status_t status = psa_get_key_attributes(GetKeyId(), &attributes); + psa_status_t status = psa_get_key_attributes(mKeyId, &attributes); psa_reset_key_attributes(&attributes); return status == PSA_SUCCESS; } -CHIP_ERROR PSAOperationalKeystore::PersistentP256Keypair::Generate() +CHIP_ERROR PSAOperationalKeystore::PersistentP256Keypair::Destroy() { + psa_status_t status = psa_destroy_key(mKeyId); + + ReturnErrorCodeIf(status == PSA_ERROR_INVALID_HANDLE, CHIP_ERROR_INVALID_FABRIC_INDEX); + VerifyOrReturnError(status == PSA_SUCCESS, CHIP_ERROR_INTERNAL); + mKeyId = 0; + + return CHIP_NO_ERROR; +} + +CHIP_ERROR PSAOperationalKeystore::PersistentP256Keypair::Commit(const P256Keypair & pending) +{ + // Upcast to access the protected member + psa_key_id_t pending_key_id = ToPsaContext(static_cast(pending).mKeypair).key_id; + 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)); @@ -68,14 +74,14 @@ 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_set_key_lifetime(&attributes, PSA_KEY_LIFETIME_PERSISTENT); - psa_set_key_id(&attributes, GetKeyId()); + psa_set_key_id(&attributes, mKeyId); - status = psa_generate_key(&attributes, &keyId); - VerifyOrExit(status == PSA_SUCCESS, error = CHIP_ERROR_INTERNAL); + // Destroy the previous key if it was present otherwise the copy would fail + psa_destroy_key(mKeyId); + + status = psa_copy_key(pending_key_id, &attributes, &mKeyId); - 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); @@ -83,16 +89,6 @@ CHIP_ERROR PSAOperationalKeystore::PersistentP256Keypair::Generate() return error; } -CHIP_ERROR PSAOperationalKeystore::PersistentP256Keypair::Destroy() -{ - psa_status_t status = psa_destroy_key(GetKeyId()); - - ReturnErrorCodeIf(status == PSA_ERROR_INVALID_HANDLE, CHIP_ERROR_INVALID_FABRIC_INDEX); - VerifyOrReturnError(status == PSA_SUCCESS, CHIP_ERROR_INTERNAL); - - return CHIP_NO_ERROR; -} - bool PSAOperationalKeystore::HasPendingOpKeypair() const { return mPendingFabricIndex != kUndefinedFabricIndex; @@ -117,15 +113,17 @@ CHIP_ERROR PSAOperationalKeystore::NewOpKeypairForFabric(FabricIndex fabricIndex if (HasPendingOpKeypair()) { VerifyOrReturnError(fabricIndex == mPendingFabricIndex, CHIP_ERROR_INVALID_FABRIC_INDEX); + // release the existing key to create a new one + ReleasePendingKeypair(); } if (mPendingKeypair == nullptr) { - mPendingKeypair = Platform::New(fabricIndex); + mPendingKeypair = Platform::New(); } VerifyOrReturnError(mPendingKeypair != nullptr, CHIP_ERROR_NO_MEMORY); - ReturnErrorOnFailure(mPendingKeypair->Generate()); + ReturnErrorOnFailure(mPendingKeypair->Initialize(ECPKeyTarget::ECDSA)); size_t csrLength = outCertificateSigningRequest.size(); ReturnErrorOnFailure(mPendingKeypair->NewCertificateSigningRequest(outCertificateSigningRequest.data(), csrLength)); @@ -149,6 +147,8 @@ CHIP_ERROR PSAOperationalKeystore::CommitOpKeypairForFabric(FabricIndex fabricIn VerifyOrReturnError(IsValidFabricIndex(fabricIndex) && mPendingFabricIndex == fabricIndex, CHIP_ERROR_INVALID_FABRIC_INDEX); VerifyOrReturnError(mIsPendingKeypairActive, CHIP_ERROR_INCORRECT_STATE); + PersistentP256Keypair(fabricIndex).Commit(*mPendingKeypair); + ReleasePendingKeypair(); return CHIP_NO_ERROR; @@ -170,7 +170,6 @@ CHIP_ERROR PSAOperationalKeystore::RemoveOpKeypairForFabric(FabricIndex fabricIn void PSAOperationalKeystore::RevertPendingKeypair() { VerifyOrReturn(HasPendingOpKeypair()); - mPendingKeypair->Destroy(); ReleasePendingKeypair(); } @@ -184,11 +183,13 @@ CHIP_ERROR PSAOperationalKeystore::SignWithOpKeypair(FabricIndex fabricIndex, co VerifyOrReturnError(mIsPendingKeypairActive, CHIP_ERROR_INVALID_FABRIC_INDEX); return mPendingKeypair->ECDSA_sign_msg(message.data(), message.size(), outSignature); } + else + { + PersistentP256Keypair keypair(fabricIndex); + VerifyOrReturnError(keypair.Exists(), CHIP_ERROR_INVALID_FABRIC_INDEX); - PersistentP256Keypair keypair(fabricIndex); - VerifyOrReturnError(keypair.Exists(), CHIP_ERROR_INVALID_FABRIC_INDEX); - - return keypair.ECDSA_sign_msg(message.data(), message.size(), outSignature); + return keypair.ECDSA_sign_msg(message.data(), message.size(), outSignature); + } } Crypto::P256Keypair * PSAOperationalKeystore::AllocateEphemeralKeypairForCASE() diff --git a/src/crypto/PSAOperationalKeystore.h b/src/crypto/PSAOperationalKeystore.h index 89c3edc7fe7607..2a96534dd00c61 100644 --- a/src/crypto/PSAOperationalKeystore.h +++ b/src/crypto/PSAOperationalKeystore.h @@ -49,17 +49,21 @@ class PSAOperationalKeystore final : public OperationalKeystore using P256Keypair::NewCertificateSigningRequest; using P256Keypair::Pubkey; - psa_key_id_t GetKeyId() const; bool Exists() const; - CHIP_ERROR Generate(); CHIP_ERROR Destroy(); + CHIP_ERROR Commit(const P256Keypair & pending); + + private: + using P256Keypair::mInitialized; + using P256Keypair::mKeypair; + psa_key_id_t & mKeyId; }; void ReleasePendingKeypair(); - PersistentP256Keypair * mPendingKeypair = nullptr; - FabricIndex mPendingFabricIndex = kUndefinedFabricIndex; - bool mIsPendingKeypairActive = false; + P256Keypair * mPendingKeypair = nullptr; + FabricIndex mPendingFabricIndex = kUndefinedFabricIndex; + bool mIsPendingKeypairActive = false; }; } // namespace Crypto diff --git a/src/crypto/tests/CHIPCryptoPALTest.cpp b/src/crypto/tests/CHIPCryptoPALTest.cpp index 5f377841935725..74f3460e33cfdc 100644 --- a/src/crypto/tests/CHIPCryptoPALTest.cpp +++ b/src/crypto/tests/CHIPCryptoPALTest.cpp @@ -1388,6 +1388,64 @@ static void TestKeypair_Serialize(nlTestSuite * inSuite, void * inContext) NL_TEST_ASSERT(inSuite, keypair.Pubkey().ECDSA_validate_msg_signature(test_msg, msglen, test_sig) == CHIP_NO_ERROR); } +uint8_t raw_keypair[] = { 0x04, 0x38, 0x9b, 0x9e, 0xc4, 0x9e, 0x84, 0x48, 0xc0, 0x8f, 0x34, 0x14, 0x9c, 0x3e, 0xa9, 0x47, 0xd1, + 0x49, 0xe2, 0xbb, 0xf5, 0x93, 0x93, 0x47, 0x5f, 0xa9, 0x16, 0x71, 0x3a, 0xc7, 0x81, 0xd2, 0x73, 0xf8, + 0xb5, 0x29, 0xb2, 0x8f, 0xbe, 0xba, 0x1e, 0x3a, 0x27, 0xd1, 0x42, 0x67, 0xd4, 0x0c, 0x5e, 0xa7, 0x25, + 0x4b, 0x62, 0x57, 0x7d, 0x00, 0x30, 0x30, 0x27, 0xd8, 0xa8, 0x4f, 0xa1, 0x11, 0xa0, 0xe7, 0x8e, 0xa5, + 0x02, 0xbd, 0xc4, 0x75, 0x3c, 0x0b, 0x87, 0x68, 0xd4, 0x3b, 0x68, 0x17, 0x40, 0xca, 0x29, 0xc4, 0x41, + 0x63, 0xaa, 0xb8, 0x3a, 0x26, 0xfa, 0xa3, 0xf1, 0x4a, 0x11, 0x30, 0xff }; +unsigned int raw_keypair_len = 97; + +const uint8_t raw_public_key[65] = { + 0x04, 0x46, 0x3a, 0xc6, 0x93, 0x42, 0x91, 0x0a, 0x0e, 0x55, 0x88, 0xfc, 0x6f, 0xf5, 0x6b, 0xb6, 0x3e, + 0x62, 0xec, 0xce, 0xcb, 0x14, 0x8f, 0x7d, 0x4e, 0xb0, 0x3e, 0xe5, 0x52, 0x60, 0x14, 0x15, 0x76, 0x7d, + 0x16, 0xa5, 0xc6, 0x63, 0xf7, 0x93, 0xe4, 0x91, 0x23, 0x26, 0x0b, 0x82, 0x97, 0xa7, 0xcd, 0x7e, 0x7c, + 0xfc, 0x7b, 0x31, 0x6b, 0x39, 0xd9, 0x8e, 0x90, 0xd2, 0x93, 0x77, 0x73, 0x8e, 0x82, +}; + +const uint8_t raw_private_key[32] = { + 0xaa, 0xb6, 0x00, 0xae, 0x8a, 0xe8, 0xaa, 0xb7, 0xd7, 0x36, 0x27, 0xc2, 0x17, 0xb7, 0xc2, 0x04, + 0x70, 0x9c, 0xa6, 0x94, 0x6a, 0xf5, 0xf2, 0xf7, 0x53, 0x08, 0x33, 0xa5, 0x2b, 0x44, 0xfb, 0xff, +}; + +static void TestKeypair_LoadFromRaw(nlTestSuite * inSuite, void * inContext) +{ + HeapChecker heapChecker(inSuite); + Test_P256Keypair keypair1; + Test_P256Keypair keypair2; + Test_P256Keypair keypair3; + Test_P256Keypair keypair4; + ByteSpan raw_keypair_bytespan = ByteSpan(raw_keypair, raw_keypair_len); + ByteSpan raw_public_key_bytespan = ByteSpan(raw_public_key, 65); + ByteSpan raw_private_key_bytespan = ByteSpan(raw_private_key, 32); + + NL_TEST_ASSERT(inSuite, keypair1.ImportRawKeypair(raw_keypair_bytespan) == CHIP_NO_ERROR); + NL_TEST_ASSERT(inSuite, keypair2.ImportRawKeypair(raw_keypair, raw_keypair_len) == CHIP_NO_ERROR); + NL_TEST_ASSERT(inSuite, keypair3.ImportRawKeypair(raw_private_key, 32, raw_public_key, 65) == CHIP_NO_ERROR); + NL_TEST_ASSERT(inSuite, keypair4.ImportRawKeypair(raw_private_key_bytespan, raw_public_key_bytespan) == CHIP_NO_ERROR); +} + +static void TestKeypair_Copy(nlTestSuite * inSuite, void * inContext) +{ + HeapChecker heapChecker(inSuite); + Test_P256Keypair keypair; + Test_P256Keypair keypair_dup; + + NL_TEST_ASSERT(inSuite, keypair.Initialize(ECPKeyTarget::ECDSA) == CHIP_NO_ERROR); + NL_TEST_ASSERT(inSuite, keypair_dup.Copy(keypair) == CHIP_NO_ERROR); + + const char * msg = "Test Message for Keygen"; + const uint8_t * test_msg = Uint8::from_const_char(msg); + size_t msglen = strlen(msg); + + P256ECDSASignature test_sig; + NL_TEST_ASSERT(inSuite, keypair.ECDSA_sign_msg(test_msg, msglen, test_sig) == CHIP_NO_ERROR); + NL_TEST_ASSERT(inSuite, keypair_dup.Pubkey().ECDSA_validate_msg_signature(test_msg, msglen, test_sig) == CHIP_NO_ERROR); + + NL_TEST_ASSERT(inSuite, keypair_dup.ECDSA_sign_msg(test_msg, msglen, test_sig) == CHIP_NO_ERROR); + NL_TEST_ASSERT(inSuite, keypair.Pubkey().ECDSA_validate_msg_signature(test_msg, msglen, test_sig) == CHIP_NO_ERROR); +} + static void TestSPAKE2P_spake2p_FEMul(nlTestSuite * inSuite, void * inContext) { HeapChecker heapChecker(inSuite); @@ -2687,6 +2745,8 @@ static const nlTest sTests[] = { NL_TEST_DEF("Test CSR Generation via P256Keypair method", TestCSR_GenByKeypair), NL_TEST_DEF("Test Direct CSR Generation", TestCSR_GenDirect), NL_TEST_DEF("Test Keypair Serialize", TestKeypair_Serialize), + NL_TEST_DEF("Test Keypair Load From Raw", TestKeypair_LoadFromRaw), + NL_TEST_DEF("Test Keypair Copy", TestKeypair_Copy), NL_TEST_DEF("Test Spake2p_spake2p FEMul", TestSPAKE2P_spake2p_FEMul), NL_TEST_DEF("Test Spake2p_spake2p FELoad/FEWrite", TestSPAKE2P_spake2p_FELoadWrite), NL_TEST_DEF("Test Spake2p_spake2p Mac", TestSPAKE2P_spake2p_Mac), diff --git a/src/crypto/tests/TestPSAOpKeyStore.cpp b/src/crypto/tests/TestPSAOpKeyStore.cpp index c8aef046010196..591421ef68d8b2 100644 --- a/src/crypto/tests/TestPSAOpKeyStore.cpp +++ b/src/crypto/tests/TestPSAOpKeyStore.cpp @@ -175,7 +175,7 @@ void TestEphemeralKeys(nlTestSuite * inSuite, void * inContext) /** * Test Suite. It lists all the test functions. */ -static const nlTest sTests[] = { NL_TEST_DEF("Test Basic Lifecycle of PersistentStorageOperationalKeystore", TestBasicLifeCycle), +static const nlTest sTests[] = { NL_TEST_DEF("Test Basic Lifecycle of PSAOperationalKeystore", TestBasicLifeCycle), NL_TEST_DEF("Test ephemeral key management", TestEphemeralKeys), NL_TEST_SENTINEL() }; /** diff --git a/src/messaging/tests/MessagingContext.cpp b/src/messaging/tests/MessagingContext.cpp index 295518d0811006..5733204fbab5bf 100644 --- a/src/messaging/tests/MessagingContext.cpp +++ b/src/messaging/tests/MessagingContext.cpp @@ -38,7 +38,9 @@ CHIP_ERROR MessagingContext::Init(TransportMgrBase * transport, IOContext * ioCo ReturnErrorOnFailure(PlatformMemoryUser::Init()); +#if !CHIP_CRYPTO_PSA ReturnErrorOnFailure(mOpKeyStore.Init(&mStorage)); +#endif ReturnErrorOnFailure(mOpCertStore.Init(&mStorage)); chip::FabricTable::InitParams initParams; @@ -80,7 +82,9 @@ void MessagingContext::Shutdown() mSessionManager.Shutdown(); mFabricTable.Shutdown(); mOpCertStore.Finish(); +#if !CHIP_CRYPTO_PSA mOpKeyStore.Finish(); +#endif } CHIP_ERROR MessagingContext::InitFromExisting(const MessagingContext & existing) diff --git a/src/messaging/tests/MessagingContext.h b/src/messaging/tests/MessagingContext.h index 156bb78bf3609e..9e7792d8c3a16a 100644 --- a/src/messaging/tests/MessagingContext.h +++ b/src/messaging/tests/MessagingContext.h @@ -18,7 +18,11 @@ #include #include +#if CHIP_CRYPTO_PSA +#include +#else #include +#endif #include #include #include @@ -182,7 +186,13 @@ class MessagingContext : public PlatformMemoryUser IOContext * mIOContext; TransportMgrBase * mTransport; // Only needed for InitFromExisting. chip::TestPersistentStorageDelegate mStorage; // for SessionManagerInit + +#if CHIP_CRYPTO_PSA + chip::Crypto::PSAOperationalKeystore mOpKeyStore; +#else chip::PersistentStorageOperationalKeystore mOpKeyStore; +#endif + chip::Credentials::PersistentStorageOpCertStore mOpCertStore; chip::Crypto::DefaultSessionKeystore mSessionKeystore; diff --git a/src/platform/Ameba/FactoryDataProvider.cpp b/src/platform/Ameba/FactoryDataProvider.cpp index ad1441b10593ba..48f3450588e687 100644 --- a/src/platform/Ameba/FactoryDataProvider.cpp +++ b/src/platform/Ameba/FactoryDataProvider.cpp @@ -129,16 +129,6 @@ const uint8_t kDacPrivateKey[] = { 0x70, 0x9c, 0xa6, 0x94, 0x6a, 0xf5, 0xf2, 0xf7, 0x53, 0x08, 0x33, 0xa5, 0x2b, 0x44, 0xfb, 0xff, }; -// TODO: This should be moved to a method of P256Keypair -CHIP_ERROR LoadKeypairFromRaw(ByteSpan private_key, ByteSpan public_key, Crypto::P256Keypair & keypair) -{ - Crypto::P256SerializedKeypair serialized_keypair; - ReturnErrorOnFailure(serialized_keypair.SetLength(private_key.size() + public_key.size())); - memcpy(serialized_keypair.Bytes(), public_key.data(), public_key.size()); - memcpy(serialized_keypair.Bytes() + public_key.size(), private_key.data(), private_key.size()); - return keypair.Deserialize(serialized_keypair); -} - CHIP_ERROR FactoryDataProvider::Init() { CHIP_ERROR err = CHIP_NO_ERROR; @@ -260,13 +250,13 @@ CHIP_ERROR FactoryDataProvider::SignWithDeviceAttestationKey(const ByteSpan & me chip::Crypto::P256PublicKey dacPublicKey; ReturnErrorOnFailure(chip::Crypto::ExtractPubkeyFromX509Cert(dacCertSpan, dacPublicKey)); - ReturnErrorOnFailure( - LoadKeypairFromRaw(ByteSpan(reinterpret_cast(mFactoryData.dac.dac_key.value), mFactoryData.dac.dac_key.len), - ByteSpan(dacPublicKey.Bytes(), dacPublicKey.Length()), keypair)); + ReturnErrorOnFailure(keypair.ImportRawKeypair( + ByteSpan(reinterpret_cast(mFactoryData.dac.dac_key.value), mFactoryData.dac.dac_key.len), + ByteSpan(dacPublicKey.Bytes(), dacPublicKey.Length()))); } else { - ReturnErrorOnFailure(LoadKeypairFromRaw(ByteSpan(kDacPrivateKey), ByteSpan(kDacPublicKey), keypair)); + ReturnErrorOnFailure(keypair.ImportRawKeypair(ByteSpan(kDacPrivateKey), ByteSpan(kDacPublicKey))); } ReturnErrorOnFailure(keypair.ECDSA_sign_msg(messageToSign.data(), messageToSign.size(), signature)); diff --git a/src/platform/ESP32/ESP32FactoryDataProvider.cpp b/src/platform/ESP32/ESP32FactoryDataProvider.cpp index 951d39132df3c6..889b5b800d226e 100644 --- a/src/platform/ESP32/ESP32FactoryDataProvider.cpp +++ b/src/platform/ESP32/ESP32FactoryDataProvider.cpp @@ -30,14 +30,6 @@ namespace { static constexpr uint32_t kDACPrivateKeySize = 32; static constexpr uint32_t kDACPublicKeySize = 65; -CHIP_ERROR LoadKeypairFromRaw(ByteSpan privateKey, ByteSpan publicKey, Crypto::P256Keypair & keypair) -{ - Crypto::P256SerializedKeypair serializedKeypair; - ReturnErrorOnFailure(serializedKeypair.SetLength(privateKey.size() + publicKey.size())); - memcpy(serializedKeypair.Bytes(), publicKey.data(), publicKey.size()); - memcpy(serializedKeypair.Bytes() + publicKey.size(), privateKey.data(), privateKey.size()); - return keypair.Deserialize(serializedKeypair); -} } // namespace CHIP_ERROR ESP32FactoryDataProvider::GetSetupDiscriminator(uint16_t & setupDiscriminator) @@ -148,7 +140,7 @@ CHIP_ERROR ESP32FactoryDataProvider::SignWithDeviceAttestationKey(const ByteSpan ESP32Config::ReadConfigValueBin(ESP32Config::kConfigKey_DACPrivateKey, privKeyBuf, privKeyLen, privKeyLen)); ReturnErrorOnFailure(ESP32Config::ReadConfigValueBin(ESP32Config::kConfigKey_DACPublicKey, pubKeyBuf, pubKeyLen, pubKeyLen)); - ReturnErrorOnFailure(LoadKeypairFromRaw(ByteSpan(privKeyBuf, privKeyLen), ByteSpan(pubKeyBuf, pubKeyLen), keypair)); + ReturnErrorOnFailure(keypair.ImportRawKeypair(ByteSpan(privKeyBuf, privKeyLen), ByteSpan(pubKeyBuf, pubKeyLen))); ReturnErrorOnFailure(keypair.ECDSA_sign_msg(messageToSign.data(), messageToSign.size(), signature)); return CopySpanToMutableSpan(ByteSpan{ signature.ConstBytes(), signature.Length() }, outSignBuffer); diff --git a/src/platform/nrfconnect/FactoryDataProvider.cpp b/src/platform/nrfconnect/FactoryDataProvider.cpp index 45adec502140e5..816aaea071fe12 100644 --- a/src/platform/nrfconnect/FactoryDataProvider.cpp +++ b/src/platform/nrfconnect/FactoryDataProvider.cpp @@ -29,15 +29,6 @@ namespace chip { namespace { -CHIP_ERROR LoadKeypairFromRaw(ByteSpan privateKey, ByteSpan publicKey, Crypto::P256Keypair & keypair) -{ - Crypto::P256SerializedKeypair serializedKeypair; - ReturnErrorOnFailure(serializedKeypair.SetLength(privateKey.size() + publicKey.size())); - memcpy(serializedKeypair.Bytes(), publicKey.data(), publicKey.size()); - memcpy(serializedKeypair.Bytes() + publicKey.size(), privateKey.data(), privateKey.size()); - return keypair.Deserialize(serializedKeypair); -} - CHIP_ERROR GetFactoryDataString(const FactoryDataString & str, char * buf, size_t bufSize) { ReturnErrorCodeIf(bufSize < str.len + 1, CHIP_ERROR_BUFFER_TOO_SMALL); @@ -167,9 +158,9 @@ CHIP_ERROR FactoryDataProvider::SignWithDeviceAttestationKey(c chip::Crypto::P256PublicKey dacPublicKey; ReturnErrorOnFailure(chip::Crypto::ExtractPubkeyFromX509Cert(dacCertSpan, dacPublicKey)); - ReturnErrorOnFailure( - LoadKeypairFromRaw(ByteSpan(reinterpret_cast(mFactoryData.dac_priv_key.data), mFactoryData.dac_priv_key.len), - ByteSpan(dacPublicKey.Bytes(), dacPublicKey.Length()), keypair)); + ReturnErrorOnFailure(keypair.ImportRawKeypair( + ByteSpan(reinterpret_cast(mFactoryData.dac_priv_key.data), mFactoryData.dac_priv_key.len), + ByteSpan(dacPublicKey.Bytes(), dacPublicKey.Length()))); ReturnErrorOnFailure(keypair.ECDSA_sign_msg(messageToSign.data(), messageToSign.size(), signature)); return CopySpanToMutableSpan(ByteSpan{ signature.ConstBytes(), signature.Length() }, outSignBuffer); diff --git a/src/platform/nxp/mw320/FactoryDataProvider.cpp b/src/platform/nxp/mw320/FactoryDataProvider.cpp index 20400b08f05534..f3cdc72842ec09 100644 --- a/src/platform/nxp/mw320/FactoryDataProvider.cpp +++ b/src/platform/nxp/mw320/FactoryDataProvider.cpp @@ -28,17 +28,6 @@ extern uint8_t * __FACTORY_DATA_START; extern uint32_t __FACTORY_DATA_SIZE; namespace chip { -namespace { - -CHIP_ERROR 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); -} -} // namespace namespace DeviceLayer { @@ -195,8 +184,8 @@ CHIP_ERROR FactoryDataProvider::SignWithDeviceAttestationKey(const ByteSpan & me ReturnErrorOnFailure(SearchForId(kDacPrivateKeyId, dacPrivateKeySpan.data(), dacPrivateKeySpan.size(), keySize)); dacPrivateKeySpan.reduce_size(keySize); - ReturnErrorOnFailure(LoadKeypairFromRaw(ByteSpan(dacPrivateKeySpan.data(), dacPrivateKeySpan.size()), - ByteSpan(dacPublicKey.Bytes(), dacPublicKey.Length()), keypair)); + ReturnErrorOnFailure(keypair.ImportRawKeypair(ByteSpan(dacPrivateKeySpan.data(), dacPrivateKeySpan.size()), + ByteSpan(dacPublicKey.Bytes(), dacPublicKey.Length()))); ReturnErrorOnFailure(keypair.ECDSA_sign_msg(messageToSign.data(), messageToSign.size(), signature)); res = CopySpanToMutableSpan(ByteSpan{ signature.ConstBytes(), signature.Length() }, outSignBuffer); diff --git a/src/platform/qpg/FactoryDataProvider.cpp b/src/platform/qpg/FactoryDataProvider.cpp index 3d7601eb731763..0af906082910ee 100644 --- a/src/platform/qpg/FactoryDataProvider.cpp +++ b/src/platform/qpg/FactoryDataProvider.cpp @@ -26,18 +26,6 @@ #include "qvCHIP.h" namespace chip { -namespace { - -CHIP_ERROR LoadKeypairFromRaw(ByteSpan privateKey, ByteSpan publicKey, Crypto::P256Keypair & keypair) -{ - Crypto::P256SerializedKeypair serializedKeypair; - ReturnErrorOnFailure(serializedKeypair.SetLength(privateKey.size() + publicKey.size())); - memcpy(serializedKeypair.Bytes(), publicKey.data(), publicKey.size()); - memcpy(serializedKeypair.Bytes() + publicKey.size(), privateKey.data(), privateKey.size()); - return keypair.Deserialize(serializedKeypair); -} - -} // namespace namespace DeviceLayer { @@ -115,7 +103,7 @@ CHIP_ERROR FactoryDataProvider::SignWithDeviceAttestationKey(const ByteSpan & me // 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. - ReturnErrorOnFailure(LoadKeypairFromRaw(qorvoDacPrivateKey, qorvoDacPublicKey, keypair)); + ReturnErrorOnFailure(keypair.ImportRawKeypair(qorvoDacPrivateKey, qorvoDacPublicKey)); ReturnErrorOnFailure(keypair.ECDSA_sign_msg(messageToSign.data(), messageToSign.size(), signature)); return CopySpanToMutableSpan(ByteSpan{ signature.ConstBytes(), signature.Length() }, outSignBuffer); diff --git a/src/platform/telink/FactoryDataProvider.cpp b/src/platform/telink/FactoryDataProvider.cpp index 806cdb2cfe9391..f39492af66e177 100644 --- a/src/platform/telink/FactoryDataProvider.cpp +++ b/src/platform/telink/FactoryDataProvider.cpp @@ -29,15 +29,6 @@ namespace chip { namespace { -CHIP_ERROR LoadKeypairFromRaw(ByteSpan privateKey, ByteSpan publicKey, Crypto::P256Keypair & keypair) -{ - Crypto::P256SerializedKeypair serializedKeypair; - ReturnErrorOnFailure(serializedKeypair.SetLength(privateKey.size() + publicKey.size())); - memcpy(serializedKeypair.Bytes(), publicKey.data(), publicKey.size()); - memcpy(serializedKeypair.Bytes() + publicKey.size(), privateKey.data(), privateKey.size()); - return keypair.Deserialize(serializedKeypair); -} - CHIP_ERROR GetFactoryDataString(const FactoryDataString & str, char * buf, size_t bufSize) { ReturnErrorCodeIf(bufSize < str.len + 1, CHIP_ERROR_BUFFER_TOO_SMALL); @@ -166,9 +157,9 @@ CHIP_ERROR FactoryDataProvider::SignWithDeviceAttestationKey(c chip::Crypto::P256PublicKey dacPublicKey; ReturnErrorOnFailure(chip::Crypto::ExtractPubkeyFromX509Cert(dacCertSpan, dacPublicKey)); - ReturnErrorOnFailure( - LoadKeypairFromRaw(ByteSpan(reinterpret_cast(mFactoryData.dac_priv_key.data), mFactoryData.dac_priv_key.len), - ByteSpan(dacPublicKey.Bytes(), dacPublicKey.Length()), keypair)); + ReturnErrorOnFailure(keypair.ImportRawKeypair( + ByteSpan(reinterpret_cast(mFactoryData.dac_priv_key.data), mFactoryData.dac_priv_key.len), + ByteSpan(dacPublicKey.Bytes(), dacPublicKey.Length()))); ReturnErrorOnFailure(keypair.ECDSA_sign_msg(messageToSign.data(), messageToSign.size(), signature)); return CopySpanToMutableSpan(ByteSpan{ signature.ConstBytes(), signature.Length() }, outSignBuffer); diff --git a/src/protocols/secure_channel/tests/TestCASESession.cpp b/src/protocols/secure_channel/tests/TestCASESession.cpp index 11d5000f71df03..cdf064e457a8b1 100644 --- a/src/protocols/secure_channel/tests/TestCASESession.cpp +++ b/src/protocols/secure_channel/tests/TestCASESession.cpp @@ -270,16 +270,10 @@ CHIP_ERROR InitCredentialSets() FabricInfo deviceFabric; { - P256SerializedKeypair opKeysSerialized; - auto deviceOpKey = Platform::MakeUnique(); - memcpy(opKeysSerialized.Bytes(), sTestCert_Node01_01_PublicKey, sTestCert_Node01_01_PublicKey_Len); - memcpy(opKeysSerialized.Bytes() + sTestCert_Node01_01_PublicKey_Len, sTestCert_Node01_01_PrivateKey, - sTestCert_Node01_01_PrivateKey_Len); - - ReturnErrorOnFailure(opKeysSerialized.SetLength(sTestCert_Node01_01_PublicKey_Len + sTestCert_Node01_01_PrivateKey_Len)); - ReturnErrorOnFailure(deviceOpKey->Deserialize(opKeysSerialized)); + deviceOpKey->ImportRawKeypair(sTestCert_Node01_01_PrivateKey, sTestCert_Node01_01_PrivateKey_Len, + sTestCert_Node01_01_PublicKey, sTestCert_Node01_01_PublicKey_Len); // Use an injected operational key for device gDeviceOperationalKeystore.Init(1, std::move(deviceOpKey)); diff --git a/src/transport/tests/TestSessionManager.cpp b/src/transport/tests/TestSessionManager.cpp index 12dc46ae360cc6..71d372a64b99ff 100644 --- a/src/transport/tests/TestSessionManager.cpp +++ b/src/transport/tests/TestSessionManager.cpp @@ -27,7 +27,11 @@ #include #include #include +#if CHIP_CRYPTO_PSA +#include +#else #include +#endif #include #include #include @@ -70,13 +74,17 @@ class FabricTableHolder ~FabricTableHolder() { mFabricTable.Shutdown(); +#if !CHIP_CRYPTO_PSA mOpKeyStore.Finish(); +#endif mOpCertStore.Finish(); } CHIP_ERROR Init() { +#if !CHIP_CRYPTO_PSA ReturnErrorOnFailure(mOpKeyStore.Init(&mStorage)); +#endif ReturnErrorOnFailure(mOpCertStore.Init(&mStorage)); chip::FabricTable::InitParams initParams; @@ -92,7 +100,11 @@ class FabricTableHolder private: chip::FabricTable mFabricTable; chip::TestPersistentStorageDelegate mStorage; +#if CHIP_CRYPTO_PSA + chip::PSAOperationalKeystore mOpKeyStore; +#else chip::PersistentStorageOperationalKeystore mOpKeyStore; +#endif chip::Credentials::PersistentStorageOpCertStore mOpCertStore; }; diff --git a/src/transport/tests/TestSessionManagerDispatch.cpp b/src/transport/tests/TestSessionManagerDispatch.cpp index 4e320961267bd7..018cd4fd528a06 100644 --- a/src/transport/tests/TestSessionManagerDispatch.cpp +++ b/src/transport/tests/TestSessionManagerDispatch.cpp @@ -27,7 +27,11 @@ #include #include #include +#if CHIP_CRYPTO_PSA +#include +#else #include +#endif #include #include #include @@ -427,13 +431,17 @@ class FabricTableHolder ~FabricTableHolder() { mFabricTable.Shutdown(); +#if !CHIP_CRYPTO_PSA mOpKeyStore.Finish(); +#endif mOpCertStore.Finish(); } CHIP_ERROR Init() { +#if !CHIP_CRYPTO_PSA ReturnErrorOnFailure(mOpKeyStore.Init(&mStorage)); +#endif ReturnErrorOnFailure(mOpCertStore.Init(&mStorage)); // Initialize Group Data Provider @@ -457,7 +465,11 @@ class FabricTableHolder private: chip::FabricTable mFabricTable; chip::TestPersistentStorageDelegate mStorage; +#if CHIP_CRYPTO_PSA + chip::Crypto::PSAOperationalKeystore mOpKeyStore; +#else chip::PersistentStorageOperationalKeystore mOpKeyStore; +#endif chip::Credentials::PersistentStorageOpCertStore mOpCertStore; };