diff --git a/.github/workflows/examples-k32w.yaml b/.github/workflows/examples-k32w.yaml index 855f0ea88fa34b..1744acc20e91ba 100644 --- a/.github/workflows/examples-k32w.yaml +++ b/.github/workflows/examples-k32w.yaml @@ -86,7 +86,6 @@ jobs: run: | scripts/run_in_build_env.sh "\ ./scripts/build/build_examples.py \ - --target k32w-light-no-ble-se05x \ --target k32w-light-crypto-platform-tokenizer \ --target k32w-lock-crypto-platform-tokenizer \ --target k32w-lock-crypto-platform-low-power-nologs \ diff --git a/examples/contact-sensor-app/nxp/k32w/k32w0/BUILD.gn b/examples/contact-sensor-app/nxp/k32w/k32w0/BUILD.gn index fc64f7de9c8e66..e4c15436b3bd86 100644 --- a/examples/contact-sensor-app/nxp/k32w/k32w0/BUILD.gn +++ b/examples/contact-sensor-app/nxp/k32w/k32w0/BUILD.gn @@ -57,10 +57,6 @@ k32w0_sdk("sdk") { "${k32w0_platform_dir}/common", ] - if (chip_with_se05x == 1) { - include_dirs += [ "${chip_root}/examples/platform/nxp/se05x" ] - } - defines = [] if (is_debug) { defines += [ "BUILD_RELEASE=0" ] diff --git a/examples/lighting-app/nxp/k32w/k32w0/BUILD.gn b/examples/lighting-app/nxp/k32w/k32w0/BUILD.gn index 54721dad1a397d..2ee2e42a24259e 100644 --- a/examples/lighting-app/nxp/k32w/k32w0/BUILD.gn +++ b/examples/lighting-app/nxp/k32w/k32w0/BUILD.gn @@ -57,10 +57,6 @@ k32w0_sdk("sdk") { "${k32w0_platform_dir}/common", ] - if (chip_with_se05x == 1) { - include_dirs += [ "${chip_root}/examples/platform/nxp/se05x" ] - } - defines = [] if (is_debug) { defines += [ "BUILD_RELEASE=0" ] diff --git a/examples/lock-app/nxp/k32w/k32w0/BUILD.gn b/examples/lock-app/nxp/k32w/k32w0/BUILD.gn index 7a18fc3eb14396..0b752583604a89 100644 --- a/examples/lock-app/nxp/k32w/k32w0/BUILD.gn +++ b/examples/lock-app/nxp/k32w/k32w0/BUILD.gn @@ -57,10 +57,6 @@ k32w0_sdk("sdk") { "${k32w0_platform_dir}/common", ] - if (chip_with_se05x == 1) { - include_dirs += [ "${chip_root}/examples/platform/nxp/se05x" ] - } - defines = [] if (is_debug) { defines += [ "BUILD_RELEASE=0" ] @@ -111,7 +107,6 @@ k32w0_executable("lock_app") { "${chip_root}/src/lib", "${chip_root}/src/platform:syscalls_stub", "${chip_root}/third_party/mbedtls:mbedtls", - "${chip_root}/third_party/simw-top-mini:se05x", "${k32w0_platform_dir}/app/support:freertos_mbedtls_utils", ] diff --git a/examples/platform/nxp/se05x/DeviceAttestationSe05xCredsExample.cpp b/examples/platform/nxp/se05x/DeviceAttestationSe05xCredsExample.cpp index 5c8b513974f866..c4231df0b129ea 100644 --- a/examples/platform/nxp/se05x/DeviceAttestationSe05xCredsExample.cpp +++ b/examples/platform/nxp/se05x/DeviceAttestationSe05xCredsExample.cpp @@ -16,20 +16,13 @@ */ #include "DeviceAttestationSe05xCredsExample.h" +#include #include #include #include #include #include -#if CHIP_CRYPTO_HSM -#include -#endif - -#ifdef ENABLE_HSM_DEVICE_ATTESTATION - -#include - /* Device attestation key ids */ #define DEV_ATTESTATION_KEY_SE05X_ID 0x7D300000 #define DEV_ATTESTATION_CERT_SE05X_ID 0x7D300001 @@ -135,7 +128,9 @@ CHIP_ERROR ExampleSe05xDACProvider::SignWithDeviceAttestationKey(const ByteSpan MutableByteSpan & out_signature_buffer) { Crypto::P256ECDSASignature signature; - Crypto::P256KeypairHSM keypair; + Crypto::P256Keypair keypair; + Crypto::P256SerializedKeypair serialized_keypair; + uint8_t magic_bytes[] = NXP_CRYPTO_KEY_MAGIC; ChipLogDetail(Crypto, "Sign using DA key from se05x"); @@ -143,9 +138,22 @@ CHIP_ERROR ExampleSe05xDACProvider::SignWithDeviceAttestationKey(const ByteSpan VerifyOrReturnError(IsSpanUsable(message_to_sign), CHIP_ERROR_INVALID_ARGUMENT); VerifyOrReturnError(out_signature_buffer.size() >= signature.Capacity(), CHIP_ERROR_BUFFER_TOO_SMALL); - keypair.SetKeyId(DEV_ATTESTATION_KEY_SE05X_ID); - keypair.provisioned_key = true; - keypair.Initialize(Crypto::ECPKeyTarget::ECDSA); + // Add public key + reference private key (ref to key inside SE) + + serialized_keypair.SetLength(Crypto::kP256_PublicKey_Length + Crypto::kP256_PrivateKey_Length); + + memset(serialized_keypair.Bytes(), 0, Crypto::kP256_PublicKey_Length); + memcpy(serialized_keypair.Bytes() + Crypto::kP256_PublicKey_Length, magic_bytes, sizeof(magic_bytes)); + *(serialized_keypair.Bytes() + Crypto::kP256_PublicKey_Length + sizeof(magic_bytes) + 0) = + (DEV_ATTESTATION_KEY_SE05X_ID & 0xFF000000) >> (8 * 3); + *(serialized_keypair.Bytes() + Crypto::kP256_PublicKey_Length + sizeof(magic_bytes) + 1) = + (DEV_ATTESTATION_KEY_SE05X_ID & 0x00FF0000) >> (8 * 2); + *(serialized_keypair.Bytes() + Crypto::kP256_PublicKey_Length + sizeof(magic_bytes) + 2) = + (DEV_ATTESTATION_KEY_SE05X_ID & 0x0000FF00) >> (8 * 1); + *(serialized_keypair.Bytes() + Crypto::kP256_PublicKey_Length + sizeof(magic_bytes) + 3) = + (DEV_ATTESTATION_KEY_SE05X_ID & 0x000000FF) >> (8 * 0); + + ReturnErrorOnFailure(keypair.Deserialize(serialized_keypair)); ReturnErrorOnFailure(keypair.ECDSA_sign_msg(message_to_sign.data(), message_to_sign.size(), signature)); @@ -164,5 +172,3 @@ DeviceAttestationCredentialsProvider * GetExampleSe05xDACProvider() } // namespace Examples } // namespace Credentials } // namespace chip - -#endif //#ifdef ENABLE_HSM_DEVICE_ATTESTATION diff --git a/examples/platform/nxp/se05x/DeviceAttestationSe05xCredsExample_v2.cpp b/examples/platform/nxp/se05x/DeviceAttestationSe05xCredsExample_v2.cpp index 4b8202cd99f86a..5592a49d17b872 100644 --- a/examples/platform/nxp/se05x/DeviceAttestationSe05xCredsExample_v2.cpp +++ b/examples/platform/nxp/se05x/DeviceAttestationSe05xCredsExample_v2.cpp @@ -14,8 +14,10 @@ * See the License for the specific language governing permissions and * limitations under the License. */ + #include "DeviceAttestationSe05xCredsExample.h" +#include #include #include #include @@ -23,17 +25,9 @@ #include #include #include -#include +#include #include -#if CHIP_CRYPTO_HSM -#include -#endif - -#ifdef ENABLE_HSM_DEVICE_ATTESTATION - -#include - /* Device attestation key ids */ #define DEV_ATTESTATION_KEY_SE05X_ID 0x7D300000 #define DEV_ATTESTATION_CERT_SE05X_ID 0x7D300001 @@ -279,5 +273,3 @@ DeviceAttestationCredentialsProvider * GetExampleSe05xDACProviderv2() } // namespace Examples } // namespace Credentials } // namespace chip - -#endif // #ifdef ENABLE_HSM_DEVICE_ATTESTATION diff --git a/examples/platform/nxp/se05x/linux/AppMain.cpp b/examples/platform/nxp/se05x/linux/AppMain.cpp index 5ae726604a4c8a..2c04b81b0ce8bb 100644 --- a/examples/platform/nxp/se05x/linux/AppMain.cpp +++ b/examples/platform/nxp/se05x/linux/AppMain.cpp @@ -77,12 +77,8 @@ #include "AppMain.h" #include "CommissionableInit.h" -#if CHIP_CRYPTO_HSM #include "DeviceAttestationSe05xCredsExample.h" -#include "se05x_t4t_utils.h" -#include -#include -#endif +#include using namespace chip; using namespace chip::ArgParser; @@ -289,95 +285,10 @@ int ChipLinuxAppInit(int argc, char * const argv[], OptionSet * customOptions) return 0; } -#ifdef ENABLE_HSM_EC_KEY - -struct CommonCaseDeviceServerInitParams_Se05x : public CommonCaseDeviceServerInitParams -{ - CHIP_ERROR InitializeStaticResourcesBeforeServerInit() - { - static chip::KvsPersistentStorageDelegate sKvsPersistenStorageDelegate; - static chip::PersistentStorageOperationalKeystoreHSM sPersistentStorageOperationalKeystore; - static chip::Credentials::PersistentStorageOpCertStore sPersistentStorageOpCertStore; - static chip::Credentials::GroupDataProviderImpl sGroupDataProvider; - static Credentials::IgnoreCertificateValidityPeriodPolicy sDefaultCertValidityPolicy; - static chip::Crypto::DefaultSessionKeystore sSessionKeystore; - -#if CHIP_CONFIG_ENABLE_SESSION_RESUMPTION - static chip::SimpleSessionResumptionStorage sSessionResumptionStorage; -#endif - static chip::app::DefaultAclStorage sAclStorage; - - // KVS-based persistent storage delegate injection - if (persistentStorageDelegate == nullptr) - { - chip::DeviceLayer::PersistedStorage::KeyValueStoreManager & kvsManager = - DeviceLayer::PersistedStorage::KeyValueStoreMgr(); - ReturnErrorOnFailure(sKvsPersistenStorageDelegate.Init(&kvsManager)); - this->persistentStorageDelegate = &sKvsPersistenStorageDelegate; - } - - // PersistentStorageDelegate "software-based" operational key access injection - if (this->operationalKeystore == nullptr) - { - // WARNING: PersistentStorageOperationalKeystore::Finish() is never called. It's fine for - // for examples and for now. - ReturnErrorOnFailure(sPersistentStorageOperationalKeystore.Init(this->persistentStorageDelegate)); - this->operationalKeystore = &sPersistentStorageOperationalKeystore; - } - - // OpCertStore can be injected but default to persistent storage default - // for simplicity of the examples. - if (this->opCertStore == nullptr) - { - // WARNING: PersistentStorageOpCertStore::Finish() is never called. It's fine for - // for examples and for now, since all storage is immediate for that impl. - ReturnErrorOnFailure(sPersistentStorageOpCertStore.Init(this->persistentStorageDelegate)); - this->opCertStore = &sPersistentStorageOpCertStore; - } - - // Session Keystore injection - this->sessionKeystore = &sSessionKeystore; - - // Group Data provider injection - sGroupDataProvider.SetStorageDelegate(this->persistentStorageDelegate); - sGroupDataProvider.SetSessionKeystore(this->sessionKeystore); - ReturnErrorOnFailure(sGroupDataProvider.Init()); - this->groupDataProvider = &sGroupDataProvider; - -#if CHIP_CONFIG_ENABLE_SESSION_RESUMPTION - ReturnErrorOnFailure(sSessionResumptionStorage.Init(this->persistentStorageDelegate)); - this->sessionResumptionStorage = &sSessionResumptionStorage; -#else - this->sessionResumptionStorage = nullptr; -#endif - - // Inject access control delegate - this->accessDelegate = Access::Examples::GetAccessControlDelegate(); - - // Inject ACL storage. (Don't initialize it.) - this->aclStorage = &sAclStorage; - - // Inject certificate validation policy compatible with non-wall-clock-time-synced - // embedded systems. - this->certificateValidityPolicy = &sDefaultCertValidityPolicy; - - return CHIP_NO_ERROR; - } -}; - -#endif - void ChipLinuxAppMainLoop(AppMainLoopImplementation * impl) { -#ifdef ENABLE_HSM_EC_KEY - static CommonCaseDeviceServerInitParams_Se05x initParams; -#else static chip::CommonCaseDeviceServerInitParams initParams; -#endif -#if CHIP_CRYPTO_HSM - VerifyOrDie(se05x_enable_contactless_interface() == 0); -#endif VerifyOrDie(initParams.InitializeStaticResourcesBeforeServerInit() == CHIP_NO_ERROR); #if defined(ENABLE_CHIP_SHELL) @@ -423,7 +334,7 @@ void ChipLinuxAppMainLoop(AppMainLoopImplementation * impl) PrintOnboardingCodes(LinuxDeviceOptions::GetInstance().payload); // Initialize device attestation config -#ifdef ENABLE_HSM_DEVICE_ATTESTATION +#if ENABLE_SE05X_DEVICE_ATTESTATION SetDeviceAttestationCredentialsProvider(Examples::GetExampleSe05xDACProvider()); #else SetDeviceAttestationCredentialsProvider(LinuxDeviceOptions::GetInstance().dacProvider); diff --git a/examples/platform/nxp/se05x/linux/BUILD.gn b/examples/platform/nxp/se05x/linux/BUILD.gn index 52ce3d417617e5..2a93a4bf085a3e 100644 --- a/examples/platform/nxp/se05x/linux/BUILD.gn +++ b/examples/platform/nxp/se05x/linux/BUILD.gn @@ -59,6 +59,7 @@ source_set("app-main") { include_dirs = [ "${chip_root}/examples/platform/linux", "${chip_root}/examples/platform/nxp/se05x", + "${chip_root}/src/platform/nxp/crypto/se05x", ] defines = [] diff --git a/examples/shell/nxp/k32w/k32w0/BUILD.gn b/examples/shell/nxp/k32w/k32w0/BUILD.gn index 8b062831685aea..b19d08fe44e325 100644 --- a/examples/shell/nxp/k32w/k32w0/BUILD.gn +++ b/examples/shell/nxp/k32w/k32w0/BUILD.gn @@ -69,7 +69,6 @@ k32w0_executable("shell_app") { "${chip_root}/examples/shell/shell_common:shell_common", "${chip_root}/src/platform:syscalls_stub", "${chip_root}/third_party/mbedtls:mbedtls", - "${chip_root}/third_party/simw-top-mini:se05x", "${k32w0_platform_dir}/app/support:freertos_mbedtls_utils", ] diff --git a/examples/thermostat/nxp/linux-se05x/BUILD.gn b/examples/thermostat/nxp/linux-se05x/BUILD.gn index 1f5851a30caeca..69bdb0358106d3 100644 --- a/examples/thermostat/nxp/linux-se05x/BUILD.gn +++ b/examples/thermostat/nxp/linux-se05x/BUILD.gn @@ -14,14 +14,18 @@ import("//build_overrides/build.gni") import("//build_overrides/chip.gni") +import("${chip_root}/src/platform/nxp/crypto/nxp_crypto.gni") -executable("thermostat-se05x-app") { - sources = [ "${chip_root}/examples/thermostat/linux/main.cpp" ] - +executable("thermostat-app") { + sources = [ + "../../linux/include/low-power/LowPowerManager.cpp", + "../../linux/include/low-power/LowPowerManager.h", + "../../linux/main.cpp", + ] include_dirs = [ "${chip_root}/examples/platform/linux" ] deps = [ - "${chip_root}/examples/platform/nxp/se05x/linux:app-main", + "${chip_root}/examples/platform/nxp/${nxp_crypto_impl}/linux:app-main", "${chip_root}/examples/thermostat/thermostat-common", "${chip_root}/src/lib", ] @@ -29,4 +33,16 @@ executable("thermostat-se05x-app") { cflags = [ "-Wconversion" ] output_dir = root_out_dir + + deps += [ + "${chip_root}/src/platform/nxp/crypto/${nxp_crypto_impl}:nxp_crypto_lib", + ] +} + +group("linux") { + deps = [ ":thermostat-app" ] +} + +group("default") { + deps = [ ":linux" ] } diff --git a/examples/thermostat/nxp/linux-se05x/args.gni b/examples/thermostat/nxp/linux-se05x/args.gni index c9ccb79255d82b..98b7b40c1038b4 100644 --- a/examples/thermostat/nxp/linux-se05x/args.gni +++ b/examples/thermostat/nxp/linux-se05x/args.gni @@ -13,5 +13,8 @@ # limitations under the License. import("//build_overrides/chip.gni") + import("${chip_root}/config/standalone/args.gni") -chip_with_se05x = 1 + +# Include to define nxp_crypto_impl +import("${chip_root}/src/platform/nxp/crypto/se05x/args.gni") diff --git a/src/crypto/BUILD.gn b/src/crypto/BUILD.gn index d97c89737c15bc..d0fe7190175ed6 100644 --- a/src/crypto/BUILD.gn +++ b/src/crypto/BUILD.gn @@ -55,14 +55,6 @@ buildconfig_header("crypto_buildconfig") { "CHIP_CRYPTO_BORINGSSL=${chip_crypto_boringssl}", "CHIP_CRYPTO_PLATFORM=${chip_crypto_platform}", ] - - if (chip_with_se05x == 1) { - defines += [ "CHIP_CRYPTO_HSM=1" ] - defines += [ "CHIP_CRYPTO_HSM_NXP=1" ] - } else { - defines += [ "CHIP_CRYPTO_HSM=0" ] - defines += [ "CHIP_CRYPTO_HSM_NXP=0" ] - } } source_set("public_headers") { @@ -177,19 +169,4 @@ static_library("crypto") { } else { assert(false, "Invalid CHIP crypto") } - - if (chip_with_se05x == 1) { - sources += [ - "hsm/nxp/CHIPCryptoPALHsm_SE05X_HKDF.cpp", - "hsm/nxp/CHIPCryptoPALHsm_SE05X_HMAC.cpp", - "hsm/nxp/CHIPCryptoPALHsm_SE05X_P256.cpp", - "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/CHIPCryptoPAL.cpp b/src/crypto/CHIPCryptoPAL.cpp index 69c3f575867ab6..8d42fd49726156 100644 --- a/src/crypto/CHIPCryptoPAL.cpp +++ b/src/crypto/CHIPCryptoPAL.cpp @@ -197,11 +197,7 @@ CHIP_ERROR ConvertIntegerRawToDerInternal(const ByteSpan & raw_integer, MutableB namespace chip { namespace Crypto { -#ifdef ENABLE_HSM_HKDF -using HKDF_sha_crypto = HKDF_shaHSM; -#else using HKDF_sha_crypto = HKDF_sha; -#endif CHIP_ERROR Spake2p::InternalHash(const uint8_t * in, size_t in_len) { @@ -549,11 +545,7 @@ CHIP_ERROR Spake2pVerifier::Generate(uint32_t pbkdf2IterCount, const ByteSpan & size_t len; // Create local Spake2+ object for w0 and L computations. -#ifdef ENABLE_HSM_SPAKE - Spake2pHSM_P256_SHA256_HKDF_HMAC spake2p; -#else Spake2p_P256_SHA256_HKDF_HMAC spake2p; -#endif uint8_t context[kSHA256_Hash_Length] = { 0 }; SuccessOrExit(err = spake2p.Init(context, sizeof(context))); @@ -575,11 +567,7 @@ CHIP_ERROR Spake2pVerifier::Generate(uint32_t pbkdf2IterCount, const ByteSpan & CHIP_ERROR Spake2pVerifier::ComputeWS(uint32_t pbkdf2IterCount, const ByteSpan & salt, uint32_t setupPin, uint8_t * ws, uint32_t ws_len) { -#ifdef ENABLE_HSM_PBKDF2 - PBKDF2_sha256HSM pbkdf2; -#else PBKDF2_sha256 pbkdf2; -#endif uint8_t littleEndianSetupPINCode[sizeof(uint32_t)]; Encoding::LittleEndian::Put32(littleEndianSetupPINCode, setupPin); diff --git a/src/crypto/RawKeySessionKeystore.cpp b/src/crypto/RawKeySessionKeystore.cpp index 97666569345d04..7db2c0c8b28962 100644 --- a/src/crypto/RawKeySessionKeystore.cpp +++ b/src/crypto/RawKeySessionKeystore.cpp @@ -22,11 +22,7 @@ namespace chip { namespace Crypto { -#ifdef ENABLE_HSM_HKDF -using HKDF_sha_crypto = HKDF_shaHSM; -#else using HKDF_sha_crypto = HKDF_sha; -#endif CHIP_ERROR RawKeySessionKeystore::CreateKey(const Aes128KeyByteArray & keyMaterial, Aes128KeyHandle & key) { diff --git a/src/crypto/hsm/CHIPCryptoPALHsm.h b/src/crypto/hsm/CHIPCryptoPALHsm.h deleted file mode 100644 index dde8be48c52a8a..00000000000000 --- a/src/crypto/hsm/CHIPCryptoPALHsm.h +++ /dev/null @@ -1,212 +0,0 @@ -/* - * - * Copyright (c) 2020 Project CHIP Authors - * - * 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. - */ - -/** - * @file - * Header that exposes the platform agnostic CHIP crypto primitives - */ - -#pragma once - -#include "CHIPCryptoPALHsm_config.h" -#include - -#if CHIP_CRYPTO_HSM_NXP -#include -#endif - -#if ((ENABLE_HSM_SPAKE_VERIFIER) || (ENABLE_HSM_SPAKE_PROVER)) -typedef struct hsm_pake_context_s -{ - uint8_t spake_context[32]; - size_t spake_context_len; -#if CHIP_CRYPTO_HSM_NXP - SE05x_CryptoObjectID_t spake_objId; -#endif -} hsm_pake_context_t; -#endif //#if ((ENABLE_HSM_SPAKE_VERIFIER) || (ENABLE_HSM_SPAKE_PROVER)) - -namespace chip { -namespace Crypto { - -#if ((ENABLE_HSM_SPAKE_VERIFIER) || (ENABLE_HSM_SPAKE_PROVER)) -/* Spake HSM class */ - -class Spake2pHSM_P256_SHA256_HKDF_HMAC : public Spake2p_P256_SHA256_HKDF_HMAC -{ -public: - Spake2pHSM_P256_SHA256_HKDF_HMAC() {} - - ~Spake2pHSM_P256_SHA256_HKDF_HMAC() {} - - CHIP_ERROR Init(const uint8_t * context, size_t context_len) override; - -#if ENABLE_HSM_SPAKE_VERIFIER - CHIP_ERROR BeginVerifier(const uint8_t * my_identity, size_t my_identity_len, const uint8_t * peer_identity, - size_t peer_identity_len, const uint8_t * w0in, size_t w0in_len, const uint8_t * Lin, - size_t Lin_len) override; -#endif - -#if ENABLE_HSM_SPAKE_PROVER - CHIP_ERROR BeginProver(const uint8_t * my_identity, size_t my_identity_len, const uint8_t * peer_identity, - size_t peer_identity_len, const uint8_t * w0in, size_t w0in_len, const uint8_t * w1in, - size_t w1in_len) override; -#endif - - CHIP_ERROR ComputeRoundOne(const uint8_t * pab, size_t pab_len, uint8_t * out, size_t * out_len) override; - - CHIP_ERROR ComputeRoundTwo(const uint8_t * in, size_t in_len, uint8_t * out, size_t * out_len) override; - - CHIP_ERROR KeyConfirm(const uint8_t * in, size_t in_len) override; - - hsm_pake_context_t hsm_pake_context; -}; - -#endif //#if ((ENABLE_HSM_SPAKE_VERIFIER) || (ENABLE_HSM_SPAKE_PROVER)) - -#if ENABLE_HSM_GENERATE_EC_KEY -/* Nist256 Key pair HSM class */ - -class P256PublicKeyHSM : public P256PublicKey -{ -public: - P256PublicKeyHSM() { PublicKeyid = 0; } - - size_t Length() const override { return kP256_PublicKey_Length; } - operator uint8_t *() override { return bytes; } - operator const uint8_t *() const override { return bytes; } - - const uint8_t * ConstBytes() const override { return &bytes[0]; } - uint8_t * Bytes() override { return &bytes[0]; } - bool IsUncompressed() const override - { - constexpr uint8_t kUncompressedPointMarker = 0x04; - // SEC1 definition of an uncompressed point is (0x04 || X || Y) where X and Y are - // raw zero-padded big-endian large integers of the group size. - return (Length() == ((kP256_FE_Length * 2) + 1)) && (ConstBytes()[0] == kUncompressedPointMarker); - } - - void SetPublicKeyId(uint32_t id) { PublicKeyid = id; } - - CHIP_ERROR ECDSA_validate_msg_signature(const uint8_t * msg, size_t msg_length, - const P256ECDSASignature & signature) const override; - - CHIP_ERROR ECDSA_validate_hash_signature(const uint8_t * hash, size_t hash_length, - const P256ECDSASignature & signature) const override; - -private: - uint8_t bytes[kP256_PublicKey_Length]; - uint32_t PublicKeyid; -}; - -class P256KeypairHSM : public P256Keypair -{ -public: - P256KeypairHSM() - { - provisioned_key = false; - keyid = 0; - } - - ~P256KeypairHSM(); - - virtual CHIP_ERROR Initialize(ECPKeyTarget key_target) override; - - virtual CHIP_ERROR Serialize(P256SerializedKeypair & output) const override; - - virtual CHIP_ERROR Deserialize(P256SerializedKeypair & input) override; - - virtual CHIP_ERROR ECDSA_sign_msg(const uint8_t * msg, size_t msg_length, P256ECDSASignature & out_signature) const override; - - virtual CHIP_ERROR ECDH_derive_secret(const P256PublicKey & remote_public_key, - P256ECDHDerivedSecret & out_secret) const override; - - CHIP_ERROR NewCertificateSigningRequest(uint8_t * csr, size_t & csr_length) const override; - - const P256PublicKeyHSM & Pubkey() const override { return mPublicKeyHSM; } - - bool provisioned_key; - - void SetKeyId(uint32_t id) { keyid = id; } - - uint32_t GetKeyId(void) { return keyid; } - -private: - uint32_t keyid; - P256PublicKeyHSM mPublicKeyHSM; -}; - -#endif //#if ENABLE_HSM_GENERATE_EC_KEY - -#if ENABLE_HSM_PBKDF2_SHA256 - -class PBKDF2_sha256HSM : public PBKDF2_sha256 -{ -public: - PBKDF2_sha256HSM(); - ~PBKDF2_sha256HSM(); - - virtual CHIP_ERROR pbkdf2_sha256(const uint8_t * password, size_t plen, const uint8_t * salt, size_t slen, - unsigned int iteration_count, uint32_t key_length, uint8_t * output) override; - - void SetKeyId(uint32_t id) { keyid = id; } - - uint32_t GetKeyId() { return keyid; } - -private: - uint32_t keyid; -}; - -#endif //#if ENABLE_HSM_PBKDF2_SHA256 - -#if ENABLE_HSM_HKDF_SHA256 - -class HKDF_shaHSM : public HKDF_sha -{ -public: - HKDF_shaHSM(); - ~HKDF_shaHSM(); - - virtual CHIP_ERROR HKDF_SHA256(const uint8_t * secret, const size_t secret_length, const uint8_t * salt, - const size_t salt_length, const uint8_t * info, const size_t info_length, uint8_t * out_buffer, - size_t out_length) override; - -private: - uint32_t keyid; -}; - -#endif //#if ENABLE_HSM_HKDF_SHA256 - -#if ENABLE_HSM_HMAC_SHA256 - -class HMAC_shaHSM : public HMAC_sha -{ -public: - HMAC_shaHSM(); - ~HMAC_shaHSM(); - - virtual CHIP_ERROR HMAC_SHA256(const uint8_t * key, size_t key_length, const uint8_t * message, size_t message_length, - uint8_t * out_buffer, size_t out_length) override; - -private: - uint32_t keyid; -}; - -#endif //#if ENABLE_HSM_HMAC_SHA256 - -} // namespace Crypto -} // namespace chip diff --git a/src/crypto/hsm/CHIPCryptoPALHsm_config.h b/src/crypto/hsm/CHIPCryptoPALHsm_config.h deleted file mode 100644 index 27d6eb2e1e33d2..00000000000000 --- a/src/crypto/hsm/CHIPCryptoPALHsm_config.h +++ /dev/null @@ -1,75 +0,0 @@ -/* - * - * Copyright (c) 2020 Project CHIP Authors - * - * 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. - */ - -/** - * @file - * Header that exposes the options to enable HSM for required crypto operations. - */ - -#pragma once - -/* - * Enable HSM for SPAKE VERIFIER - */ -#define ENABLE_HSM_SPAKE_VERIFIER 0 - -/* - * Enable HSM for SPAKE PROVER - */ -#define ENABLE_HSM_SPAKE_PROVER 0 - -/* - * Enable HSM for Generate EC Key - */ -#define ENABLE_HSM_GENERATE_EC_KEY 1 - -/* - * Enable HSM for PBKDF SHA256 - */ -#define ENABLE_HSM_PBKDF2_SHA256 0 - -/* - * Enable HSM for HKDF SHA256 - */ -#define ENABLE_HSM_HKDF_SHA256 0 - -/* - * Enable HSM for HMAC SHA256 - */ -#define ENABLE_HSM_HMAC_SHA256 0 - -#if ((CHIP_CRYPTO_HSM) && ((ENABLE_HSM_SPAKE_VERIFIER) || (ENABLE_HSM_SPAKE_PROVER))) -#define ENABLE_HSM_SPAKE -#endif - -#if ((CHIP_CRYPTO_HSM) && (ENABLE_HSM_GENERATE_EC_KEY)) -#define ENABLE_HSM_EC_KEY -//#define ENABLE_HSM_ECDSA_VERIFY -//#define ENABLE_HSM_DEVICE_ATTESTATION -#endif - -#if ((CHIP_CRYPTO_HSM) && (ENABLE_HSM_PBKDF2_SHA256)) -#define ENABLE_HSM_PBKDF2 -#endif - -#if ((CHIP_CRYPTO_HSM) && (ENABLE_HSM_HKDF_SHA256)) -#define ENABLE_HSM_HKDF -#endif - -#if ((CHIP_CRYPTO_HSM) && (ENABLE_HSM_HMAC_SHA256)) -#define ENABLE_HSM_HMAC -#endif diff --git a/src/crypto/hsm/nxp/PersistentStorageOperationalKeystoreHSM.cpp b/src/crypto/hsm/nxp/PersistentStorageOperationalKeystoreHSM.cpp deleted file mode 100644 index 3b0185b03f9250..00000000000000 --- a/src/crypto/hsm/nxp/PersistentStorageOperationalKeystoreHSM.cpp +++ /dev/null @@ -1,274 +0,0 @@ -/* - * 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 - -#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(); - 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(Crypto::ECPKeyTarget::ECDSA); - 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(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(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(); - - 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(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 deleted file mode 100644 index bc00feaa8bb8d0..00000000000000 --- a/src/crypto/hsm/nxp/PersistentStorageOperationalKeystoreHSM.h +++ /dev/null @@ -1,99 +0,0 @@ -/* - * 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 -#include -#include -#include -#include -#include - -#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 diff --git a/src/crypto/hsm/nxp/README.md b/src/crypto/hsm/nxp/README.md deleted file mode 100644 index 0a6d492cdf72d3..00000000000000 --- a/src/crypto/hsm/nxp/README.md +++ /dev/null @@ -1,31 +0,0 @@ -# Using SE05X for crypto operations - -## Introduction - -CHIPCryptoPALHsm*SE05X*\*.cpp file provides the integration of secure element -(SE05x) in crypto layer of CHIP stack. By enabling the required directives in -CHIPCryptoPALHsm_config.h header file, required crypto operations can be -performed using SE05x. By default, the secure element is enabled for PAKE -(Verifier), HKDF, HMAC (SHA256). - -Following are the list operations supported by secure element. - - 1. PAKE - 2. ECC KEY - P256 (Disabled by default) - 3. PBKDF (Disabled by default) - 4. HKDF - 5. HMAC (SHA256) - -## Build - -- Use the following gn build arguments to enable the secure element in crypto - layer, - -``` -chip_with_se05x=1 ==> To enable Se05x -host = "host_k32w" ==> To set host -``` - -## Known Limitations: - -- None diff --git a/src/crypto/tests/CHIPCryptoPALTest.cpp b/src/crypto/tests/CHIPCryptoPALTest.cpp index 702a96de7217e0..5f377841935725 100644 --- a/src/crypto/tests/CHIPCryptoPALTest.cpp +++ b/src/crypto/tests/CHIPCryptoPALTest.cpp @@ -37,9 +37,6 @@ #include #include -#if CHIP_CRYPTO_HSM -#include -#endif #include #include #include @@ -62,8 +59,6 @@ #include #include -#define HSM_ECC_KEYID 0x11223344 - #include #include #include @@ -84,40 +79,11 @@ using namespace chip::TLV; namespace { -#ifdef ENABLE_HSM_EC_KEY -class Test_P256Keypair : public P256KeypairHSM -{ -public: - Test_P256Keypair() { SetKeyId(HSM_ECC_KEYID); } - Test_P256Keypair(uint32_t keyId) { SetKeyId(keyId); } -}; -#else using Test_P256Keypair = P256Keypair; -#endif - -#ifdef ENABLE_HSM_SPAKE -using TestSpake2p_P256_SHA256_HKDF_HMAC = Spake2pHSM_P256_SHA256_HKDF_HMAC; -#else using TestSpake2p_P256_SHA256_HKDF_HMAC = Spake2p_P256_SHA256_HKDF_HMAC; -#endif - -#ifdef ENABLE_HSM_PBKDF2 -using TestPBKDF2_sha256 = PBKDF2_sha256HSM; -#else using TestPBKDF2_sha256 = PBKDF2_sha256; -#endif - -#ifdef ENABLE_HSM_HKDF -using TestHKDF_sha = HKDF_shaHSM; -#else using TestHKDF_sha = HKDF_sha; -#endif - -#ifdef ENABLE_HSM_HMAC -using TestHMAC_sha = HMAC_shaHSM; -#else using TestHMAC_sha = HMAC_sha; -#endif // Helper class to verify that all mbedTLS heap objects are released at the end of a test. #if CHIP_CRYPTO_MBEDTLS && defined(MBEDTLS_MEMORY_DEBUG) @@ -1045,11 +1011,7 @@ static void TestECDH_EstablishSecret(nlTestSuite * inSuite, void * inContext) Test_P256Keypair keypair1; NL_TEST_ASSERT(inSuite, keypair1.Initialize(ECPKeyTarget::ECDH) == CHIP_NO_ERROR); -#ifdef ENABLE_HSM_EC_KEY - Test_P256Keypair keypair2(HSM_ECC_KEYID + 1); -#else Test_P256Keypair keypair2; -#endif NL_TEST_ASSERT(inSuite, keypair2.Initialize(ECPKeyTarget::ECDH) == CHIP_NO_ERROR); P256ECDHDerivedSecret out_secret1; @@ -1664,12 +1626,7 @@ static void TestSPAKE2P_spake2p_PointIsValid(nlTestSuite * inSuite, void * inCon // We need to "generate" specific field elements // to do so we need to override the specific method -class Test_Spake2p_P256_SHA256_HKDF_HMAC : -#ifdef ENABLE_HSM_SPAKE - public Spake2pHSM_P256_SHA256_HKDF_HMAC -#else - public Spake2p_P256_SHA256_HKDF_HMAC -#endif +class Test_Spake2p_P256_SHA256_HKDF_HMAC : public Spake2p_P256_SHA256_HKDF_HMAC { public: CHIP_ERROR TestSetFE(const uint8_t * fe_in, size_t fe_in_len) diff --git a/src/platform/nxp/crypto/nxp_crypto.gni b/src/platform/nxp/crypto/nxp_crypto.gni new file mode 100644 index 00000000000000..dcc4dcae7c8f8f --- /dev/null +++ b/src/platform/nxp/crypto/nxp_crypto.gni @@ -0,0 +1,21 @@ +# Copyright (c) 2022 Project CHIP Authors +# +# 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. + +declare_args() { + nxp_crypto_impl = "" + nxp_crypto_mw_root = "" +} + +assert(nxp_crypto_impl != "", "nxp_crypto_impl should be defined") +assert(nxp_crypto_mw_root != "", "nxp_crypto_mw_root should be defined") diff --git a/src/platform/nxp/crypto/se05x/BUILD.gn b/src/platform/nxp/crypto/se05x/BUILD.gn new file mode 100644 index 00000000000000..dc41efa0977635 --- /dev/null +++ b/src/platform/nxp/crypto/se05x/BUILD.gn @@ -0,0 +1,65 @@ +# Copyright (c) 2020 Project CHIP Authors +# +# 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. + +import("//build_overrides/chip.gni") +import("//build_overrides/nlassert.gni") +import("${chip_root}/build/chip/buildconfig_header.gni") +import("${chip_root}/src/crypto/crypto.gni") +import("${chip_root}/src/platform/nxp/crypto/se05x/args.gni") + +if (chip_crypto == "platform") { + import("//build_overrides/mbedtls.gni") +} + +source_set("public_headers") { + sources = [ + "CHIPCryptoPAL.h", + "OperationalKeystore.h", + ] + + public_deps = [ + "${chip_root}/src/lib/asn1", + "${chip_root}/src/lib/core", + "${chip_root}/src/lib/support", + "${nlassert_root}:nlassert", + ] +} + +static_library("nxp_crypto_lib") { + sources = [ + "${chip_root}/src/platform/nxp/crypto/se05x/CHIPCryptoPALHost.cpp", + "${chip_root}/src/platform/nxp/crypto/se05x/CHIPCryptoPALHsm_se05x_hkdf.cpp", + "${chip_root}/src/platform/nxp/crypto/se05x/CHIPCryptoPALHsm_se05x_hmac.cpp", + "${chip_root}/src/platform/nxp/crypto/se05x/CHIPCryptoPALHsm_se05x_p256.cpp", + "${chip_root}/src/platform/nxp/crypto/se05x/CHIPCryptoPALHsm_se05x_pbkdf.cpp", + "${chip_root}/src/platform/nxp/crypto/se05x/CHIPCryptoPALHsm_se05x_rng.cpp", + "${chip_root}/src/platform/nxp/crypto/se05x/CHIPCryptoPALHsm_se05x_utils.cpp", + "${chip_root}/src/platform/nxp/crypto/se05x/CHIPCryptoPAL_HostFallBack.cpp", + ] + + public_deps = [ ":public_headers" ] + deps = [ "${chip_root}/${nxp_crypto_mw_root}:se05x" ] + + external_mbedtls = current_os == "zephyr" + + if (!external_mbedtls) { + public_deps += [ "${mbedtls_root}:mbedtls" ] + } + + include_dirs = [ + ".", + "${chip_root}/src/crypto", + "${chip_root}/src/platform/nxp/crypto/se05x", + ] +} diff --git a/src/platform/nxp/crypto/se05x/CHIPCryptoPALHost.cpp b/src/platform/nxp/crypto/se05x/CHIPCryptoPALHost.cpp new file mode 100644 index 00000000000000..525d3e32ba654f --- /dev/null +++ b/src/platform/nxp/crypto/se05x/CHIPCryptoPALHost.cpp @@ -0,0 +1,1351 @@ +/* + * + * Copyright (c) 2020-2022 Project CHIP Authors + * + * 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. + */ + +/** + * @file + * mbedTLS based implementation of CHIP crypto primitives + */ + +#include "CHIPCryptoPAL.h" + +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#if defined(MBEDTLS_X509_CRT_PARSE_C) +#include +#endif // defined(MBEDTLS_X509_CRT_PARSE_C) +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +namespace chip { +namespace Crypto { + +#define MAX_ERROR_STR_LEN 128 +#define NUM_BYTES_IN_SHA256_HASH 32 + +// In mbedTLS 3.0.0 direct access to structure fields was replaced with using MBEDTLS_PRIVATE macro. +#if (MBEDTLS_VERSION_NUMBER >= 0x03000000) +#define CHIP_CRYPTO_PAL_PRIVATE(x) MBEDTLS_PRIVATE(x) +#else +#define CHIP_CRYPTO_PAL_PRIVATE(x) x +#endif + +#if (MBEDTLS_VERSION_NUMBER >= 0x03000000 && MBEDTLS_VERSION_NUMBER < 0x03010000) +#define CHIP_CRYPTO_PAL_PRIVATE_X509(x) MBEDTLS_PRIVATE(x) +#else +#define CHIP_CRYPTO_PAL_PRIVATE_X509(x) x +#endif + +typedef struct +{ + bool mInitialized; + bool mDRBGSeeded; + mbedtls_ctr_drbg_context mDRBGCtxt; + mbedtls_entropy_context mEntropy; +} EntropyContext; + +static EntropyContext gsEntropyContext; + +static void _log_mbedTLS_error(int error_code) +{ + if (error_code != 0) + { +#if defined(MBEDTLS_ERROR_C) + char error_str[MAX_ERROR_STR_LEN]; + mbedtls_strerror(error_code, error_str, sizeof(error_str)); + ChipLogError(Crypto, "mbedTLS error: %s", error_str); +#else + // Error codes defined in 16-bit negative hex numbers. Ease lookup by printing likewise + ChipLogError(Crypto, "mbedTLS error: -0x%04X", -static_cast(error_code)); +#endif + } +} + +static bool _isValidTagLength(size_t tag_length) +{ + if (tag_length == 8 || tag_length == 12 || tag_length == 16) + { + return true; + } + return false; +} + +CHIP_ERROR AES_CCM_encrypt(const uint8_t * plaintext, size_t plaintext_length, const uint8_t * aad, size_t aad_length, + const Aes128KeyHandle & key, const uint8_t * nonce, size_t nonce_length, uint8_t * ciphertext, + uint8_t * tag, size_t tag_length) +{ + CHIP_ERROR error = CHIP_NO_ERROR; + int result = 1; + + mbedtls_ccm_context context; + mbedtls_ccm_init(&context); + + VerifyOrExit(plaintext != nullptr || plaintext_length == 0, error = CHIP_ERROR_INVALID_ARGUMENT); + VerifyOrExit(ciphertext != nullptr || plaintext_length == 0, error = CHIP_ERROR_INVALID_ARGUMENT); + VerifyOrExit(nonce != nullptr, error = CHIP_ERROR_INVALID_ARGUMENT); + VerifyOrExit(nonce_length > 0, error = CHIP_ERROR_INVALID_ARGUMENT); + VerifyOrExit(tag != nullptr, error = CHIP_ERROR_INVALID_ARGUMENT); + VerifyOrExit(_isValidTagLength(tag_length), error = CHIP_ERROR_INVALID_ARGUMENT); + if (aad_length > 0) + { + VerifyOrExit(aad != nullptr, error = CHIP_ERROR_INVALID_ARGUMENT); + } + + // Size of key is expressed in bits, hence the multiplication by 8. + result = mbedtls_ccm_setkey(&context, MBEDTLS_CIPHER_ID_AES, key.As(), sizeof(Aes128KeyByteArray) * 8); + VerifyOrExit(result == 0, error = CHIP_ERROR_INTERNAL); + + // Encrypt + result = mbedtls_ccm_encrypt_and_tag(&context, plaintext_length, Uint8::to_const_uchar(nonce), nonce_length, + Uint8::to_const_uchar(aad), aad_length, Uint8::to_const_uchar(plaintext), + Uint8::to_uchar(ciphertext), Uint8::to_uchar(tag), tag_length); + _log_mbedTLS_error(result); + VerifyOrExit(result == 0, error = CHIP_ERROR_INTERNAL); + +exit: + mbedtls_ccm_free(&context); + return error; +} + +CHIP_ERROR AES_CCM_decrypt(const uint8_t * ciphertext, size_t ciphertext_len, const uint8_t * aad, size_t aad_len, + const uint8_t * tag, size_t tag_length, const Aes128KeyHandle & key, const uint8_t * nonce, + size_t nonce_length, uint8_t * plaintext) +{ + CHIP_ERROR error = CHIP_NO_ERROR; + int result = 1; + + mbedtls_ccm_context context; + mbedtls_ccm_init(&context); + + VerifyOrExit(plaintext != nullptr || ciphertext_len == 0, error = CHIP_ERROR_INVALID_ARGUMENT); + VerifyOrExit(ciphertext != nullptr || ciphertext_len == 0, error = CHIP_ERROR_INVALID_ARGUMENT); + VerifyOrExit(tag != nullptr, error = CHIP_ERROR_INVALID_ARGUMENT); + VerifyOrExit(_isValidTagLength(tag_length), error = CHIP_ERROR_INVALID_ARGUMENT); + VerifyOrExit(nonce != nullptr, error = CHIP_ERROR_INVALID_ARGUMENT); + VerifyOrExit(nonce_length > 0, error = CHIP_ERROR_INVALID_ARGUMENT); + if (aad_len > 0) + { + VerifyOrExit(aad != nullptr, error = CHIP_ERROR_INVALID_ARGUMENT); + } + + // Size of key is expressed in bits, hence the multiplication by 8. + result = mbedtls_ccm_setkey(&context, MBEDTLS_CIPHER_ID_AES, key.As(), sizeof(Aes128KeyByteArray) * 8); + VerifyOrExit(result == 0, error = CHIP_ERROR_INTERNAL); + + // Decrypt + result = mbedtls_ccm_auth_decrypt(&context, ciphertext_len, Uint8::to_const_uchar(nonce), nonce_length, + Uint8::to_const_uchar(aad), aad_len, Uint8::to_const_uchar(ciphertext), + Uint8::to_uchar(plaintext), Uint8::to_const_uchar(tag), tag_length); + _log_mbedTLS_error(result); + VerifyOrExit(result == 0, error = CHIP_ERROR_INTERNAL); + +exit: + mbedtls_ccm_free(&context); + return error; +} + +CHIP_ERROR Hash_SHA256(const uint8_t * data, const size_t data_length, uint8_t * out_buffer) +{ + // zero data length hash is supported. + VerifyOrReturnError(data != nullptr, CHIP_ERROR_INVALID_ARGUMENT); + VerifyOrReturnError(out_buffer != nullptr, CHIP_ERROR_INVALID_ARGUMENT); + +#if (MBEDTLS_VERSION_NUMBER >= 0x03000000) + const int result = mbedtls_sha256(Uint8::to_const_uchar(data), data_length, Uint8::to_uchar(out_buffer), 0); +#else + const int result = mbedtls_sha256_ret(Uint8::to_const_uchar(data), data_length, Uint8::to_uchar(out_buffer), 0); +#endif + + VerifyOrReturnError(result == 0, CHIP_ERROR_INTERNAL); + + return CHIP_NO_ERROR; +} + +CHIP_ERROR Hash_SHA1(const uint8_t * data, const size_t data_length, uint8_t * out_buffer) +{ + // zero data length hash is supported. + VerifyOrReturnError(out_buffer != nullptr, CHIP_ERROR_INVALID_ARGUMENT); + +#if (MBEDTLS_VERSION_NUMBER >= 0x03000000) + const int result = mbedtls_sha1(Uint8::to_const_uchar(data), data_length, Uint8::to_uchar(out_buffer)); +#else + const int result = mbedtls_sha1_ret(Uint8::to_const_uchar(data), data_length, Uint8::to_uchar(out_buffer)); +#endif + + VerifyOrReturnError(result == 0, CHIP_ERROR_INTERNAL); + + return CHIP_NO_ERROR; +} + +static_assert(kMAX_Hash_SHA256_Context_Size >= sizeof(mbedtls_sha256_context), + "kMAX_Hash_SHA256_Context_Size is too small for the size of underlying mbedtls_sha256_context"); + +static inline mbedtls_sha256_context * to_inner_hash_sha256_context(HashSHA256OpaqueContext * context) +{ + return SafePointerCast(context); +} + +Hash_SHA256_stream::Hash_SHA256_stream(void) +{ + mbedtls_sha256_context * context = to_inner_hash_sha256_context(&mContext); + mbedtls_sha256_init(context); +} + +Hash_SHA256_stream::~Hash_SHA256_stream(void) +{ + mbedtls_sha256_context * context = to_inner_hash_sha256_context(&mContext); + mbedtls_sha256_free(context); + Clear(); +} + +CHIP_ERROR Hash_SHA256_stream::Begin(void) +{ + mbedtls_sha256_context * const context = to_inner_hash_sha256_context(&mContext); + +#if (MBEDTLS_VERSION_NUMBER >= 0x03000000) + const int result = mbedtls_sha256_starts(context, 0); +#else + const int result = mbedtls_sha256_starts_ret(context, 0); +#endif + + VerifyOrReturnError(result == 0, CHIP_ERROR_INTERNAL); + + return CHIP_NO_ERROR; +} + +CHIP_ERROR Hash_SHA256_stream::AddData(const ByteSpan data) +{ + mbedtls_sha256_context * const context = to_inner_hash_sha256_context(&mContext); + +#if (MBEDTLS_VERSION_NUMBER >= 0x03000000) + const int result = mbedtls_sha256_update(context, Uint8::to_const_uchar(data.data()), data.size()); +#else + const int result = mbedtls_sha256_update_ret(context, Uint8::to_const_uchar(data.data()), data.size()); +#endif + + VerifyOrReturnError(result == 0, CHIP_ERROR_INTERNAL); + + return CHIP_NO_ERROR; +} + +CHIP_ERROR Hash_SHA256_stream::GetDigest(MutableByteSpan & out_buffer) +{ + mbedtls_sha256_context * context = to_inner_hash_sha256_context(&mContext); + + // Back-up context as we are about to finalize the hash to extract digest. + mbedtls_sha256_context previous_ctx; + mbedtls_sha256_init(&previous_ctx); + mbedtls_sha256_clone(&previous_ctx, context); + + // Pad + compute digest, then finalize context. It is restored next line to continue. + CHIP_ERROR result = Finish(out_buffer); + + // Restore context prior to finalization. + mbedtls_sha256_clone(context, &previous_ctx); + mbedtls_sha256_free(&previous_ctx); + + return result; +} + +CHIP_ERROR Hash_SHA256_stream::Finish(MutableByteSpan & out_buffer) +{ + VerifyOrReturnError(out_buffer.size() >= kSHA256_Hash_Length, CHIP_ERROR_BUFFER_TOO_SMALL); + mbedtls_sha256_context * const context = to_inner_hash_sha256_context(&mContext); + +#if (MBEDTLS_VERSION_NUMBER >= 0x03000000) + const int result = mbedtls_sha256_finish(context, Uint8::to_uchar(out_buffer.data())); +#else + const int result = mbedtls_sha256_finish_ret(context, Uint8::to_uchar(out_buffer.data())); +#endif + + VerifyOrReturnError(result == 0, CHIP_ERROR_INTERNAL); + out_buffer = out_buffer.SubSpan(0, kSHA256_Hash_Length); + + return CHIP_NO_ERROR; +} + +void Hash_SHA256_stream::Clear(void) +{ + mbedtls_platform_zeroize(this, sizeof(*this)); +} + +static EntropyContext * get_entropy_context() +{ + if (!gsEntropyContext.mInitialized) + { + mbedtls_entropy_init(&gsEntropyContext.mEntropy); + mbedtls_ctr_drbg_init(&gsEntropyContext.mDRBGCtxt); + + gsEntropyContext.mInitialized = true; + } + + return &gsEntropyContext; +} + +CHIP_ERROR add_entropy_source(entropy_source fn_source, void * p_source, size_t threshold) +{ + VerifyOrReturnError(fn_source != nullptr, CHIP_ERROR_INVALID_ARGUMENT); + + EntropyContext * const entropy_ctxt = get_entropy_context(); + VerifyOrReturnError(entropy_ctxt != nullptr, CHIP_ERROR_INTERNAL); + + const int result = + mbedtls_entropy_add_source(&entropy_ctxt->mEntropy, fn_source, p_source, threshold, MBEDTLS_ENTROPY_SOURCE_STRONG); + VerifyOrReturnError(result == 0, CHIP_ERROR_INTERNAL); + return CHIP_NO_ERROR; +} + +static int CryptoRNG(void * ctxt, uint8_t * out_buffer, size_t out_length) +{ + return (chip::Crypto::DRBG_get_bytes(out_buffer, out_length) == CHIP_NO_ERROR) ? 0 : 1; +} + +mbedtls_ecp_group_id MapECPGroupId(SupportedECPKeyTypes keyType) +{ + switch (keyType) + { + case SupportedECPKeyTypes::ECP256R1: + return MBEDTLS_ECP_DP_SECP256R1; + default: + return MBEDTLS_ECP_DP_NONE; + } +} + +static inline mbedtls_ecp_keypair * to_keypair(P256KeypairContext * context) +{ + return SafePointerCast(context); +} + +static inline const mbedtls_ecp_keypair * to_const_keypair(const P256KeypairContext * context) +{ + return SafePointerCast(context); +} + +// THE BELOW IS FROM `third_party/openthread/repo/third_party/mbedtls/repo/library/constant_time.c` since +// mbedtls_ct_memcmp is not available on Linux somehow :( +int mbedtls_ct_memcmp_copy(const void * a, const void * b, size_t n) +{ + size_t i; + volatile const unsigned char * A = (volatile const unsigned char *) a; + volatile const unsigned char * B = (volatile const unsigned char *) b; + volatile unsigned char diff = 0; + + for (i = 0; i < n; i++) + { + /* Read volatile data in order before computing diff. + * This avoids IAR compiler warning: + * 'the order of volatile accesses is undefined ..' */ + unsigned char x = A[i], y = B[i]; + diff |= x ^ y; + } + + return ((int) diff); +} + +bool IsBufferContentEqualConstantTime(const void * a, const void * b, size_t n) +{ + return mbedtls_ct_memcmp_copy(a, b, n) == 0; +} + +void P256Keypair::Clear() +{ + if (mInitialized) + { + mbedtls_ecp_keypair * keypair = to_keypair(&mKeypair); + mbedtls_ecp_keypair_free(keypair); + mInitialized = false; + } +} + +CHIP_ERROR VerifyCertificateSigningRequest(const uint8_t * csr_buf, size_t csr_length, P256PublicKey & pubkey) +{ +#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. + // 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; + size_t pubkey_size = 0; + + mbedtls_ecp_keypair * keypair = nullptr; + + P256ECDSASignature signature; + MutableByteSpan out_raw_sig_span(signature.Bytes(), signature.Capacity()); + + mbedtls_x509_csr csr; + mbedtls_x509_csr_init(&csr); + + int result = mbedtls_x509_csr_parse_der(&csr, csr_buf, csr_length); + VerifyOrExit(result == 0, error = CHIP_ERROR_INTERNAL); + + // Verify the signature algorithm and public key type + VerifyOrExit(csr.CHIP_CRYPTO_PAL_PRIVATE(sig_md) == MBEDTLS_MD_SHA256, error = CHIP_ERROR_UNSUPPORTED_SIGNATURE_TYPE); + VerifyOrExit(csr.CHIP_CRYPTO_PAL_PRIVATE(sig_pk) == MBEDTLS_PK_ECDSA, error = CHIP_ERROR_WRONG_KEY_TYPE); + + keypair = mbedtls_pk_ec(csr.CHIP_CRYPTO_PAL_PRIVATE_X509(pk)); + + // Copy the public key from the CSR + result = mbedtls_ecp_point_write_binary(&keypair->CHIP_CRYPTO_PAL_PRIVATE(grp), &keypair->CHIP_CRYPTO_PAL_PRIVATE(Q), + MBEDTLS_ECP_PF_UNCOMPRESSED, &pubkey_size, Uint8::to_uchar(pubkey), pubkey.Length()); + + VerifyOrExit(result == 0, error = CHIP_ERROR_INTERNAL); + VerifyOrExit(pubkey_size == pubkey.Length(), error = CHIP_ERROR_INTERNAL); + + // Convert DER signature to raw signature + error = EcdsaAsn1SignatureToRaw(kP256_FE_Length, + ByteSpan{ csr.CHIP_CRYPTO_PAL_PRIVATE(sig).CHIP_CRYPTO_PAL_PRIVATE_X509(p), + csr.CHIP_CRYPTO_PAL_PRIVATE(sig).CHIP_CRYPTO_PAL_PRIVATE_X509(len) }, + out_raw_sig_span); + + VerifyOrExit(error == CHIP_NO_ERROR, error = CHIP_ERROR_INVALID_ARGUMENT); + VerifyOrExit(out_raw_sig_span.size() == (kP256_FE_Length * 2), error = CHIP_ERROR_INTERNAL); + signature.SetLength(out_raw_sig_span.size()); + + // Verify the signature using the public key + error = pubkey.ECDSA_validate_msg_signature(csr.CHIP_CRYPTO_PAL_PRIVATE_X509(cri).CHIP_CRYPTO_PAL_PRIVATE_X509(p), + csr.CHIP_CRYPTO_PAL_PRIVATE_X509(cri).CHIP_CRYPTO_PAL_PRIVATE_X509(len), signature); + + SuccessOrExit(error); + +exit: + mbedtls_x509_csr_free(&csr); + _log_mbedTLS_error(result); + return error; +#else + ChipLogError(Crypto, "MBEDTLS_X509_CSR_PARSE_C is not enabled. CSR cannot be parsed"); + return CHIP_ERROR_UNSUPPORTED_CHIP_FEATURE; +#endif +} + +typedef struct Spake2p_Context +{ + mbedtls_ecp_group curve; + mbedtls_ecp_point M; + mbedtls_ecp_point N; + mbedtls_ecp_point X; + mbedtls_ecp_point Y; + mbedtls_ecp_point L; + mbedtls_ecp_point Z; + mbedtls_ecp_point V; + + mbedtls_mpi w0; + mbedtls_mpi w1; + mbedtls_mpi xy; + mbedtls_mpi tempbn; +} Spake2p_Context; + +static inline Spake2p_Context * to_inner_spake2p_context(Spake2pOpaqueContext * context) +{ + return SafePointerCast(context); +} + +CHIP_ERROR Spake2p_P256_SHA256_HKDF_HMAC::InitInternal(void) +{ + CHIP_ERROR error = CHIP_NO_ERROR; + int result = 0; + + Spake2p_Context * context = to_inner_spake2p_context(&mSpake2pContext); + + memset(context, 0, sizeof(Spake2p_Context)); + + mbedtls_ecp_group_init(&context->curve); + result = mbedtls_ecp_group_load(&context->curve, MBEDTLS_ECP_DP_SECP256R1); + VerifyOrExit(result == 0, error = CHIP_ERROR_INTERNAL); + + VerifyOrExit(mbedtls_md_info_from_type(MBEDTLS_MD_SHA256) != nullptr, error = CHIP_ERROR_INTERNAL); + + mbedtls_ecp_point_init(&context->M); + mbedtls_ecp_point_init(&context->N); + mbedtls_ecp_point_init(&context->X); + mbedtls_ecp_point_init(&context->Y); + mbedtls_ecp_point_init(&context->L); + mbedtls_ecp_point_init(&context->V); + mbedtls_ecp_point_init(&context->Z); + M = &context->M; + N = &context->N; + X = &context->X; + Y = &context->Y; + L = &context->L; + V = &context->V; + Z = &context->Z; + + mbedtls_mpi_init(&context->w0); + mbedtls_mpi_init(&context->w1); + mbedtls_mpi_init(&context->xy); + mbedtls_mpi_init(&context->tempbn); + w0 = &context->w0; + w1 = &context->w1; + xy = &context->xy; + tempbn = &context->tempbn; + + G = &context->curve.G; + order = &context->curve.N; + + return error; + +exit: + _log_mbedTLS_error(result); + Clear(); + return error; +} + +void Spake2p_P256_SHA256_HKDF_HMAC::Clear() +{ + VerifyOrReturn(state != CHIP_SPAKE2P_STATE::PREINIT); + + Spake2p_Context * context = to_inner_spake2p_context(&mSpake2pContext); + mbedtls_ecp_point_free(&context->M); + mbedtls_ecp_point_free(&context->N); + mbedtls_ecp_point_free(&context->X); + mbedtls_ecp_point_free(&context->Y); + mbedtls_ecp_point_free(&context->L); + mbedtls_ecp_point_free(&context->Z); + mbedtls_ecp_point_free(&context->V); + + mbedtls_mpi_free(&context->w0); + mbedtls_mpi_free(&context->w1); + mbedtls_mpi_free(&context->xy); + mbedtls_mpi_free(&context->tempbn); + + mbedtls_ecp_group_free(&context->curve); + state = CHIP_SPAKE2P_STATE::PREINIT; +} + +CHIP_ERROR Spake2p_P256_SHA256_HKDF_HMAC::Mac(const uint8_t * key, size_t key_len, const uint8_t * in, size_t in_len, + MutableByteSpan & out_span) +{ + HMAC_sha hmac; + VerifyOrReturnError(out_span.size() >= kSHA256_Hash_Length, CHIP_ERROR_BUFFER_TOO_SMALL); + ReturnErrorOnFailure(hmac.HMAC_SHA256(key, key_len, in, in_len, out_span.data(), kSHA256_Hash_Length)); + out_span = out_span.SubSpan(0, kSHA256_Hash_Length); + return CHIP_NO_ERROR; +} + +CHIP_ERROR Spake2p_P256_SHA256_HKDF_HMAC::MacVerify(const uint8_t * key, size_t key_len, const uint8_t * mac, size_t mac_len, + const uint8_t * in, size_t in_len) +{ + CHIP_ERROR error = CHIP_NO_ERROR; + int result = 0; + + uint8_t computed_mac[kSHA256_Hash_Length]; + MutableByteSpan computed_mac_span{ computed_mac }; + VerifyOrExit(mac_len == kSHA256_Hash_Length, error = CHIP_ERROR_INVALID_ARGUMENT); + + SuccessOrExit(error = Mac(key, key_len, in, in_len, computed_mac_span)); + VerifyOrExit(computed_mac_span.size() == mac_len, error = CHIP_ERROR_INTERNAL); + + VerifyOrExit(IsBufferContentEqualConstantTime(mac, computed_mac, kSHA256_Hash_Length), error = CHIP_ERROR_INTERNAL); + +exit: + _log_mbedTLS_error(result); + return error; +} + +CHIP_ERROR Spake2p_P256_SHA256_HKDF_HMAC::FELoad(const uint8_t * in, size_t in_len, void * fe) +{ + CHIP_ERROR error = CHIP_NO_ERROR; + int result = 0; + + result = mbedtls_mpi_read_binary((mbedtls_mpi *) fe, Uint8::to_const_uchar(in), in_len); + VerifyOrExit(result == 0, error = CHIP_ERROR_INTERNAL); + + result = mbedtls_mpi_mod_mpi((mbedtls_mpi *) fe, (mbedtls_mpi *) fe, (const mbedtls_mpi *) order); + VerifyOrExit(result == 0, error = CHIP_ERROR_INTERNAL); + +exit: + _log_mbedTLS_error(result); + return error; +} + +CHIP_ERROR Spake2p_P256_SHA256_HKDF_HMAC::FEWrite(const void * fe, uint8_t * out, size_t out_len) +{ + if (mbedtls_mpi_write_binary((const mbedtls_mpi *) fe, Uint8::to_uchar(out), out_len) != 0) + { + return CHIP_ERROR_INTERNAL; + } + return CHIP_NO_ERROR; +} + +CHIP_ERROR Spake2p_P256_SHA256_HKDF_HMAC::FEGenerate(void * fe) +{ + CHIP_ERROR error = CHIP_NO_ERROR; + int result = 0; + + Spake2p_Context * context = to_inner_spake2p_context(&mSpake2pContext); + + result = mbedtls_ecp_gen_privkey(&context->curve, (mbedtls_mpi *) fe, CryptoRNG, nullptr); + VerifyOrExit(result == 0, error = CHIP_ERROR_INTERNAL); + +exit: + _log_mbedTLS_error(result); + return error; +} + +CHIP_ERROR Spake2p_P256_SHA256_HKDF_HMAC::FEMul(void * fer, const void * fe1, const void * fe2) +{ + CHIP_ERROR error = CHIP_NO_ERROR; + int result = 0; + + result = mbedtls_mpi_mul_mpi((mbedtls_mpi *) fer, (const mbedtls_mpi *) fe1, (const mbedtls_mpi *) fe2); + VerifyOrExit(result == 0, error = CHIP_ERROR_INTERNAL); + + result = mbedtls_mpi_mod_mpi((mbedtls_mpi *) fer, (mbedtls_mpi *) fer, (const mbedtls_mpi *) order); + VerifyOrExit(result == 0, error = CHIP_ERROR_INTERNAL); + +exit: + _log_mbedTLS_error(result); + return error; +} + +CHIP_ERROR Spake2p_P256_SHA256_HKDF_HMAC::PointLoad(const uint8_t * in, size_t in_len, void * R) +{ + Spake2p_Context * context = to_inner_spake2p_context(&mSpake2pContext); + + if (mbedtls_ecp_point_read_binary(&context->curve, (mbedtls_ecp_point *) R, Uint8::to_const_uchar(in), in_len) != 0) + { + return CHIP_ERROR_INTERNAL; + } + + return CHIP_NO_ERROR; +} + +CHIP_ERROR Spake2p_P256_SHA256_HKDF_HMAC::PointWrite(const void * R, uint8_t * out, size_t out_len) +{ + memset(out, 0, out_len); + + size_t mbedtls_out_len = out_len; + + Spake2p_Context * context = to_inner_spake2p_context(&mSpake2pContext); + + if (mbedtls_ecp_point_write_binary(&context->curve, (const mbedtls_ecp_point *) R, MBEDTLS_ECP_PF_UNCOMPRESSED, + &mbedtls_out_len, Uint8::to_uchar(out), out_len) != 0) + { + return CHIP_ERROR_INTERNAL; + } + + return CHIP_NO_ERROR; +} + +CHIP_ERROR Spake2p_P256_SHA256_HKDF_HMAC::PointMul(void * R, const void * P1, const void * fe1) +{ + Spake2p_Context * context = to_inner_spake2p_context(&mSpake2pContext); + + if (mbedtls_ecp_mul(&context->curve, (mbedtls_ecp_point *) R, (const mbedtls_mpi *) fe1, (const mbedtls_ecp_point *) P1, + CryptoRNG, nullptr) != 0) + { + return CHIP_ERROR_INTERNAL; + } + + return CHIP_NO_ERROR; +} + +CHIP_ERROR Spake2p_P256_SHA256_HKDF_HMAC::PointAddMul(void * R, const void * P1, const void * fe1, const void * P2, + const void * fe2) +{ + Spake2p_Context * context = to_inner_spake2p_context(&mSpake2pContext); + + if (mbedtls_ecp_muladd(&context->curve, (mbedtls_ecp_point *) R, (const mbedtls_mpi *) fe1, (const mbedtls_ecp_point *) P1, + (const mbedtls_mpi *) fe2, (const mbedtls_ecp_point *) P2) != 0) + { + return CHIP_ERROR_INTERNAL; + } + + return CHIP_NO_ERROR; +} + +CHIP_ERROR Spake2p_P256_SHA256_HKDF_HMAC::PointInvert(void * R) +{ + mbedtls_ecp_point * Rp = (mbedtls_ecp_point *) R; + Spake2p_Context * context = to_inner_spake2p_context(&mSpake2pContext); + + if (mbedtls_mpi_sub_mpi(&Rp->CHIP_CRYPTO_PAL_PRIVATE(Y), &context->curve.P, &Rp->CHIP_CRYPTO_PAL_PRIVATE(Y)) != 0) + { + return CHIP_ERROR_INTERNAL; + } + + return CHIP_NO_ERROR; +} + +CHIP_ERROR Spake2p_P256_SHA256_HKDF_HMAC::PointCofactorMul(void * R) +{ + return CHIP_NO_ERROR; +} + +CHIP_ERROR Spake2p_P256_SHA256_HKDF_HMAC::ComputeL(uint8_t * Lout, size_t * L_len, const uint8_t * w1in, size_t w1in_len) +{ + CHIP_ERROR error = CHIP_NO_ERROR; + int result = 0; + + mbedtls_ecp_group curve; + mbedtls_mpi w1_bn; + mbedtls_ecp_point Ltemp; + + mbedtls_ecp_group_init(&curve); + mbedtls_mpi_init(&w1_bn); + mbedtls_ecp_point_init(&Ltemp); + + result = mbedtls_ecp_group_load(&curve, MBEDTLS_ECP_DP_SECP256R1); + VerifyOrExit(result == 0, error = CHIP_ERROR_INTERNAL); + + result = mbedtls_mpi_read_binary(&w1_bn, Uint8::to_const_uchar(w1in), w1in_len); + VerifyOrExit(result == 0, error = CHIP_ERROR_INTERNAL); + + result = mbedtls_mpi_mod_mpi(&w1_bn, &w1_bn, &curve.N); + VerifyOrExit(result == 0, error = CHIP_ERROR_INTERNAL); + + result = mbedtls_ecp_mul(&curve, &Ltemp, &w1_bn, &curve.G, CryptoRNG, nullptr); + VerifyOrExit(result == 0, error = CHIP_ERROR_INTERNAL); + + memset(Lout, 0, *L_len); + + result = mbedtls_ecp_point_write_binary(&curve, &Ltemp, MBEDTLS_ECP_PF_UNCOMPRESSED, L_len, Uint8::to_uchar(Lout), *L_len); + VerifyOrExit(result == 0, error = CHIP_ERROR_INTERNAL); + +exit: + _log_mbedTLS_error(result); + mbedtls_ecp_point_free(&Ltemp); + mbedtls_mpi_free(&w1_bn); + mbedtls_ecp_group_free(&curve); + + return error; +} + +CHIP_ERROR Spake2p_P256_SHA256_HKDF_HMAC::PointIsValid(void * R) +{ + Spake2p_Context * context = to_inner_spake2p_context(&mSpake2pContext); + + if (mbedtls_ecp_check_pubkey(&context->curve, (mbedtls_ecp_point *) R) != 0) + { + return CHIP_ERROR_INTERNAL; + } + + return CHIP_NO_ERROR; +} + +namespace { + +#if defined(MBEDTLS_X509_CRT_PARSE_C) +bool IsTimeGreaterThanEqual(const mbedtls_x509_time * const timeA, const mbedtls_x509_time * const timeB) +{ + + // checks if two values are different and if yes, then returns first > second. +#define RETURN_STRICTLY_GREATER_IF_DIFFERENT(component) \ + { \ + auto valueA = timeA->CHIP_CRYPTO_PAL_PRIVATE_X509(component); \ + auto valueB = timeB->CHIP_CRYPTO_PAL_PRIVATE_X509(component); \ + \ + if (valueA != valueB) \ + { \ + return valueA > valueB; \ + } \ + } + + RETURN_STRICTLY_GREATER_IF_DIFFERENT(year); + RETURN_STRICTLY_GREATER_IF_DIFFERENT(mon); + RETURN_STRICTLY_GREATER_IF_DIFFERENT(day); + RETURN_STRICTLY_GREATER_IF_DIFFERENT(hour); + RETURN_STRICTLY_GREATER_IF_DIFFERENT(min); + RETURN_STRICTLY_GREATER_IF_DIFFERENT(sec); + + // all above are equal + return true; +} + +CHIP_ERROR IsCertificateValidAtIssuance(const mbedtls_x509_crt * candidateCertificate, const mbedtls_x509_crt * issuerCertificate) +{ + mbedtls_x509_time candidateNotBeforeTime = candidateCertificate->CHIP_CRYPTO_PAL_PRIVATE_X509(valid_from); + mbedtls_x509_time issuerNotBeforeTime = issuerCertificate->CHIP_CRYPTO_PAL_PRIVATE_X509(valid_from); + mbedtls_x509_time issuerNotAfterTime = issuerCertificate->CHIP_CRYPTO_PAL_PRIVATE_X509(valid_to); + + // check if candidateCertificate is issued at or after issuerCertificate's notBefore timestamp + VerifyOrReturnError(IsTimeGreaterThanEqual(&candidateNotBeforeTime, &issuerNotBeforeTime), CHIP_ERROR_CERT_EXPIRED); + + // check if candidateCertificate is issued at or before issuerCertificate's notAfter timestamp + VerifyOrReturnError(IsTimeGreaterThanEqual(&issuerNotAfterTime, &candidateNotBeforeTime), CHIP_ERROR_CERT_EXPIRED); + + return CHIP_NO_ERROR; +} + +int CallbackForCustomValidityCheck(void * data, mbedtls_x509_crt * crt, int depth, uint32_t * flags) +{ + mbedtls_x509_crt * leafCert = reinterpret_cast(data); + mbedtls_x509_crt * issuerCert = crt; + + // Ignore any time validy error performed by the standard mbedTLS code. + *flags &= ~(static_cast(MBEDTLS_X509_BADCERT_EXPIRED | MBEDTLS_X509_BADCERT_FUTURE)); + + // Verify that the leaf certificate has a notBefore time valid within the validity period of the issuerCertificate. + // Note that this callback is invoked for each certificate in the chain. + if (IsCertificateValidAtIssuance(leafCert, issuerCert) != CHIP_NO_ERROR) + { + return MBEDTLS_ERR_X509_INVALID_DATE; + } + + return 0; +} + +constexpr uint8_t sOID_AttributeType_CommonName[] = { 0x55, 0x04, 0x03 }; +constexpr uint8_t sOID_AttributeType_MatterVendorId[] = { 0x2B, 0x06, 0x01, 0x04, 0x01, 0x82, 0xA2, 0x7C, 0x02, 0x01 }; +constexpr uint8_t sOID_AttributeType_MatterProductId[] = { 0x2B, 0x06, 0x01, 0x04, 0x01, 0x82, 0xA2, 0x7C, 0x02, 0x02 }; +constexpr uint8_t sOID_SigAlgo_ECDSAWithSHA256[] = { 0x2A, 0x86, 0x48, 0xCE, 0x3D, 0x04, 0x03, 0x02 }; +constexpr uint8_t sOID_Extension_BasicConstraints[] = { 0x55, 0x1D, 0x13 }; +constexpr uint8_t sOID_Extension_KeyUsage[] = { 0x55, 0x1D, 0x0F }; +constexpr uint8_t sOID_Extension_SubjectKeyIdentifier[] = { 0x55, 0x1D, 0x0E }; +constexpr uint8_t sOID_Extension_AuthorityKeyIdentifier[] = { 0x55, 0x1D, 0x23 }; + +/** + * Compares an mbedtls_asn1_buf structure (oidBuf) to a reference OID represented as uint8_t array (oid). + */ +#define OID_CMP(oid, oidBuf) \ + ((MBEDTLS_ASN1_OID == (oidBuf).CHIP_CRYPTO_PAL_PRIVATE_X509(tag)) && \ + (sizeof(oid) == (oidBuf).CHIP_CRYPTO_PAL_PRIVATE_X509(len)) && \ + (memcmp((oid), (oidBuf).CHIP_CRYPTO_PAL_PRIVATE_X509(p), (oidBuf).CHIP_CRYPTO_PAL_PRIVATE_X509(len)) == 0)) + +#endif // defined(MBEDTLS_X509_CRT_PARSE_C) + +} // anonymous namespace + +CHIP_ERROR VerifyAttestationCertificateFormat(const ByteSpan & cert, AttestationCertType certType) +{ +#if defined(MBEDTLS_X509_CRT_PARSE_C) + CHIP_ERROR error = CHIP_NO_ERROR; + int result = 0; + mbedtls_x509_crt mbed_cert; + unsigned char * p = nullptr; + const unsigned char * end = nullptr; + size_t len = 0; + bool extBasicPresent = false; + bool extKeyUsagePresent = false; + + VerifyOrReturnError(!cert.empty(), CHIP_ERROR_INVALID_ARGUMENT); + + mbedtls_x509_crt_init(&mbed_cert); + + result = mbedtls_x509_crt_parse(&mbed_cert, Uint8::to_const_uchar(cert.data()), cert.size()); + VerifyOrExit(result == 0, error = CHIP_ERROR_INTERNAL); + + // "version" value is 1 higher than the actual encoded value. + VerifyOrExit(mbed_cert.CHIP_CRYPTO_PAL_PRIVATE_X509(version) - 1 == 2, error = CHIP_ERROR_INTERNAL); + + // Verify signature algorithms is ECDSA with SHA256. + VerifyOrExit(OID_CMP(sOID_SigAlgo_ECDSAWithSHA256, mbed_cert.CHIP_CRYPTO_PAL_PRIVATE_X509(sig_oid)), + error = CHIP_ERROR_INTERNAL); + + // Verify public key presence and format. + { + Crypto::P256PublicKey pubkey; + SuccessOrExit(error = ExtractPubkeyFromX509Cert(cert, pubkey)); + } + + p = mbed_cert.CHIP_CRYPTO_PAL_PRIVATE_X509(v3_ext).CHIP_CRYPTO_PAL_PRIVATE_X509(p); + end = p + mbed_cert.CHIP_CRYPTO_PAL_PRIVATE_X509(v3_ext).CHIP_CRYPTO_PAL_PRIVATE_X509(len); + result = mbedtls_asn1_get_tag(&p, end, &len, MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE); + VerifyOrExit(result == 0, error = CHIP_ERROR_INTERNAL); + + while (p < end) + { + mbedtls_x509_buf extOID = { 0, 0, nullptr }; + int extCritical = 0; + + result = mbedtls_asn1_get_tag(&p, end, &len, MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE); + VerifyOrExit(result == 0, error = CHIP_ERROR_INTERNAL); + + /* Get extension ID */ + result = mbedtls_asn1_get_tag(&p, end, &len, MBEDTLS_ASN1_OID); + VerifyOrExit(result == 0, error = CHIP_ERROR_INTERNAL); + + extOID.CHIP_CRYPTO_PAL_PRIVATE_X509(tag) = MBEDTLS_ASN1_OID; + extOID.CHIP_CRYPTO_PAL_PRIVATE_X509(len) = len; + extOID.CHIP_CRYPTO_PAL_PRIVATE_X509(p) = p; + p += len; + + /* Get optional critical */ + result = mbedtls_asn1_get_bool(&p, end, &extCritical); + VerifyOrExit(result == 0 || result == MBEDTLS_ERR_ASN1_UNEXPECTED_TAG, error = CHIP_ERROR_INTERNAL); + + /* Data should be octet string type */ + result = mbedtls_asn1_get_tag(&p, end, &len, MBEDTLS_ASN1_OCTET_STRING); + VerifyOrExit(result == 0, error = CHIP_ERROR_INTERNAL); + + if (OID_CMP(sOID_Extension_BasicConstraints, extOID)) + { + int isCA = 0; + int pathLen = -1; + unsigned char * seqStart = p; + + VerifyOrExit(extCritical, error = CHIP_ERROR_INTERNAL); + extBasicPresent = true; + + result = mbedtls_asn1_get_tag(&p, end, &len, MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE); + VerifyOrExit(result == 0, error = CHIP_ERROR_INTERNAL); + if (len > 0) + { + result = mbedtls_asn1_get_bool(&p, end, &isCA); + VerifyOrExit(result == 0 || result == MBEDTLS_ERR_ASN1_UNEXPECTED_TAG, error = CHIP_ERROR_INTERNAL); + + if (p != seqStart + len) + { + result = mbedtls_asn1_get_int(&p, end, &pathLen); + VerifyOrExit(result == 0, error = CHIP_ERROR_INTERNAL); + } + } + + if (certType == AttestationCertType::kDAC) + { + VerifyOrExit(!isCA && pathLen == -1, error = CHIP_ERROR_INTERNAL); + } + else if (certType == AttestationCertType::kPAI) + { + VerifyOrExit(isCA && pathLen == 0, error = CHIP_ERROR_INTERNAL); + } + else + { + VerifyOrExit(isCA && (pathLen == -1 || pathLen == 0 || pathLen == 1), error = CHIP_ERROR_INTERNAL); + } + } + else if (OID_CMP(sOID_Extension_KeyUsage, extOID)) + { + mbedtls_x509_bitstring bs = { 0, 0, nullptr }; + unsigned int keyUsage = 0; + + VerifyOrExit(extCritical, error = CHIP_ERROR_INTERNAL); + extKeyUsagePresent = true; + + result = mbedtls_asn1_get_bitstring(&p, p + len, &bs); + VerifyOrExit(result == 0, error = CHIP_ERROR_INTERNAL); + + for (size_t i = 0; i < bs.CHIP_CRYPTO_PAL_PRIVATE_X509(len) && i < sizeof(unsigned int); i++) + { + keyUsage |= static_cast(bs.CHIP_CRYPTO_PAL_PRIVATE_X509(p)[i]) << (8 * i); + } + + if (certType == AttestationCertType::kDAC) + { + // SHALL only have the digitalSignature bit set. + VerifyOrExit(keyUsage == MBEDTLS_X509_KU_DIGITAL_SIGNATURE, error = CHIP_ERROR_INTERNAL); + } + else + { + bool keyCertSignFlag = keyUsage & MBEDTLS_X509_KU_KEY_CERT_SIGN; + bool crlSignFlag = keyUsage & MBEDTLS_X509_KU_CRL_SIGN; + bool otherFlags = + keyUsage & ~(MBEDTLS_X509_KU_CRL_SIGN | MBEDTLS_X509_KU_KEY_CERT_SIGN | MBEDTLS_X509_KU_DIGITAL_SIGNATURE); + VerifyOrExit(keyCertSignFlag && crlSignFlag && !otherFlags, error = CHIP_ERROR_INTERNAL); + } + } + else + { + p += len; + } + } + + // Verify basic and key usage extensions are present. + VerifyOrExit(extBasicPresent && extKeyUsagePresent, error = CHIP_ERROR_INTERNAL); + + // Verify that SKID and AKID extensions are present. + { + uint8_t kidBuf[kSubjectKeyIdentifierLength]; + MutableByteSpan kid(kidBuf); + SuccessOrExit(error = ExtractSKIDFromX509Cert(cert, kid)); + if (certType == AttestationCertType::kDAC || certType == AttestationCertType::kPAI) + { + // Mandatory extension for DAC and PAI certs. + SuccessOrExit(error = ExtractAKIDFromX509Cert(cert, kid)); + } + } + +exit: + _log_mbedTLS_error(result); + mbedtls_x509_crt_free(&mbed_cert); + +#else + (void) cert; + (void) certType; + CHIP_ERROR error = CHIP_ERROR_NOT_IMPLEMENTED; +#endif // defined(MBEDTLS_X509_CRT_PARSE_C) + + return error; +} + +CHIP_ERROR ValidateCertificateChain(const uint8_t * rootCertificate, size_t rootCertificateLen, const uint8_t * caCertificate, + size_t caCertificateLen, const uint8_t * leafCertificate, size_t leafCertificateLen, + CertificateChainValidationResult & result) +{ +#if defined(MBEDTLS_X509_CRT_PARSE_C) + CHIP_ERROR error = CHIP_NO_ERROR; + mbedtls_x509_crt certChain; + mbedtls_x509_crt rootCert; + int mbedResult; + uint32_t flags = 0; + + result = CertificateChainValidationResult::kInternalFrameworkError; + + VerifyOrReturnError(rootCertificate != nullptr && rootCertificateLen != 0, + (result = CertificateChainValidationResult::kRootArgumentInvalid, CHIP_ERROR_INVALID_ARGUMENT)); + VerifyOrReturnError(leafCertificate != nullptr && leafCertificateLen != 0, + (result = CertificateChainValidationResult::kLeafArgumentInvalid, CHIP_ERROR_INVALID_ARGUMENT)); + + mbedtls_x509_crt_init(&certChain); + mbedtls_x509_crt_init(&rootCert); + + /* Start of chain */ + mbedResult = mbedtls_x509_crt_parse(&certChain, Uint8::to_const_uchar(leafCertificate), leafCertificateLen); + VerifyOrExit(mbedResult == 0, (result = CertificateChainValidationResult::kLeafFormatInvalid, error = CHIP_ERROR_INTERNAL)); + + /* Add the intermediate to the chain, if present */ + if (caCertificate != nullptr && caCertificateLen > 0) + { + mbedResult = mbedtls_x509_crt_parse(&certChain, Uint8::to_const_uchar(caCertificate), caCertificateLen); + VerifyOrExit(mbedResult == 0, (result = CertificateChainValidationResult::kICAFormatInvalid, error = CHIP_ERROR_INTERNAL)); + } + + /* Parse the root cert */ + mbedResult = mbedtls_x509_crt_parse(&rootCert, Uint8::to_const_uchar(rootCertificate), rootCertificateLen); + VerifyOrExit(mbedResult == 0, (result = CertificateChainValidationResult::kRootFormatInvalid, error = CHIP_ERROR_INTERNAL)); + + /* Verify the chain against the root */ + mbedResult = + mbedtls_x509_crt_verify(&certChain, &rootCert, nullptr, nullptr, &flags, CallbackForCustomValidityCheck, &certChain); + + switch (mbedResult) + { + case 0: + VerifyOrExit(flags == 0, (result = CertificateChainValidationResult::kInternalFrameworkError, error = CHIP_ERROR_INTERNAL)); + result = CertificateChainValidationResult::kSuccess; + break; + case MBEDTLS_ERR_X509_INVALID_DATE: + case MBEDTLS_ERR_X509_CERT_VERIFY_FAILED: + result = CertificateChainValidationResult::kChainInvalid; + error = CHIP_ERROR_CERT_NOT_TRUSTED; + break; + default: + result = CertificateChainValidationResult::kInternalFrameworkError; + error = CHIP_ERROR_INTERNAL; + break; + } + +exit: + _log_mbedTLS_error(mbedResult); + mbedtls_x509_crt_free(&certChain); + mbedtls_x509_crt_free(&rootCert); + +#else + (void) rootCertificate; + (void) rootCertificateLen; + (void) caCertificate; + (void) caCertificateLen; + (void) leafCertificate; + (void) leafCertificateLen; + (void) result; + CHIP_ERROR error = CHIP_ERROR_NOT_IMPLEMENTED; +#endif // defined(MBEDTLS_X509_CRT_PARSE_C) + + return error; +} + +CHIP_ERROR IsCertificateValidAtIssuance(const ByteSpan & candidateCertificate, const ByteSpan & issuerCertificate) +{ +#if defined(MBEDTLS_X509_CRT_PARSE_C) + CHIP_ERROR error = CHIP_NO_ERROR; + mbedtls_x509_crt mbedCandidateCertificate; + mbedtls_x509_crt mbedIssuerCertificate; + int result; + + VerifyOrReturnError(!candidateCertificate.empty() && !issuerCertificate.empty(), CHIP_ERROR_INVALID_ARGUMENT); + + mbedtls_x509_crt_init(&mbedCandidateCertificate); + mbedtls_x509_crt_init(&mbedIssuerCertificate); + + result = mbedtls_x509_crt_parse(&mbedCandidateCertificate, Uint8::to_const_uchar(candidateCertificate.data()), + candidateCertificate.size()); + VerifyOrExit(result == 0, error = CHIP_ERROR_INTERNAL); + + result = + mbedtls_x509_crt_parse(&mbedIssuerCertificate, Uint8::to_const_uchar(issuerCertificate.data()), issuerCertificate.size()); + VerifyOrExit(result == 0, error = CHIP_ERROR_INTERNAL); + + // Verify that the candidateCertificate has a notBefore time valid within the validity period of the issuerCertificate. + SuccessOrExit(error = IsCertificateValidAtIssuance(&mbedCandidateCertificate, &mbedIssuerCertificate)); + +exit: + _log_mbedTLS_error(result); + mbedtls_x509_crt_free(&mbedCandidateCertificate); + mbedtls_x509_crt_free(&mbedIssuerCertificate); + +#else + (void) candidateCertificate; + (void) issuerCertificate; + CHIP_ERROR error = CHIP_ERROR_NOT_IMPLEMENTED; +#endif // defined(MBEDTLS_X509_CRT_PARSE_C) + + return error; +} + +CHIP_ERROR IsCertificateValidAtCurrentTime(const ByteSpan & certificate) +{ +#if defined(MBEDTLS_X509_CRT_PARSE_C) + CHIP_ERROR error = CHIP_NO_ERROR; + mbedtls_x509_crt mbedCertificate; + int result; + + VerifyOrReturnError(!certificate.empty(), CHIP_ERROR_INVALID_ARGUMENT); + + mbedtls_x509_crt_init(&mbedCertificate); + + result = mbedtls_x509_crt_parse(&mbedCertificate, Uint8::to_const_uchar(certificate.data()), certificate.size()); + VerifyOrExit(result == 0, error = CHIP_ERROR_INTERNAL); + + // check if certificate's notBefore timestamp is earlier than or equal to current time. + result = mbedtls_x509_time_is_past(&mbedCertificate.CHIP_CRYPTO_PAL_PRIVATE_X509(valid_from)); + VerifyOrExit(result == 1, error = CHIP_ERROR_CERT_EXPIRED); + + // check if certificate's notAfter timestamp is later than current time. + result = mbedtls_x509_time_is_future(&mbedCertificate.CHIP_CRYPTO_PAL_PRIVATE_X509(valid_to)); + VerifyOrExit(result == 1, error = CHIP_ERROR_CERT_EXPIRED); + +exit: + _log_mbedTLS_error(result); + mbedtls_x509_crt_free(&mbedCertificate); + +#else + (void) certificate; + CHIP_ERROR error = CHIP_ERROR_NOT_IMPLEMENTED; +#endif // defined(MBEDTLS_X509_CRT_PARSE_C) + + return error; +} + +CHIP_ERROR ExtractPubkeyFromX509Cert(const ByteSpan & certificate, Crypto::P256PublicKey & pubkey) +{ +#if defined(MBEDTLS_X509_CRT_PARSE_C) + CHIP_ERROR error = CHIP_NO_ERROR; + mbedtls_x509_crt mbed_cert; + mbedtls_ecp_keypair * keypair = nullptr; + size_t pubkey_size = 0; + + mbedtls_x509_crt_init(&mbed_cert); + + int result = mbedtls_x509_crt_parse(&mbed_cert, Uint8::to_const_uchar(certificate.data()), certificate.size()); + VerifyOrExit(result == 0, error = CHIP_ERROR_INTERNAL); + + VerifyOrExit(mbedtls_pk_get_type(&(mbed_cert.CHIP_CRYPTO_PAL_PRIVATE_X509(pk))) == MBEDTLS_PK_ECKEY, + error = CHIP_ERROR_INVALID_ARGUMENT); + + keypair = mbedtls_pk_ec(mbed_cert.CHIP_CRYPTO_PAL_PRIVATE_X509(pk)); + VerifyOrExit(keypair->CHIP_CRYPTO_PAL_PRIVATE(grp).id == MapECPGroupId(pubkey.Type()), error = CHIP_ERROR_INVALID_ARGUMENT); + // Copy the public key from the cert in raw point format + result = + mbedtls_ecp_point_write_binary(&keypair->CHIP_CRYPTO_PAL_PRIVATE(grp), &keypair->CHIP_CRYPTO_PAL_PRIVATE(Q), + MBEDTLS_ECP_PF_UNCOMPRESSED, &pubkey_size, Uint8::to_uchar(pubkey.Bytes()), pubkey.Length()); + + VerifyOrExit(result == 0, error = CHIP_ERROR_INTERNAL); + VerifyOrExit(pubkey_size == pubkey.Length(), error = CHIP_ERROR_INTERNAL); + +exit: + _log_mbedTLS_error(result); + mbedtls_x509_crt_free(&mbed_cert); + +#else + (void) certificate; + (void) pubkey; + CHIP_ERROR error = CHIP_ERROR_NOT_IMPLEMENTED; +#endif // defined(MBEDTLS_X509_CRT_PARSE_C) + + return error; +} + +namespace { + +CHIP_ERROR ExtractKIDFromX509Cert(bool extractSKID, const ByteSpan & certificate, MutableByteSpan & kid) +{ +#if defined(MBEDTLS_X509_CRT_PARSE_C) + CHIP_ERROR error = CHIP_ERROR_NOT_FOUND; + mbedtls_x509_crt mbed_cert; + unsigned char * p = nullptr; + const unsigned char * end = nullptr; + size_t len = 0; + + mbedtls_x509_crt_init(&mbed_cert); + + int result = mbedtls_x509_crt_parse(&mbed_cert, Uint8::to_const_uchar(certificate.data()), certificate.size()); + VerifyOrExit(result == 0, error = CHIP_ERROR_INTERNAL); + + // TODO: The mbedTLS team is working on supporting SKID and AKID extensions processing. + // Once it is supported, this code should be updated. + + p = mbed_cert.CHIP_CRYPTO_PAL_PRIVATE_X509(v3_ext).CHIP_CRYPTO_PAL_PRIVATE_X509(p); + end = mbed_cert.CHIP_CRYPTO_PAL_PRIVATE_X509(v3_ext).CHIP_CRYPTO_PAL_PRIVATE_X509(p) + + mbed_cert.CHIP_CRYPTO_PAL_PRIVATE_X509(v3_ext).CHIP_CRYPTO_PAL_PRIVATE_X509(len); + result = mbedtls_asn1_get_tag(&p, end, &len, MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE); + VerifyOrExit(result == 0, error = CHIP_ERROR_WRONG_CERT_TYPE); + + while (p < end) + { + result = mbedtls_asn1_get_tag(&p, end, &len, MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE); + VerifyOrExit(result == 0, error = CHIP_ERROR_WRONG_CERT_TYPE); + result = mbedtls_asn1_get_tag(&p, end, &len, MBEDTLS_ASN1_OID); + VerifyOrExit(result == 0, error = CHIP_ERROR_WRONG_CERT_TYPE); + + mbedtls_x509_buf extOID = { MBEDTLS_ASN1_OID, len, p }; + bool extractCurrentExtSKID = extractSKID && OID_CMP(sOID_Extension_SubjectKeyIdentifier, extOID); + bool extractCurrentExtAKID = !extractSKID && OID_CMP(sOID_Extension_AuthorityKeyIdentifier, extOID); + p += len; + + int is_critical = 0; + result = mbedtls_asn1_get_bool(&p, end, &is_critical); + VerifyOrExit(result == 0 || result == MBEDTLS_ERR_ASN1_UNEXPECTED_TAG, error = CHIP_ERROR_WRONG_CERT_TYPE); + + result = mbedtls_asn1_get_tag(&p, end, &len, MBEDTLS_ASN1_OCTET_STRING); + VerifyOrExit(result == 0, error = CHIP_ERROR_WRONG_CERT_TYPE); + + if (extractCurrentExtSKID || extractCurrentExtAKID) + { + if (extractCurrentExtSKID) + { + result = mbedtls_asn1_get_tag(&p, end, &len, MBEDTLS_ASN1_OCTET_STRING); + VerifyOrExit(result == 0, error = CHIP_ERROR_WRONG_CERT_TYPE); + } + else + { + result = mbedtls_asn1_get_tag(&p, end, &len, MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE); + VerifyOrExit(result == 0, error = CHIP_ERROR_WRONG_CERT_TYPE); + result = mbedtls_asn1_get_tag(&p, end, &len, MBEDTLS_ASN1_CONTEXT_SPECIFIC); + VerifyOrExit(result == 0, error = CHIP_ERROR_WRONG_CERT_TYPE); + // Other optional fields, authorityCertIssuer and authorityCertSerialNumber, + // will be skipped if present. + } + VerifyOrExit(len == kSubjectKeyIdentifierLength, error = CHIP_ERROR_WRONG_CERT_TYPE); + VerifyOrExit(len <= kid.size(), error = CHIP_ERROR_BUFFER_TOO_SMALL); + memcpy(kid.data(), p, len); + if (kid.size() > len) + { + kid.reduce_size(len); + } + ExitNow(error = CHIP_NO_ERROR); + break; + } + p += len; + } + +exit: + _log_mbedTLS_error(result); + mbedtls_x509_crt_free(&mbed_cert); + +#else + (void) certificate; + (void) kid; + CHIP_ERROR error = CHIP_ERROR_NOT_IMPLEMENTED; +#endif // defined(MBEDTLS_X509_CRT_PARSE_C) + + return error; +} + +} // namespace + +CHIP_ERROR ExtractSKIDFromX509Cert(const ByteSpan & certificate, MutableByteSpan & skid) +{ + return ExtractKIDFromX509Cert(true, certificate, skid); +} + +CHIP_ERROR ExtractAKIDFromX509Cert(const ByteSpan & certificate, MutableByteSpan & akid) +{ + return ExtractKIDFromX509Cert(false, certificate, akid); +} + +CHIP_ERROR ExtractVIDPIDFromX509Cert(const ByteSpan & certificate, AttestationCertVidPid & vidpid) +{ +#if defined(MBEDTLS_X509_CRT_PARSE_C) + CHIP_ERROR error = CHIP_NO_ERROR; + mbedtls_x509_crt mbed_cert; + mbedtls_asn1_named_data * dnIterator = nullptr; + AttestationCertVidPid vidpidFromCN; + + mbedtls_x509_crt_init(&mbed_cert); + + int result = mbedtls_x509_crt_parse(&mbed_cert, Uint8::to_const_uchar(certificate.data()), certificate.size()); + VerifyOrExit(result == 0, error = CHIP_ERROR_INTERNAL); + + for (dnIterator = &mbed_cert.CHIP_CRYPTO_PAL_PRIVATE_X509(subject); dnIterator != nullptr; + dnIterator = dnIterator->CHIP_CRYPTO_PAL_PRIVATE_X509(next)) + { + DNAttrType attrType = DNAttrType::kUnspecified; + if (OID_CMP(sOID_AttributeType_CommonName, dnIterator->CHIP_CRYPTO_PAL_PRIVATE_X509(oid))) + { + attrType = DNAttrType::kCommonName; + } + else if (OID_CMP(sOID_AttributeType_MatterVendorId, dnIterator->CHIP_CRYPTO_PAL_PRIVATE_X509(oid))) + { + attrType = DNAttrType::kMatterVID; + } + else if (OID_CMP(sOID_AttributeType_MatterProductId, dnIterator->CHIP_CRYPTO_PAL_PRIVATE_X509(oid))) + { + attrType = DNAttrType::kMatterPID; + } + + size_t val_len = dnIterator->CHIP_CRYPTO_PAL_PRIVATE_X509(val).CHIP_CRYPTO_PAL_PRIVATE_X509(len); + uint8_t * val_p = dnIterator->CHIP_CRYPTO_PAL_PRIVATE_X509(val).CHIP_CRYPTO_PAL_PRIVATE_X509(p); + error = ExtractVIDPIDFromAttributeString(attrType, ByteSpan(val_p, val_len), vidpid, vidpidFromCN); + SuccessOrExit(error); + } + + // If Matter Attributes were not found use values extracted from the CN Attribute, + // which might be uninitialized as well. + if (!vidpid.Initialized()) + { + vidpid = vidpidFromCN; + } + +exit: + _log_mbedTLS_error(result); + mbedtls_x509_crt_free(&mbed_cert); + +#else + (void) certificate; + (void) vidpid; + CHIP_ERROR error = CHIP_ERROR_NOT_IMPLEMENTED; +#endif // defined(MBEDTLS_X509_CRT_PARSE_C) + + return error; +} + +} // namespace Crypto +} // namespace chip diff --git a/src/platform/nxp/crypto/se05x/CHIPCryptoPALHsm_se05x_config.h b/src/platform/nxp/crypto/se05x/CHIPCryptoPALHsm_se05x_config.h new file mode 100644 index 00000000000000..61db3cc26216dd --- /dev/null +++ b/src/platform/nxp/crypto/se05x/CHIPCryptoPALHsm_se05x_config.h @@ -0,0 +1,73 @@ +/* + * + * Copyright (c) 2020 Project CHIP Authors + * + * 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. + */ + +/** + * @file + * Header that exposes the options to enable SE05x for required crypto operations. + */ + +#pragma once + +/* + * Enable se05x for SPAKE VERIFIER + */ +#define ENABLE_SE05X_SPAKE_VERIFIER 0 + +/* + * Enable se05x for SPAKE PROVER + */ +#define ENABLE_SE05X_SPAKE_PROVER 0 + +/* + * Enable se05x for random number generation + */ +#define ENABLE_SE05X_RND_GEN 1 + +/* + * Enable se05x for Generate EC Key + */ +#define ENABLE_SE05X_GENERATE_EC_KEY 1 + +/* + * Enable ECDSA Verify using se05x + */ +#define ENABLE_SE05X_ECDSA_VERIFY 1 + +/* + * Enable Key Import for se05x + */ +#define ENABLE_SE05X_KEY_IMPORT 0 + +/* + * Enable se05x for PBKDF SHA256 + */ +#define ENABLE_SE05X_PBKDF2_SHA256 0 + +/* + * Enable se05x for HKDF SHA256 + */ +#define ENABLE_SE05X_HKDF_SHA256 1 + +/* + * Enable se05x for HMAC SHA256 + */ +#define ENABLE_SE05X_HMAC_SHA256 1 + +/* + * Enable se05x for DA + */ +#define ENABLE_SE05X_DEVICE_ATTESTATION 0 diff --git a/src/crypto/hsm/nxp/CHIPCryptoPALHsm_SE05X_HKDF.cpp b/src/platform/nxp/crypto/se05x/CHIPCryptoPALHsm_se05x_hkdf.cpp similarity index 67% rename from src/crypto/hsm/nxp/CHIPCryptoPALHsm_SE05X_HKDF.cpp rename to src/platform/nxp/crypto/se05x/CHIPCryptoPALHsm_se05x_hkdf.cpp index 604ccac84f4e5a..4a3c06d4828272 100644 --- a/src/crypto/hsm/nxp/CHIPCryptoPALHsm_SE05X_HKDF.cpp +++ b/src/platform/nxp/crypto/se05x/CHIPCryptoPALHsm_se05x_hkdf.cpp @@ -22,31 +22,33 @@ * chip crypto apis use either HSM or rollback to software implementation. */ -#include "CHIPCryptoPALHsm_SE05X_utils.h" +#include "CHIPCryptoPALHsm_se05x_utils.h" #include -#if ENABLE_HSM_HKDF_SHA256 - namespace chip { namespace Crypto { -HKDF_shaHSM::HKDF_shaHSM() -{ - keyid = kKeyId_hkdf_sha256_hmac_keyid; -} -HKDF_shaHSM::~HKDF_shaHSM() {} +extern CHIP_ERROR HKDF_SHA256_H(const uint8_t * secret, const size_t secret_length, const uint8_t * salt, const size_t salt_length, + const uint8_t * info, const size_t info_length, uint8_t * out_buffer, size_t out_length); -CHIP_ERROR HKDF_shaHSM::HKDF_SHA256(const uint8_t * secret, const size_t secret_length, const uint8_t * salt, - const size_t salt_length, const uint8_t * info, const size_t info_length, uint8_t * out_buffer, - size_t out_length) +CHIP_ERROR HKDF_sha::HKDF_SHA256(const uint8_t * secret, const size_t secret_length, const uint8_t * salt, const size_t salt_length, + const uint8_t * info, const size_t info_length, uint8_t * out_buffer, size_t out_length) { - CHIP_ERROR error = CHIP_ERROR_INTERNAL; +#if !ENABLE_SE05X_HKDF_SHA256 + return HKDF_SHA256_H(secret, secret_length, salt, salt_length, info, info_length, out_buffer, out_length); +#else + CHIP_ERROR error = CHIP_ERROR_INTERNAL; + uint32_t keyid = kKeyId_hkdf_sha256_hmac_keyid; + sss_object_t keyObject = { 0 }; + if (salt_length > 64 || info_length > 80 || secret_length > 256 || out_length > 768) { /* Length not supported by se05x. Rollback to SW */ - return HKDF_sha::HKDF_SHA256(secret, secret_length, salt, salt_length, info, info_length, out_buffer, out_length); + return HKDF_SHA256_H(secret, secret_length, salt, salt_length, info, info_length, out_buffer, out_length); } + ChipLogDetail(Crypto, "HKDF_SHA256 : Using se05x for HKDF"); + // Salt is optional if (salt_length > 0) { @@ -58,13 +60,10 @@ CHIP_ERROR HKDF_shaHSM::HKDF_SHA256(const uint8_t * secret, const size_t secret_ VerifyOrReturnError(out_buffer != nullptr, CHIP_ERROR_INVALID_ARGUMENT); VerifyOrReturnError(secret != nullptr, CHIP_ERROR_INVALID_ARGUMENT); - VerifyOrReturnError(keyid != kKeyId_NotInitialized, CHIP_ERROR_HSM); - - se05x_sessionOpen(); + VerifyOrReturnError(se05x_sessionOpen() == CHIP_NO_ERROR, CHIP_ERROR_INTERNAL); VerifyOrReturnError(gex_sss_chip_ctx.ks.session != NULL, CHIP_ERROR_INTERNAL); - sss_object_t keyObject = { 0 }; - sss_status_t status = sss_key_object_init(&keyObject, &gex_sss_chip_ctx.ks); + sss_status_t status = sss_key_object_init(&keyObject, &gex_sss_chip_ctx.ks); VerifyOrReturnError(status == kStatus_SSS_Success, CHIP_ERROR_INTERNAL); status = sss_key_object_allocate_handle(&keyObject, keyid, kSSS_KeyPart_Default, kSSS_CipherType_HMAC, secret_length, @@ -81,12 +80,15 @@ CHIP_ERROR HKDF_shaHSM::HKDF_SHA256(const uint8_t * secret, const size_t secret_ error = CHIP_NO_ERROR; exit: - sss_key_store_erase_key(&gex_sss_chip_ctx.ks, &keyObject); + if (keyObject.keyStore->session != NULL) + { + sss_key_store_erase_key(&gex_sss_chip_ctx.ks, &keyObject); + } return error; + +#endif // ENABLE_SE05X_HKDF_SHA256 } } // namespace Crypto } // namespace chip - -#endif //#if ENABLE_HSM_HKDF_SHA256 diff --git a/src/crypto/hsm/nxp/CHIPCryptoPALHsm_SE05X_HMAC.cpp b/src/platform/nxp/crypto/se05x/CHIPCryptoPALHsm_se05x_hmac.cpp similarity index 80% rename from src/crypto/hsm/nxp/CHIPCryptoPALHsm_SE05X_HMAC.cpp rename to src/platform/nxp/crypto/se05x/CHIPCryptoPALHsm_se05x_hmac.cpp index b9d68424d59ca2..ca1fb0111e4a9a 100644 --- a/src/crypto/hsm/nxp/CHIPCryptoPALHsm_SE05X_HMAC.cpp +++ b/src/platform/nxp/crypto/se05x/CHIPCryptoPALHsm_se05x_hmac.cpp @@ -22,30 +22,31 @@ * chip crypto apis use either HSM or rollback to software implementation. */ -#include "CHIPCryptoPALHsm_SE05X_utils.h" +#include "CHIPCryptoPALHsm_se05x_utils.h" #include -#if ENABLE_HSM_HMAC_SHA256 - #define MAX_MAC_ONE_SHOT_DATA_LEN 900 namespace chip { namespace Crypto { -HMAC_shaHSM::HMAC_shaHSM() -{ - keyid = kKeyId_hmac_sha256_keyid; -} -HMAC_shaHSM::~HMAC_shaHSM() {} +extern CHIP_ERROR HMAC_SHA256_h(const uint8_t * key, size_t key_length, const uint8_t * message, size_t message_length, + uint8_t * out_buffer, size_t out_length); -CHIP_ERROR HMAC_shaHSM::HMAC_SHA256(const uint8_t * key, size_t key_length, const uint8_t * message, size_t message_length, - uint8_t * out_buffer, size_t out_length) +CHIP_ERROR HMAC_sha::HMAC_SHA256(const uint8_t * key, size_t key_length, const uint8_t * message, size_t message_length, + uint8_t * out_buffer, size_t out_length) { +#if !ENABLE_SE05X_HMAC_SHA256 + return HMAC_SHA256_h(key, key_length, message, message_length, out_buffer, out_length); +#else CHIP_ERROR error = CHIP_ERROR_INTERNAL; + uint32_t keyid = kKeyId_hmac_sha256_keyid; sss_mac_t ctx_mac = { 0 }; sss_object_t keyObject = { 0 }; + ChipLogDetail(Crypto, "HMAC_SHA256 : Using se05x for HMAC"); + VerifyOrReturnError(key != nullptr, CHIP_ERROR_INVALID_ARGUMENT); VerifyOrReturnError(key_length > 0, CHIP_ERROR_INVALID_ARGUMENT); VerifyOrReturnError(message != nullptr, CHIP_ERROR_INVALID_ARGUMENT); @@ -55,12 +56,12 @@ CHIP_ERROR HMAC_shaHSM::HMAC_SHA256(const uint8_t * key, size_t key_length, cons if (key_length > 256) { - return HMAC_sha::HMAC_SHA256(key, key_length, message, message_length, out_buffer, out_length); + return CHIP_ERROR_INTERNAL; // TODO - Add rollback } VerifyOrReturnError(keyid != kKeyId_NotInitialized, CHIP_ERROR_HSM); - se05x_sessionOpen(); + VerifyOrReturnError(se05x_sessionOpen() == CHIP_NO_ERROR, CHIP_ERROR_INTERNAL); VerifyOrReturnError(gex_sss_chip_ctx.ks.session != NULL, CHIP_ERROR_INTERNAL); sss_status_t status = sss_key_object_init(&keyObject, &gex_sss_chip_ctx.ks); @@ -110,12 +111,14 @@ CHIP_ERROR HMAC_shaHSM::HMAC_SHA256(const uint8_t * key, size_t key_length, cons sss_mac_context_free(&ctx_mac); } - sss_key_store_erase_key(&gex_sss_chip_ctx.ks, &keyObject); + if (keyObject.keyStore->session != NULL) + { + sss_key_store_erase_key(&gex_sss_chip_ctx.ks, &keyObject); + } return error; +#endif } } // namespace Crypto } // namespace chip - -#endif //#if ENABLE_HSM_HMAC_SHA256 diff --git a/src/crypto/hsm/nxp/CHIPCryptoPALHsm_SE05X_P256.cpp b/src/platform/nxp/crypto/se05x/CHIPCryptoPALHsm_se05x_p256.cpp similarity index 53% rename from src/crypto/hsm/nxp/CHIPCryptoPALHsm_SE05X_P256.cpp rename to src/platform/nxp/crypto/se05x/CHIPCryptoPALHsm_se05x_p256.cpp index a467f61fd8ea7d..a9c8cd94bdacb6 100644 --- a/src/crypto/hsm/nxp/CHIPCryptoPALHsm_SE05X_P256.cpp +++ b/src/platform/nxp/crypto/se05x/CHIPCryptoPALHsm_se05x_p256.cpp @@ -22,13 +22,12 @@ * chip crypto apis use either HSM or rollback to software implementation. */ -#include "CHIPCryptoPALHsm_SE05X_utils.h" +#include "CHIPCryptoPALHsm_se05x_utils.h" #include -#if ENABLE_HSM_GENERATE_EC_KEY - #define MAX_SHA_ONE_SHOT_DATA_LEN 900 #define NIST256_HEADER_OFFSET 26 +#define CRYPTO_KEYPAIR_KEYID_OFFSET 8 /* Used for CSR generation */ // Organisation info. @@ -47,84 +46,134 @@ const uint8_t kTlvHeader = 2; namespace chip { namespace Crypto { -P256KeypairHSM::~P256KeypairHSM() +#define EC_NIST_P256_KP_HEADER \ + { \ + 0x30, 0x81, 0x87, 0x02, 0x01, 0x00, 0x30, 0x13, 0x06, 0x07, 0x2A, 0x86, 0x48, 0xCE, 0x3D, 0x02, 0x01, 0x06, 0x08, 0x2A, \ + 0x86, 0x48, 0xCE, 0x3D, 0x03, 0x01, 0x07, 0x04, 0x6D, 0x30, 0x6B, 0x02, 0x01, 0x01, 0x04, 0x20, \ + } + +#define EC_NIST_P256_KP_PUB_HEADER \ + { \ + 0xA1, 0x44, 0x03, 0x42, 0x00, \ + } + +extern CHIP_ERROR Initialize_H(P256Keypair * pk, P256PublicKey * mPublicKey, P256KeypairContext * mKeypair); +extern CHIP_ERROR ECDSA_sign_msg_H(P256KeypairContext * mKeypair, const uint8_t * msg, const size_t msg_length, + P256ECDSASignature & out_signature); +extern CHIP_ERROR ECDH_derive_secret_H(P256KeypairContext * mKeypair, const P256PublicKey & remote_public_key, + P256ECDHDerivedSecret & out_secret); +extern CHIP_ERROR NewCertificateSigningRequest_H(P256KeypairContext * mKeypair, uint8_t * out_csr, size_t & csr_length); +extern CHIP_ERROR Deserialize_H(P256Keypair * pk, P256PublicKey * mPublicKey, P256KeypairContext * mKeypair, + P256SerializedKeypair & input); +extern CHIP_ERROR Serialize_H(const P256KeypairContext mKeypair, const P256PublicKey mPublicKey, P256SerializedKeypair & output); +extern CHIP_ERROR ECDSA_validate_msg_signature_H(const P256PublicKey * public_key, const uint8_t * msg, const size_t msg_length, + const P256ECDSASignature & signature); +extern CHIP_ERROR ECDSA_validate_hash_signature_H(const P256PublicKey * public_key, const uint8_t * hash, const size_t hash_length, + const P256ECDSASignature & signature); + +#if (ENABLE_SE05X_GENERATE_EC_KEY || ENABLE_SE05X_ECDSA_VERIFY) +static CHIP_ERROR parse_se05x_keyid_from_keypair(const P256KeypairContext mKeypair, uint32_t * key_id) { - if (keyid != kKeyId_NotInitialized) + if (0 != memcmp(&mKeypair.mBytes[0], se05x_magic_no, sizeof(se05x_magic_no))) { - if (provisioned_key == false) - { - ChipLogDetail(Crypto, "Deleting key with id - %x !", keyid); - se05x_delete_key(keyid); - } - else - { - ChipLogDetail(Crypto, "Provisioned key ! Not deleting key in HSM"); - } + return CHIP_ERROR_INTERNAL; + } + + *key_id += (mKeypair.mBytes[CRYPTO_KEYPAIR_KEYID_OFFSET] << (8 * 3) & 0xFF000000) | + (mKeypair.mBytes[CRYPTO_KEYPAIR_KEYID_OFFSET + 1] << (8 * 2) & 0x00FF0000) | + (mKeypair.mBytes[CRYPTO_KEYPAIR_KEYID_OFFSET + 2] << (8 * 1) & 0x0000FF00) | + (mKeypair.mBytes[CRYPTO_KEYPAIR_KEYID_OFFSET + 3] << (8 * 0) & 0x000000FF); + + return CHIP_NO_ERROR; +} +#endif //#if (ENABLE_SE05X_GENERATE_EC_KEY || ENABLE_SE05X_ECDSA_VERIFY) + +P256Keypair::~P256Keypair() +{ + uint32_t keyid = 0; + if (CHIP_NO_ERROR != parse_se05x_keyid_from_keypair(mKeypair, &keyid)) + { + Clear(); + } + else + { + // Delete the key in SE } } -CHIP_ERROR P256KeypairHSM::Initialize(ECPKeyTarget key_target) +CHIP_ERROR P256Keypair::Initialize(ECPKeyTarget key_target) { +#if !ENABLE_SE05X_GENERATE_EC_KEY + if (CHIP_NO_ERROR == Initialize_H(this, &mPublicKey, &mKeypair)) + { + mInitialized = true; + } + return error; +#else + sss_status_t status = kStatus_SSS_Fail; sss_object_t keyObject = { 0 }; uint8_t pubkey[128] = { 0, }; size_t pubKeyLen = sizeof(pubkey); size_t pbKeyBitLen = sizeof(pubkey) * 8; + uint32_t keyid = 0; + uint32_t options = kKeyObject_Mode_Transient; - if (keyid == 0) - { - ChipLogDetail(Crypto, "Keyid not set !. Set key id using 'SetKeyId' member class !"); - return CHIP_ERROR_INTERNAL; - } - - se05x_sessionOpen(); - - sss_status_t status = sss_key_object_init(&keyObject, &gex_sss_chip_ctx.ks); - VerifyOrReturnError(status == kStatus_SSS_Success, CHIP_ERROR_INTERNAL); + ChipLogDetail(Crypto, "se05x::Generate nist256 key using se05x"); - if (provisioned_key == false) + if (key_target == ECPKeyTarget::ECDH) { - - status = sss_key_object_allocate_handle(&keyObject, keyid, kSSS_KeyPart_Pair, kSSS_CipherType_EC_NIST_P, 256, - kKeyObject_Mode_Transient); - VerifyOrReturnError(status == kStatus_SSS_Success, CHIP_ERROR_INTERNAL); - - ChipLogDetail(Crypto, "Creating Nist256 key on SE05X !"); - - status = sss_key_store_generate_key(&gex_sss_chip_ctx.ks, &keyObject, 256, 0); - VerifyOrReturnError(status == kStatus_SSS_Success, CHIP_ERROR_INTERNAL); + keyid = kKeyId_case_ephemeral_keyid; } else { + // Add the logic to use different keyid + keyid = kKeyId_node_op_keyid_start; + options = kKeyObject_Mode_Persistent; + } - // if the key is provisioned already, only get the public key, - // and set it in public key member of this class. - ChipLogDetail(Crypto, "Provisioned key ! Not creating key in HSM"); + VerifyOrReturnError(se05x_sessionOpen() == CHIP_NO_ERROR, CHIP_ERROR_INTERNAL); - status = sss_key_object_get_handle(&keyObject, keyid); - VerifyOrReturnError(status == kStatus_SSS_Success, CHIP_ERROR_INTERNAL); - } + status = sss_key_object_init(&keyObject, &gex_sss_chip_ctx.ks); + VerifyOrReturnError(status == kStatus_SSS_Success, CHIP_ERROR_INTERNAL); + + status = sss_key_object_allocate_handle(&keyObject, keyid, kSSS_KeyPart_Pair, kSSS_CipherType_EC_NIST_P, 256, options); + VerifyOrReturnError(status == kStatus_SSS_Success, CHIP_ERROR_INTERNAL); + + status = sss_key_store_generate_key(&gex_sss_chip_ctx.ks, &keyObject, 256, 0); + VerifyOrReturnError(status == kStatus_SSS_Success, CHIP_ERROR_INTERNAL); status = sss_key_store_get_key(&gex_sss_chip_ctx.ks, &keyObject, pubkey, &pubKeyLen, &pbKeyBitLen); VerifyOrReturnError(status == kStatus_SSS_Success, CHIP_ERROR_INTERNAL); - { - /* Set the public key */ - P256PublicKeyHSM & public_key = const_cast(Pubkey()); - VerifyOrReturnError(pubKeyLen > NIST256_HEADER_OFFSET, CHIP_ERROR_INTERNAL); - VerifyOrReturnError((pubKeyLen - NIST256_HEADER_OFFSET) <= kP256_PublicKey_Length, CHIP_ERROR_INTERNAL); - memcpy((void *) Uint8::to_const_uchar(public_key), pubkey + NIST256_HEADER_OFFSET, pubKeyLen - NIST256_HEADER_OFFSET); - public_key.SetPublicKeyId(keyid); - } + /* Set the public key */ + P256PublicKey & public_key = const_cast(Pubkey()); + VerifyOrReturnError(pubKeyLen > NIST256_HEADER_OFFSET, CHIP_ERROR_INTERNAL); + VerifyOrReturnError((pubKeyLen - NIST256_HEADER_OFFSET) <= kP256_PublicKey_Length, CHIP_ERROR_INTERNAL); + memcpy((void *) Uint8::to_const_uchar(public_key), pubkey + NIST256_HEADER_OFFSET, pubKeyLen - NIST256_HEADER_OFFSET); + + memcpy(&mKeypair.mBytes[0], se05x_magic_no, sizeof(se05x_magic_no)); + mKeypair.mBytes[CRYPTO_KEYPAIR_KEYID_OFFSET] = (keyid >> (3 * 8)) & 0x000000FF; + mKeypair.mBytes[CRYPTO_KEYPAIR_KEYID_OFFSET + 1] = (keyid >> (2 * 8)) & 0x000000FF; + mKeypair.mBytes[CRYPTO_KEYPAIR_KEYID_OFFSET + 2] = (keyid >> (1 * 8)) & 0x000000FF; + mKeypair.mBytes[CRYPTO_KEYPAIR_KEYID_OFFSET + 3] = (keyid >> (0 * 8)) & 0x000000FF; + + mInitialized = true; return CHIP_NO_ERROR; +#endif // ENABLE_SE05X_GENERATE_EC_KEY } -CHIP_ERROR P256KeypairHSM::ECDSA_sign_msg(const uint8_t * msg, size_t msg_length, P256ECDSASignature & out_signature) const +CHIP_ERROR P256Keypair::ECDSA_sign_msg(const uint8_t * msg, size_t msg_length, P256ECDSASignature & out_signature) const { + VerifyOrReturnError(mInitialized, CHIP_ERROR_WELL_UNINITIALIZED); + +#if !ENABLE_SE05X_GENERATE_EC_KEY + return ECDSA_sign_msg_H(&mKeypair, msg, msg_length, out_signature); +#else CHIP_ERROR error = CHIP_ERROR_INTERNAL; - sss_digest_t digest_ctx = { 0 }; + uint32_t keyid = 0; sss_asymmetric_t asymm_ctx = { 0 }; uint8_t hash[kSHA256_Hash_Length] = { 0, @@ -136,44 +185,22 @@ CHIP_ERROR P256KeypairHSM::ECDSA_sign_msg(const uint8_t * msg, size_t msg_length size_t signature_se05x_len = sizeof(signature_se05x); MutableByteSpan out_raw_sig_span(out_signature.Bytes(), out_signature.Capacity()); - VerifyOrReturnError(msg != nullptr, CHIP_ERROR_INVALID_ARGUMENT); - VerifyOrReturnError(msg_length > 0, CHIP_ERROR_INVALID_ARGUMENT); - VerifyOrReturnError(out_signature != nullptr, CHIP_ERROR_INVALID_ARGUMENT); - VerifyOrReturnError(keyid != kKeyId_NotInitialized, CHIP_ERROR_HSM); - - ChipLogDetail(Crypto, "ECDSA_sign_msg: Using SE05X for Ecc Sign!"); - - se05x_sessionOpen(); - VerifyOrReturnError(gex_sss_chip_ctx.ks.session != NULL, CHIP_ERROR_INTERNAL); - - status = sss_digest_context_init(&digest_ctx, &gex_sss_chip_ctx.session, kAlgorithm_SSS_SHA256, kMode_SSS_Digest); - VerifyOrExit(status == kStatus_SSS_Success, error = CHIP_ERROR_INTERNAL); - - if (msg_length <= MAX_SHA_ONE_SHOT_DATA_LEN) + if (CHIP_NO_ERROR != parse_se05x_keyid_from_keypair(mKeypair, &keyid)) { - status = sss_digest_one_go(&digest_ctx, msg, msg_length, hash, &hashLen); - VerifyOrExit(status == kStatus_SSS_Success, error = CHIP_ERROR_INTERNAL); + ChipLogDetail(Crypto, "ECDSA_sign_msg : Not ref key. Using host for ecdsa sign"); + return ECDSA_sign_msg_H(&mKeypair, msg, msg_length, out_signature); } - else - { - /* Calculate SHA using multistep calls */ - size_t datalenTemp = 0; - size_t rem_len = msg_length; - status = sss_digest_init(&digest_ctx); - VerifyOrExit(status == kStatus_SSS_Success, error = CHIP_ERROR_INTERNAL); + VerifyOrReturnError(msg != nullptr, CHIP_ERROR_INVALID_ARGUMENT); + VerifyOrReturnError(msg_length > 0, CHIP_ERROR_INVALID_ARGUMENT); - while (rem_len > 0) - { - datalenTemp = (rem_len > MAX_SHA_ONE_SHOT_DATA_LEN) ? MAX_SHA_ONE_SHOT_DATA_LEN : rem_len; - status = sss_digest_update(&digest_ctx, (msg + (msg_length - rem_len)), datalenTemp); - VerifyOrExit(status == kStatus_SSS_Success, error = CHIP_ERROR_INTERNAL); - rem_len = rem_len - datalenTemp; - } + ChipLogDetail(Crypto, "ECDSA_sign_msg: Using se05x for ecdsa sign!"); - status = sss_digest_finish(&digest_ctx, hash, &hashLen); - VerifyOrExit(status == kStatus_SSS_Success, error = CHIP_ERROR_INTERNAL); - } + error = Hash_SHA256(msg, msg_length, hash); + SuccessOrExit(error); + + VerifyOrReturnError(se05x_sessionOpen() == CHIP_NO_ERROR, CHIP_ERROR_INTERNAL); + VerifyOrReturnError(gex_sss_chip_ctx.ks.session != NULL, CHIP_ERROR_INTERNAL); status = sss_key_object_init(&keyObject, &gex_sss_chip_ctx.ks); VerifyOrExit(status == kStatus_SSS_Success, error = CHIP_ERROR_INTERNAL); @@ -190,7 +217,7 @@ CHIP_ERROR P256KeypairHSM::ECDSA_sign_msg(const uint8_t * msg, size_t msg_length error = EcdsaAsn1SignatureToRaw(kP256_FE_Length, ByteSpan{ signature_se05x, signature_se05x_len }, out_raw_sig_span); SuccessOrExit(error); - SuccessOrExit(error = out_signature.SetLength(2 * kP256_FE_Length)); + out_signature.SetLength(2 * kP256_FE_Length); error = CHIP_NO_ERROR; exit: @@ -198,37 +225,28 @@ CHIP_ERROR P256KeypairHSM::ECDSA_sign_msg(const uint8_t * msg, size_t msg_length { sss_asymmetric_context_free(&asymm_ctx); } - if (digest_ctx.session != nullptr) - { - sss_digest_context_free(&digest_ctx); - } return error; +#endif // ENABLE_SE05X_GENERATE_EC_KEY } -CHIP_ERROR P256KeypairHSM::Serialize(P256SerializedKeypair & output) const +CHIP_ERROR P256Keypair::Serialize(P256SerializedKeypair & output) const { const size_t len = output.Length() == 0 ? output.Capacity() : output.Length(); Encoding::BufferWriter bbuf(output.Bytes(), len); - uint8_t privkey[kP256_PrivateKey_Length] = { - 0, - }; + if (0 != memcmp(&mKeypair.mBytes[0], se05x_magic_no, sizeof(se05x_magic_no))) { - /* Set the public key */ - P256PublicKeyHSM & public_key = const_cast(Pubkey()); - bbuf.Put(Uint8::to_uchar(public_key), public_key.Length()); + VerifyOrReturnError(mInitialized, CHIP_ERROR_WELL_UNINITIALIZED); + return Serialize_H(mKeypair, mPublicKey, output); } - VerifyOrReturnError(bbuf.Available() == sizeof(privkey), CHIP_ERROR_INTERNAL); - VerifyOrReturnError(sizeof(privkey) >= 4, CHIP_ERROR_INTERNAL); + /* Set the public key */ + P256PublicKey & public_key = const_cast(Pubkey()); + bbuf.Put(Uint8::to_uchar(public_key), public_key.Length()); - { - /* When HSM is used for ECC key generation, store key info in private key buffer */ - Encoding::LittleEndian::BufferWriter privkey_bbuf(privkey, sizeof(privkey)); - privkey_bbuf.Put32(keyid); - } + /* Set the private key se05x_magic_no */ + bbuf.Put(mKeypair.mBytes, kP256_PrivateKey_Length); - bbuf.Put(privkey, sizeof(privkey)); VerifyOrReturnError(bbuf.Fit(), CHIP_ERROR_BUFFER_TOO_SMALL); output.SetLength(bbuf.Needed()); @@ -236,48 +254,122 @@ CHIP_ERROR P256KeypairHSM::Serialize(P256SerializedKeypair & output) const return CHIP_NO_ERROR; } -CHIP_ERROR P256KeypairHSM::Deserialize(P256SerializedKeypair & input) +CHIP_ERROR P256Keypair::Deserialize(P256SerializedKeypair & input) { + CHIP_ERROR error = CHIP_ERROR_INTERNAL; + const uint8_t * privkey; /* Set the public key */ - P256PublicKeyHSM & public_key = const_cast(Pubkey()); + P256PublicKey & public_key = const_cast(Pubkey()); Encoding::BufferWriter bbuf((uint8_t *) Uint8::to_const_uchar(public_key), public_key.Length()); VerifyOrReturnError(input.Length() == public_key.Length() + kP256_PrivateKey_Length, CHIP_ERROR_INVALID_ARGUMENT); - bbuf.Put(static_cast(input), public_key.Length()); - /* Set private key info */ - VerifyOrReturnError(bbuf.Fit(), CHIP_ERROR_NO_MEMORY); + privkey = input.ConstBytes() /*Uint8::to_const_uchar(input) */ + public_key.Length(); + + if (0 == memcmp(privkey, se05x_magic_no, sizeof(se05x_magic_no))) { - /* When HSM is used for ECC key generation, key info in stored in private key buffer */ - const uint8_t * privkey = input.ConstBytes() + public_key.Length(); - keyid = Encoding::LittleEndian::Get32(privkey); - public_key.SetPublicKeyId(keyid); + /* se05x_magic_no + KeyID is passed */ + ChipLogDetail(Crypto, "Deserialize: ref key found"); + bbuf.Put(input.Bytes(), public_key.Length()); + VerifyOrReturnError(bbuf.Fit(), CHIP_ERROR_NO_MEMORY); + + memcpy(&mKeypair.mBytes[0], se05x_magic_no, sizeof(se05x_magic_no)); + mKeypair.mBytes[8] = *(privkey + 8); + mKeypair.mBytes[9] = *(privkey + 9); + mKeypair.mBytes[10] = *(privkey + 10); + mKeypair.mBytes[11] = *(privkey + 11); + // ChipLogDetail(Crypto, "Parsed keyId = 0x%02X%02X%02X%02X", mKeypair.mBytes[8], mKeypair.mBytes[9], + // mKeypair.mBytes[10],mKeypair.mBytes[11]); + + mInitialized = true; + + return CHIP_NO_ERROR; + } + else + { +#if !ENABLE_SE05X_KEY_IMPORT + if (CHIP_NO_ERROR == (error = Deserialize_H(this, &mPublicKey, &mKeypair, input))) + { + mInitialized = true; + } + return error; +#else + + sss_object_t sss_object = { 0 }; + sss_status_t sss_status = kStatus_SSS_Fail; + uint32_t keyid = 0; + uint8_t keyid_buffer[4] = { 0 }; + uint8_t key[128] = { 0 }; + uint8_t header[] = EC_NIST_P256_KP_HEADER; + uint8_t pub_header[] = EC_NIST_P256_KP_PUB_HEADER; + size_t key_length = 0; + + memcpy(&key[key_length], header, sizeof(header)); + key_length += sizeof(header); + if ((privkey[0] & 0x80)) + { + key[key_length++] = 0x00; + } + memcpy(&key[key_length], privkey, kP256_PrivateKey_Length); + key_length += kP256_PrivateKey_Length; + memcpy(&key[key_length], pub_header, sizeof(pub_header)); + key_length += sizeof(pub_header); + memcpy(&key[key_length], input.ConstBytes(), public_key.Length()); + key_length += public_key.Length(); + + error = DRBG_get_bytes(keyid_buffer, sizeof(keyid_buffer)); + VerifyOrReturnError(error == CHIP_NO_ERROR, error); + + keyid = (keyid_buffer[3] << (8 * 3)) + (keyid_buffer[2] << (8 * 2)) + (keyid_buffer[1] << (8 * 1)) + + (keyid_buffer[0] << (8 * 0)); + + sss_status = sss_key_object_init(&sss_object, &gex_sss_chip_ctx.ks); + VerifyOrReturnError(sss_status == kStatus_SSS_Success, CHIP_ERROR_INTERNAL); + sss_status = sss_key_object_allocate_handle(&sss_object, keyid, kSSS_KeyPart_Pair, kSSS_CipherType_EC_NIST_P, 256, + kKeyObject_Mode_Persistent); + VerifyOrReturnError(sss_status == kStatus_SSS_Success, CHIP_ERROR_INTERNAL); + sss_status = sss_key_store_set_key(&gex_sss_chip_ctx.ks, &sss_object, key, key_length, 256, NULL, 0); + VerifyOrReturnError(sss_status == kStatus_SSS_Success, CHIP_ERROR_INTERNAL); + + return CHIP_NO_ERROR; +#endif } - - return CHIP_NO_ERROR; } -CHIP_ERROR P256KeypairHSM::ECDH_derive_secret(const P256PublicKey & remote_public_key, P256ECDHDerivedSecret & out_secret) const +CHIP_ERROR P256Keypair::ECDH_derive_secret(const P256PublicKey & remote_public_key, P256ECDHDerivedSecret & out_secret) const { + VerifyOrReturnError(mInitialized, CHIP_ERROR_WELL_UNINITIALIZED); + +#if !ENABLE_SE05X_GENERATE_EC_KEY + return ECDH_derive_secret_H(&mKeypair, remote_public_key, out_secret); +#else size_t secret_length = (out_secret.Length() == 0) ? out_secret.Capacity() : out_secret.Length(); + uint32_t keyid = 0; - VerifyOrReturnError(keyid != kKeyId_NotInitialized, CHIP_ERROR_HSM); + if (CHIP_NO_ERROR != parse_se05x_keyid_from_keypair(mKeypair, &keyid)) + { + ChipLogDetail(Crypto, "ECDH_derive_secret : Not ref key. Using host for ecdh"); + return ECDH_derive_secret_H(&mKeypair, remote_public_key, out_secret); + } - ChipLogDetail(Crypto, "ECDH_derive_secret: Using SE05X for ECDH !"); + ChipLogDetail(Crypto, "ECDH_derive_secret : Using se05x for ecdh"); - se05x_sessionOpen(); + VerifyOrReturnError(se05x_sessionOpen() == CHIP_NO_ERROR, CHIP_ERROR_INTERNAL); VerifyOrReturnError(gex_sss_chip_ctx.ks.session != NULL, CHIP_ERROR_INTERNAL); const uint8_t * const rem_pubKey = Uint8::to_const_uchar(remote_public_key); - const size_t rem_pubKeyLen = remote_public_key.Length(); + const size_t rem_pubKeyLen = remote_public_key.Length(); VerifyOrReturnError(gex_sss_chip_ctx.ks.session != nullptr, CHIP_ERROR_INTERNAL); - const smStatus_t smstatus = Se05x_API_ECGenSharedSecret(&((sss_se05x_session_t *) &gex_sss_chip_ctx.session)->s_ctx, keyid, - rem_pubKey, rem_pubKeyLen, out_secret.Bytes(), &secret_length); + const smStatus_t smstatus = + Se05x_API_ECGenSharedSecret(&((sss_se05x_session_t *) &gex_sss_chip_ctx.session)->s_ctx, keyid, rem_pubKey, rem_pubKeyLen, + out_secret.Bytes() /*Uint8::to_uchar(out_secret)*/, &secret_length); VerifyOrReturnError(smstatus == SM_OK, CHIP_ERROR_INTERNAL); return out_secret.SetLength(secret_length); + +#endif // ENABLE_SE05X_GENERATE_EC_KEY } /* EC Public key HSM implementation */ @@ -293,8 +385,9 @@ CHIP_ERROR SE05X_Set_ECDSA_Public_Key(sss_object_t * keyObject, const uint8_t * const uint8_t nist256_header[] = { 0x30, 0x59, 0x30, 0x13, 0x06, 0x07, 0x2A, 0x86, 0x48, 0xCE, 0x3D, 0x02, 0x01, 0x06, 0x08, 0x2A, 0x86, 0x48, 0xCE, 0x3D, 0x03, 0x01, 0x07, 0x03, 0x42, 0x00 }; - se05x_sessionOpen(); + VerifyOrReturnError(se05x_sessionOpen() == CHIP_NO_ERROR, CHIP_ERROR_INTERNAL); VerifyOrReturnError(gex_sss_chip_ctx.ks.session != NULL, CHIP_ERROR_INTERNAL); + /* Set public key */ sss_status_t status = sss_key_object_init(keyObject, &gex_sss_chip_ctx.ks); VerifyOrReturnError(status == kStatus_SSS_Success, CHIP_ERROR_INTERNAL); @@ -316,74 +409,37 @@ CHIP_ERROR SE05X_Set_ECDSA_Public_Key(sss_object_t * keyObject, const uint8_t * return CHIP_NO_ERROR; } -CHIP_ERROR P256PublicKeyHSM::ECDSA_validate_msg_signature(const uint8_t * msg, size_t msg_length, - const P256ECDSASignature & signature) const +CHIP_ERROR P256PublicKey::ECDSA_validate_msg_signature(const uint8_t * msg, size_t msg_length, + const P256ECDSASignature & signature) const { - CHIP_ERROR error = CHIP_ERROR_INTERNAL; - sss_status_t status = kStatus_SSS_Success; +#if !ENABLE_SE05X_ECDSA_VERIFY + return ECDSA_validate_msg_signature_H(this, msg, msg_length, signature); +#else + CHIP_ERROR error = CHIP_ERROR_INTERNAL; + sss_status_t status = kStatus_SSS_Success; sss_asymmetric_t asymm_ctx = { 0 }; - sss_digest_t ctx_digest = { 0 }; - uint8_t hash[32] = { + uint8_t hash[32] = { 0, }; - size_t hash_length = sizeof(hash); - sss_object_t keyObject = { 0 }; + size_t hash_length = sizeof(hash); + sss_object_t keyObject = { 0 }; uint8_t signature_se05x[kMax_ECDSA_Signature_Length_Der] = { 0 }; - size_t signature_se05x_len = sizeof(signature_se05x); + size_t signature_se05x_len = sizeof(signature_se05x); MutableByteSpan out_der_sig_span(signature_se05x, signature_se05x_len); VerifyOrReturnError(msg != nullptr, CHIP_ERROR_INVALID_ARGUMENT); VerifyOrReturnError(msg_length > 0, CHIP_ERROR_INVALID_ARGUMENT); - ChipLogDetail(Crypto, "ECDSA_validate_msg_signature: Using SE05X for ECDSA verify (msg) !"); + ChipLogDetail(Crypto, "ECDSA_validate_msg_signature: Using se05x for ECDSA verify (msg) !"); - se05x_sessionOpen(); + VerifyOrReturnError(se05x_sessionOpen() == CHIP_NO_ERROR, CHIP_ERROR_INTERNAL); VerifyOrReturnError(gex_sss_chip_ctx.ks.session != NULL, CHIP_ERROR_INTERNAL); - /* Create hash of input data */ - status = sss_digest_context_init(&ctx_digest, &gex_sss_chip_ctx.session, kAlgorithm_SSS_SHA256, kMode_SSS_Digest); - VerifyOrExit(status == kStatus_SSS_Success, error = CHIP_ERROR_INTERNAL); - - if (msg_length <= MAX_SHA_ONE_SHOT_DATA_LEN) - { - status = sss_digest_one_go(&ctx_digest, msg, msg_length, hash, &hash_length); - VerifyOrExit(status == kStatus_SSS_Success, error = CHIP_ERROR_INTERNAL); - } - else - { - /* Calculate SHA using multistep calls */ - size_t datalenTemp = 0; - size_t rem_len = msg_length; - - status = sss_digest_init(&ctx_digest); - VerifyOrExit(status == kStatus_SSS_Success, error = CHIP_ERROR_INTERNAL); - - while (rem_len > 0) - { - datalenTemp = (rem_len > MAX_SHA_ONE_SHOT_DATA_LEN) ? MAX_SHA_ONE_SHOT_DATA_LEN : rem_len; - status = sss_digest_update(&ctx_digest, (msg + (msg_length - rem_len)), datalenTemp); - VerifyOrExit(status == kStatus_SSS_Success, error = CHIP_ERROR_INTERNAL); - rem_len = rem_len - datalenTemp; - } - - status = sss_digest_finish(&ctx_digest, hash, &hash_length); - VerifyOrExit(status == kStatus_SSS_Success, error = CHIP_ERROR_INTERNAL); - } - - if (PublicKeyid == kKeyId_NotInitialized) - { - error = SE05X_Set_ECDSA_Public_Key(&keyObject, bytes, kP256_PublicKey_Length); - SuccessOrExit(error); - error = CHIP_ERROR_INTERNAL; - } - else - { - status = sss_key_object_init(&keyObject, &gex_sss_chip_ctx.ks); - VerifyOrExit(status == kStatus_SSS_Success, error = CHIP_ERROR_INTERNAL); + error = Hash_SHA256(msg, msg_length, hash); + SuccessOrExit(error); - status = sss_key_object_get_handle(&keyObject, PublicKeyid); - VerifyOrExit(status == kStatus_SSS_Success, error = CHIP_ERROR_INTERNAL); - } + error = SE05X_Set_ECDSA_Public_Key(&keyObject, bytes, kP256_PublicKey_Length); + SuccessOrExit(error); /* ECC Verify */ status = @@ -406,52 +462,40 @@ CHIP_ERROR P256PublicKeyHSM::ECDSA_validate_msg_signature(const uint8_t * msg, s sss_asymmetric_context_free(&asymm_ctx); } - if (ctx_digest.session != NULL) - { - sss_digest_context_free(&ctx_digest); - } - - if (PublicKeyid == kKeyId_NotInitialized) + if (keyObject.keyStore->session != NULL) { sss_key_store_erase_key(&gex_sss_chip_ctx.ks, &keyObject); } return error; + +#endif // ENABLE_SE05X_ECDSA_VERIFY } -CHIP_ERROR P256PublicKeyHSM::ECDSA_validate_hash_signature(const uint8_t * hash, size_t hash_length, - const P256ECDSASignature & signature) const +CHIP_ERROR P256PublicKey::ECDSA_validate_hash_signature(const uint8_t * hash, size_t hash_length, + const P256ECDSASignature & signature) const { - CHIP_ERROR error = CHIP_ERROR_INTERNAL; - sss_status_t status = kStatus_SSS_Success; - sss_asymmetric_t asymm_ctx = { 0 }; - sss_object_t keyObject = { 0 }; +#if !ENABLE_SE05X_ECDSA_VERIFY + return ECDSA_validate_hash_signature_H(this, hash, hash_length, signature); +#else + CHIP_ERROR error = CHIP_ERROR_INTERNAL; + sss_status_t status = kStatus_SSS_Success; + sss_asymmetric_t asymm_ctx = { 0 }; + sss_object_t keyObject = { 0 }; uint8_t signature_se05x[kMax_ECDSA_Signature_Length_Der] = { 0 }; - size_t signature_se05x_len = sizeof(signature_se05x); + size_t signature_se05x_len = sizeof(signature_se05x); MutableByteSpan out_der_sig_span(signature_se05x, signature_se05x_len); VerifyOrReturnError(hash != nullptr, CHIP_ERROR_INVALID_ARGUMENT); VerifyOrReturnError(hash_length > 0, CHIP_ERROR_INVALID_ARGUMENT); - ChipLogDetail(Crypto, "ECDSA_validate_hash_signature: Using SE05X for ECDSA verify (hash) !"); + ChipLogDetail(Crypto, "ECDSA_validate_msg_signature: Using se05x for ECDSA verify (hash) !"); - se05x_sessionOpen(); + VerifyOrReturnError(se05x_sessionOpen() == CHIP_NO_ERROR, CHIP_ERROR_INTERNAL); VerifyOrReturnError(gex_sss_chip_ctx.ks.session != NULL, CHIP_ERROR_INTERNAL); - if (PublicKeyid == kKeyId_NotInitialized) - { - error = SE05X_Set_ECDSA_Public_Key(&keyObject, bytes, kP256_PublicKey_Length); - SuccessOrExit(error); - error = CHIP_ERROR_INTERNAL; - } - else - { - status = sss_key_object_init(&keyObject, &gex_sss_chip_ctx.ks); - VerifyOrExit(status == kStatus_SSS_Success, error = CHIP_ERROR_INTERNAL); - - status = sss_key_object_get_handle(&keyObject, PublicKeyid); - VerifyOrExit(status == kStatus_SSS_Success, error = CHIP_ERROR_INTERNAL); - } + error = SE05X_Set_ECDSA_Public_Key(&keyObject, bytes, kP256_PublicKey_Length); + SuccessOrExit(error); /* ECC Verify */ status = @@ -475,15 +519,17 @@ CHIP_ERROR P256PublicKeyHSM::ECDSA_validate_hash_signature(const uint8_t * hash, sss_asymmetric_context_free(&asymm_ctx); } - if (PublicKeyid == kKeyId_NotInitialized) + if (keyObject.keyStore->session != NULL) { sss_key_store_erase_key(&gex_sss_chip_ctx.ks, &keyObject); } return error; + +#endif // ENABLE_SE05X_ECDSA_VERIFY } -static void add_tlv(uint8_t * buf, size_t buf_index, uint8_t tag, size_t len, uint8_t * val) +void add_tlv(uint8_t * buf, size_t buf_index, uint8_t tag, size_t len, uint8_t * val) { buf[buf_index++] = (uint8_t) tag; buf[buf_index++] = (uint8_t) len; @@ -526,35 +572,46 @@ static void add_tlv(uint8_t * buf, size_t buf_index, uint8_t tag, size_t len, ui * */ -CHIP_ERROR P256KeypairHSM::NewCertificateSigningRequest(uint8_t * csr, size_t & csr_length) const +CHIP_ERROR P256Keypair::NewCertificateSigningRequest(uint8_t * csr, size_t & csr_length) const { - CHIP_ERROR error = CHIP_ERROR_INTERNAL; - sss_status_t status = kStatus_SSS_Success; +#if !ENABLE_SE05X_GENERATE_EC_KEY + return NewCertificateSigningRequest_H(&mKeypair, csr, csr_length); +#else + CHIP_ERROR error = CHIP_ERROR_INTERNAL; + sss_status_t status = kStatus_SSS_Success; sss_asymmetric_t asymm_ctx = { 0 }; - sss_object_t keyObject = { 0 }; - sss_digest_t digest_ctx = { 0 }; + sss_object_t keyObject = { 0 }; + uint32_t keyid = 0; uint8_t data_to_hash[128] = { 0 }; - size_t data_to_hash_len = sizeof(data_to_hash); - uint8_t pubkey[128] = { 0 }; - size_t pubKeyLen = 0; - uint8_t hash[32] = { 0 }; - size_t hash_length = sizeof(hash); - uint8_t signature[128] = { 0 }; - size_t signature_len = sizeof(signature); - - size_t csr_index = 0; + size_t data_to_hash_len = sizeof(data_to_hash); + uint8_t pubkey[128] = { 0 }; + size_t pubKeyLen = 0; + uint8_t hash[32] = { 0 }; + size_t hash_length = sizeof(hash); + uint8_t signature[128] = { 0 }; + size_t signature_len = sizeof(signature); + + size_t csr_index = 0; size_t buffer_index = data_to_hash_len; uint8_t organisation_oid[3] = { 0x55, 0x04, 0x0a }; // Version ::= INTEGER { v1(0), v2(1), v3(2) } - uint8_t version[3] = { 0x02, 0x01, 0x00 }; + uint8_t version[3] = { 0x02, 0x01, 0x00 }; uint8_t signature_oid[8] = { 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x04, 0x03, 0x02 }; uint8_t nist256_header[] = { 0x30, 0x59, 0x30, 0x13, 0x06, 0x07, 0x2A, 0x86, 0x48, 0xCE, 0x3D, 0x02, 0x01, 0x06, 0x08, 0x2A, 0x86, 0x48, 0xCE, 0x3D, 0x03, 0x01, 0x07, 0x03, 0x42, 0x00 }; - ChipLogDetail(Crypto, "NewCertificateSigningRequest: Using SE05X for creating CSR !"); + VerifyOrReturnError(mInitialized, CHIP_ERROR_WELL_UNINITIALIZED); + + if (CHIP_NO_ERROR != parse_se05x_keyid_from_keypair(mKeypair, &keyid)) + { + ChipLogDetail(Crypto, "NewCertificateSigningRequest : Not ref key. Using host for CSR"); + return NewCertificateSigningRequest_H(&mKeypair, csr, csr_length); + } + + ChipLogDetail(Crypto, "NewCertificateSigningRequest : Using se05x for CSR"); // No extensions are copied buffer_index -= kTlvHeader; @@ -562,7 +619,7 @@ CHIP_ERROR P256KeypairHSM::NewCertificateSigningRequest(uint8_t * csr, size_t & // Copy public key (with header) { - P256PublicKeyHSM & public_key = const_cast(Pubkey()); + P256PublicKey & public_key = const_cast(Pubkey()); VerifyOrExit((sizeof(nist256_header) + public_key.Length()) <= sizeof(pubkey), error = CHIP_ERROR_INTERNAL); @@ -616,12 +673,8 @@ CHIP_ERROR P256KeypairHSM::NewCertificateSigningRequest(uint8_t * csr, size_t & data_to_hash_len = (data_to_hash_len - buffer_index); memmove(data_to_hash, (data_to_hash + buffer_index), data_to_hash_len); - /* Create hash of `data_to_hash` buffer */ - status = sss_digest_context_init(&digest_ctx, &gex_sss_chip_ctx.session, kAlgorithm_SSS_SHA256, kMode_SSS_Digest); - VerifyOrExit(status == kStatus_SSS_Success, error = CHIP_ERROR_INTERNAL); - - status = sss_digest_one_go(&digest_ctx, data_to_hash, data_to_hash_len, hash, &hash_length); - VerifyOrExit(status == kStatus_SSS_Success, error = CHIP_ERROR_INTERNAL); + error = Hash_SHA256(data_to_hash, data_to_hash_len, hash); + SuccessOrExit(error); // Sign on hash status = sss_key_object_init(&keyObject, &gex_sss_chip_ctx.ks); @@ -685,15 +738,10 @@ CHIP_ERROR P256KeypairHSM::NewCertificateSigningRequest(uint8_t * csr, size_t & sss_asymmetric_context_free(&asymm_ctx); } - if (digest_ctx.session != NULL) - { - sss_digest_context_free(&digest_ctx); - } - return error; + +#endif // ENABLE_SE05X_GENERATE_EC_KEY } } // namespace Crypto } // namespace chip - -#endif //#if ENABLE_HSM_GENERATE_EC_KEY diff --git a/src/crypto/hsm/nxp/CHIPCryptoPALHsm_SE05X_PBKDF.cpp b/src/platform/nxp/crypto/se05x/CHIPCryptoPALHsm_se05x_pbkdf.cpp similarity index 78% rename from src/crypto/hsm/nxp/CHIPCryptoPALHsm_SE05X_PBKDF.cpp rename to src/platform/nxp/crypto/se05x/CHIPCryptoPALHsm_se05x_pbkdf.cpp index 9fe746bc1718d7..5de2a9e135a5cb 100644 --- a/src/crypto/hsm/nxp/CHIPCryptoPALHsm_SE05X_PBKDF.cpp +++ b/src/platform/nxp/crypto/se05x/CHIPCryptoPALHsm_se05x_pbkdf.cpp @@ -22,23 +22,21 @@ * chip crypto apis use either HSM or rollback to software implementation. */ -#include "CHIPCryptoPALHsm_SE05X_utils.h" +#include "CHIPCryptoPALHsm_se05x_utils.h" #include -#if ENABLE_HSM_PBKDF2_SHA256 - namespace chip { namespace Crypto { -PBKDF2_sha256HSM::PBKDF2_sha256HSM() -{ - keyid = kKeyId_pbkdf2_sha256_hmac_keyid; -} -PBKDF2_sha256HSM::~PBKDF2_sha256HSM() {} +extern CHIP_ERROR pbkdf2_sha256_h(const uint8_t * password, size_t plen, const uint8_t * salt, size_t slen, + unsigned int iteration_count, uint32_t key_length, uint8_t * output); -CHIP_ERROR PBKDF2_sha256HSM::pbkdf2_sha256(const uint8_t * password, size_t plen, const uint8_t * salt, size_t slen, - unsigned int iteration_count, uint32_t key_length, uint8_t * output) +CHIP_ERROR PBKDF2_sha256::pbkdf2_sha256(const uint8_t * password, size_t plen, const uint8_t * salt, size_t slen, + unsigned int iteration_count, uint32_t key_length, uint8_t * output) { +#if !ENABLE_SE05X_PBKDF2_SHA256 + return pbkdf2_sha256_h(password, plen, salt, slen, iteration_count, key_length, output); +#else CHIP_ERROR error = CHIP_ERROR_INTERNAL; VerifyOrReturnError(password != nullptr, CHIP_ERROR_INVALID_ARGUMENT); VerifyOrReturnError(plen > 0, CHIP_ERROR_INVALID_ARGUMENT); @@ -48,9 +46,9 @@ CHIP_ERROR PBKDF2_sha256HSM::pbkdf2_sha256(const uint8_t * password, size_t plen VerifyOrReturnError(slen <= kSpake2p_Max_PBKDF_Salt_Length, CHIP_ERROR_INVALID_ARGUMENT); VerifyOrReturnError(salt != nullptr, CHIP_ERROR_INVALID_ARGUMENT); - VerifyOrReturnError(keyid != kKeyId_NotInitialized, CHIP_ERROR_HSM); + const uint32_t keyid = kKeyId_pbkdf2_sha256_hmac_keyid; - ChipLogDetail(Crypto, "Using se05x for pbkdf2 sha256"); + ChipLogDetail(Crypto, "pbkdf2_sha256 : Using se05x for pbkdf2_sha256"); static sss_policy_u commonPol; commonPol.type = KPolicy_Common; @@ -72,7 +70,7 @@ CHIP_ERROR PBKDF2_sha256HSM::pbkdf2_sha256(const uint8_t * password, size_t plen policy_for_hmac_key.policies[0] = &hmac_withPol; policy_for_hmac_key.policies[1] = &commonPol; - se05x_sessionOpen(); + VerifyOrReturnError(se05x_sessionOpen() == CHIP_NO_ERROR, CHIP_ERROR_INTERNAL); VerifyOrReturnError(gex_sss_chip_ctx.ks.session != NULL, CHIP_ERROR_INTERNAL); sss_object_t hmacKeyObj = { @@ -94,13 +92,18 @@ CHIP_ERROR PBKDF2_sha256HSM::pbkdf2_sha256(const uint8_t * password, size_t plen (uint16_t) iteration_count, kSE05x_MACAlgo_HMAC_SHA256, (uint16_t) key_length, 0, /* derivedSessionKeyID */ output, (size_t *) &key_length); VerifyOrExit(smStatus == SM_OK, error = CHIP_ERROR_INTERNAL); + error = CHIP_NO_ERROR; exit: - sss_key_store_erase_key(&gex_sss_chip_ctx.ks, &hmacKeyObj); + if (hmacKeyObj.keyStore->session != NULL) + { + sss_key_store_erase_key(&gex_sss_chip_ctx.ks, &hmacKeyObj); + } + return error; + +#endif // ENABLE_SE05X_PBKDF2_SHA256 } } // namespace Crypto } // namespace chip - -#endif //#if ENABLE_HSM_PBKDF2_SHA256 diff --git a/src/platform/nxp/crypto/se05x/CHIPCryptoPALHsm_se05x_rng.cpp b/src/platform/nxp/crypto/se05x/CHIPCryptoPALHsm_se05x_rng.cpp new file mode 100644 index 00000000000000..adcfea10644d04 --- /dev/null +++ b/src/platform/nxp/crypto/se05x/CHIPCryptoPALHsm_se05x_rng.cpp @@ -0,0 +1,54 @@ +/* + * + * Copyright (c) 2021 Project CHIP Authors + * + * 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. + */ + +/** + * @file + * HSM based implementation of CHIP crypto primitives + * Based on configurations in CHIPCryptoPALHsm_config.h file, + * chip crypto apis use either HSM or rollback to software implementation. + */ + +#include "CHIPCryptoPALHsm_se05x_utils.h" +#include + +namespace chip { +namespace Crypto { + +CHIP_ERROR DRBG_get_bytes(uint8_t * out_buffer, const size_t out_length) +{ + // TODO - Add rollback + sss_status_t status; + sss_rng_context_t ctx_rng = { 0 }; + + VerifyOrReturnError(out_buffer != nullptr, CHIP_ERROR_INVALID_ARGUMENT); + VerifyOrReturnError(out_length > 0, CHIP_ERROR_INVALID_ARGUMENT); + + VerifyOrReturnError(se05x_sessionOpen() == CHIP_NO_ERROR, CHIP_ERROR_INTERNAL); + + status = sss_rng_context_init(&ctx_rng, &gex_sss_chip_ctx.session /* Session */); + VerifyOrReturnError(status == kStatus_SSS_Success, CHIP_ERROR_INTERNAL); + + status = sss_rng_get_random(&ctx_rng, out_buffer, out_length); + VerifyOrReturnError(status == kStatus_SSS_Success, CHIP_ERROR_INTERNAL); + + sss_rng_context_free(&ctx_rng); + + return CHIP_NO_ERROR; +} + +} // namespace Crypto +} // namespace chip diff --git a/src/crypto/hsm/nxp/CHIPCryptoPALHsm_SE05X_Spake2p.cpp b/src/platform/nxp/crypto/se05x/CHIPCryptoPALHsm_se05x_spake2p.cpp similarity index 95% rename from src/crypto/hsm/nxp/CHIPCryptoPALHsm_SE05X_Spake2p.cpp rename to src/platform/nxp/crypto/se05x/CHIPCryptoPALHsm_se05x_spake2p.cpp index 48c7b021ef3e96..a60209f065aade 100644 --- a/src/crypto/hsm/nxp/CHIPCryptoPALHsm_SE05X_Spake2p.cpp +++ b/src/platform/nxp/crypto/se05x/CHIPCryptoPALHsm_se05x_spake2p.cpp @@ -22,16 +22,16 @@ * chip crypto apis use either HSM or rollback to software implementation. */ -#include "CHIPCryptoPALHsm_SE05X_utils.h" +#include "CHIPCryptoPALHsm_se05x_utils.h" -#if ((ENABLE_HSM_SPAKE_VERIFIER) || (ENABLE_HSM_SPAKE_PROVER)) +#if ((ENABLE_SE05X_SPAKE_VERIFIER) || (ENABLE_SE05X_SPAKE_PROVER)) -#if ENABLE_HSM_SPAKE_VERIFIER +#if ENABLE_SE05X_SPAKE_VERIFIER const uint32_t w0in_id_v = 0x7D200001; const uint32_t Lin_id_v = 0x7D200002; #endif -#if ENABLE_HSM_SPAKE_PROVER +#if ENABLE_SE05X_SPAKE_PROVER const uint32_t w0in_id_p = 0x7D200003; const uint32_t w1in_id_p = 0x7D200004; #endif @@ -42,7 +42,7 @@ void Spake2p_Finish_HSM(hsm_pake_context_t * phsm_pake_context) if (gex_sss_chip_ctx.ks.session != NULL) { Se05x_API_DeleteCryptoObject(&((sss_se05x_session_t *) &gex_sss_chip_ctx.session)->s_ctx, phsm_pake_context->spake_objId); - setObjID(phsm_pake_context->spake_objId, OBJ_ID_TABLE_OBJID_STATUS_FREE); + se05x_setCryptoObjID(phsm_pake_context->spake_objId, OBJ_ID_TABLE_OBJID_STATUS_FREE); if (spake_objects_created > 0) { @@ -59,7 +59,7 @@ CHIP_ERROR create_init_crypto_obj(chip::Crypto::CHIP_SPAKE2P_ROLE role, hsm_pake SE05x_CryptoModeSubType_t subtype; #if ENABLE_REENTRANCY - SE05x_CryptoObjectID_t spakeObjectId = getObjID(); + SE05x_CryptoObjectID_t spakeObjectId = se05x_getCryptoObjID(); #else SE05x_CryptoObjectID_t spakeObjectId = (role == chip::Crypto::CHIP_SPAKE2P_ROLE::VERIFIER) ? kSE05x_CryptoObject_PAKE_TYPE_B : kSE05x_CryptoObject_PAKE_TYPE_A; @@ -82,7 +82,7 @@ CHIP_ERROR create_init_crypto_obj(chip::Crypto::CHIP_SPAKE2P_ROLE role, hsm_pake return CHIP_ERROR_INTERNAL; } - se05x_sessionOpen(); + VerifyOrReturnError(se05x_sessionOpen() == CHIP_NO_ERROR, CHIP_ERROR_INTERNAL); VerifyOrReturnError(gex_sss_chip_ctx.ks.session != NULL, CHIP_ERROR_INTERNAL); subtype.pakeMode = kSE05x_SPAKE2PLUS_P256_SHA256_HKDF_HMAC; @@ -200,8 +200,8 @@ CHIP_ERROR Spake2pHSM_P256_SHA256_HKDF_HMAC::Init(const uint8_t * context, size_ static uint8_t alreadyInitialised = 0; if (alreadyInitialised == false) { - delete_crypto_objects(); - init_cryptoObj_mutex(); + se05x_delete_crypto_objects(); + se05x_init_cryptoObj_mutex(); alreadyInitialised = true; } #endif //#if ENABLE_REENTRANCY @@ -227,7 +227,7 @@ CHIP_ERROR Spake2pHSM_P256_SHA256_HKDF_HMAC::Init(const uint8_t * context, size_ return error; } -#if ENABLE_HSM_SPAKE_VERIFIER +#if ENABLE_SE05X_SPAKE_VERIFIER CHIP_ERROR Spake2pHSM_P256_SHA256_HKDF_HMAC::BeginVerifier(const uint8_t * my_identity, size_t my_identity_len, const uint8_t * peer_identity, size_t peer_identity_len, const uint8_t * w0in, size_t w0in_len, const uint8_t * Lin, @@ -280,7 +280,7 @@ CHIP_ERROR Spake2pHSM_P256_SHA256_HKDF_HMAC::BeginVerifier(const uint8_t * my_id } #endif -#if ENABLE_HSM_SPAKE_PROVER +#if ENABLE_SE05X_SPAKE_PROVER CHIP_ERROR Spake2pHSM_P256_SHA256_HKDF_HMAC::BeginProver(const uint8_t * my_identity, size_t my_identity_len, const uint8_t * peer_identity, size_t peer_identity_len, const uint8_t * w0in, size_t w0in_len, const uint8_t * w1in, @@ -345,13 +345,13 @@ CHIP_ERROR Spake2pHSM_P256_SHA256_HKDF_HMAC::ComputeRoundOne(const uint8_t * pab VerifyOrReturnError(state == CHIP_SPAKE2P_STATE::STARTED, CHIP_ERROR_INTERNAL); VerifyOrReturnError(*out_len >= point_size, CHIP_ERROR_INTERNAL); -#if !ENABLE_HSM_SPAKE_VERIFIER +#if !ENABLE_SE05X_SPAKE_VERIFIER const bool sw_rollback_verifier = (role == chip::Crypto::CHIP_SPAKE2P_ROLE::VERIFIER); #else constexpr bool sw_rollback_verifier = false; #endif -#if ((CHIP_CRYPTO_HSM) && (!ENABLE_HSM_SPAKE_PROVER)) +#if ((CHIP_CRYPTO_HSM) && (!ENABLE_SE05X_SPAKE_PROVER)) const bool sw_rollback_prover = (role == chip::Crypto::CHIP_SPAKE2P_ROLE::PROVER); #else constexpr bool sw_rollback_prover = false; @@ -376,13 +376,13 @@ CHIP_ERROR Spake2pHSM_P256_SHA256_HKDF_HMAC::ComputeRoundTwo(const uint8_t * in, VerifyOrReturnError(state == CHIP_SPAKE2P_STATE::R1, CHIP_ERROR_INTERNAL); VerifyOrReturnError(in_len == point_size, CHIP_ERROR_INTERNAL); -#if !ENABLE_HSM_SPAKE_VERIFIER +#if !ENABLE_SE05X_SPAKE_VERIFIER const bool sw_rollback_verifier = (role == chip::Crypto::CHIP_SPAKE2P_ROLE::VERIFIER); #else constexpr bool sw_rollback_verifier = false; #endif -#if !ENABLE_HSM_SPAKE_PROVER +#if !ENABLE_SE05X_SPAKE_PROVER const bool sw_rollback_prover = (role == chip::Crypto::CHIP_SPAKE2P_ROLE::PROVER); #else constexpr bool sw_rollback_prover = false; @@ -411,13 +411,13 @@ CHIP_ERROR Spake2pHSM_P256_SHA256_HKDF_HMAC::KeyConfirm(const uint8_t * in, size { VerifyOrReturnError(state == CHIP_SPAKE2P_STATE::R2, CHIP_ERROR_INTERNAL); -#if !ENABLE_HSM_SPAKE_VERIFIER +#if !ENABLE_SE05X_SPAKE_VERIFIER const bool sw_rollback_verifier = (role == chip::Crypto::CHIP_SPAKE2P_ROLE::VERIFIER); #else constexpr bool sw_rollback_verifier = false; #endif -#if !ENABLE_HSM_SPAKE_PROVER +#if !ENABLE_SE05X_SPAKE_PROVER const bool sw_rollback_prover = (role == chip::Crypto::CHIP_SPAKE2P_ROLE::PROVER); #else constexpr bool sw_rollback_prover = false; @@ -441,4 +441,4 @@ CHIP_ERROR Spake2pHSM_P256_SHA256_HKDF_HMAC::KeyConfirm(const uint8_t * in, size } // namespace Crypto } // namespace chip -#endif //#if ((ENABLE_HSM_SPAKE_VERIFIER) || (ENABLE_HSM_SPAKE_PROVER)) +#endif //#if ((ENABLE_SE05X_SPAKE_VERIFIER) || (ENABLE_SE05X_SPAKE_PROVER)) diff --git a/src/crypto/hsm/nxp/CHIPCryptoPALHsm_SE05X_utils.cpp b/src/platform/nxp/crypto/se05x/CHIPCryptoPALHsm_se05x_utils.cpp similarity index 90% rename from src/crypto/hsm/nxp/CHIPCryptoPALHsm_SE05X_utils.cpp rename to src/platform/nxp/crypto/se05x/CHIPCryptoPALHsm_se05x_utils.cpp index 2545ecf5a657c1..ed5edc566b6cb9 100644 --- a/src/crypto/hsm/nxp/CHIPCryptoPALHsm_SE05X_utils.cpp +++ b/src/platform/nxp/crypto/se05x/CHIPCryptoPALHsm_se05x_utils.cpp @@ -22,7 +22,7 @@ * chip crypto apis use either HSM or rollback to software implementation. */ -#include "CHIPCryptoPALHsm_SE05X_utils.h" +#include "CHIPCryptoPALHsm_se05x_utils.h" #include "fsl_sss_policy.h" ex_sss_boot_ctx_t gex_sss_chip_ctx; @@ -76,39 +76,40 @@ static Mutex sSEObjMutex; #endif //#if ENABLE_REENTRANCY /* Open session to se05x */ -void se05x_sessionOpen(void) +CHIP_ERROR se05x_sessionOpen(void) { static int is_session_open = 0; if (is_session_open) { - return; + return CHIP_NO_ERROR; } memset(&gex_sss_chip_ctx, 0, sizeof(gex_sss_chip_ctx)); - const char * portName = nullptr; - sss_status_t status = ex_sss_boot_connectstring(0, NULL, &portName); + char * portName = nullptr; + sss_status_t status = ex_sss_boot_connectstring(0, NULL, &portName); if (kStatus_SSS_Success != status) { - ChipLogError(Crypto, "se05x error: %s\n", "ex_sss_boot_connectstring failed"); - return; + ChipLogError(Crypto, "se05x error: ex_sss_boot_connectstring failed"); + return CHIP_ERROR_INTERNAL; } status = ex_sss_boot_open(&gex_sss_chip_ctx, portName); if (kStatus_SSS_Success != status) { - ChipLogError(Crypto, "se05x error: %s\n", "ex_sss_boot_open failed"); - return; + ChipLogError(Crypto, "se05x error: ex_sss_boot_open failed"); + return CHIP_ERROR_INTERNAL; } status = ex_sss_key_store_and_object_init(&gex_sss_chip_ctx); if (kStatus_SSS_Success != status) { - ChipLogError(Crypto, "se05x error: %s\n", "ex_sss_key_store_and_object_init failed"); - return; + ChipLogError(Crypto, "se05x error: ex_sss_key_store_and_object_init failed"); + return CHIP_ERROR_INTERNAL; } is_session_open = 1; + return CHIP_NO_ERROR; } /* Delete key in se05x */ @@ -117,7 +118,11 @@ void se05x_delete_key(uint32_t keyid) smStatus_t smstatus = SM_NOT_OK; SE05x_Result_t exists = kSE05x_Result_NA; - se05x_sessionOpen(); + if (se05x_sessionOpen() != CHIP_NO_ERROR) + { + ChipLogError(Crypto, "se05x error: Error in session open"); + return; + } if (gex_sss_chip_ctx.ks.session != NULL) { @@ -130,19 +135,20 @@ void se05x_delete_key(uint32_t keyid) smstatus = Se05x_API_DeleteSecureObject(&((sss_se05x_session_t *) &gex_sss_chip_ctx.session)->s_ctx, keyid); if (smstatus != SM_OK) { - ChipLogError(Crypto, "se05x error: %s\n", "Error in deleting key"); + ChipLogError(Crypto, "se05x error: Error in deleting key"); } } else { - ChipLogError(Crypto, "se05x warn: %s\n", "Key doesnot exists"); + ChipLogError(Crypto, "se05x warn: Key doesnot exists"); } } else { - ChipLogError(Crypto, "se05x error: %s\n", "Error in Se05x_API_CheckObjectExists"); + ChipLogError(Crypto, "se05x error: Error in Se05x_API_CheckObjectExists"); } } + return; } /* Set key in se05x */ @@ -223,7 +229,7 @@ CHIP_ERROR se05xGetCertificate(uint32_t keyId, uint8_t * buf, size_t * buflen) certBitLen = (*buflen) * 8; - se05x_sessionOpen(); + VerifyOrReturnError(se05x_sessionOpen() == CHIP_NO_ERROR, CHIP_ERROR_INTERNAL); status = sss_key_object_init(&keyObject, &gex_sss_chip_ctx.ks); VerifyOrReturnError(status == kStatus_SSS_Success, CHIP_ERROR_INTERNAL); @@ -276,7 +282,7 @@ CHIP_ERROR se05xPerformInternalSign(uint32_t keyId, uint8_t * sigBuf, size_t * s #if ENABLE_REENTRANCY /* Init crypto object mutext */ -void init_cryptoObj_mutex(void) +void se05x_init_cryptoObj_mutex(void) { #if !CHIP_SYSTEM_CONFIG_NO_LOCKING Mutex::Init(sSEObjMutex); @@ -285,7 +291,7 @@ void init_cryptoObj_mutex(void) } /* Delete all crypto objects in se05x */ -void delete_crypto_objects(void) +void se05x_delete_crypto_objects(void) { static int obj_deleted = 0; smStatus_t smstatus = SM_NOT_OK; @@ -299,7 +305,12 @@ void delete_crypto_objects(void) { return; } - se05x_sessionOpen(); + + if (se05x_sessionOpen() != CHIP_NO_ERROR) + { + return; + } + if (gex_sss_chip_ctx.ks.session != NULL) { smstatus = Se05x_API_ReadCryptoObjectList(&((sss_se05x_session_t *) &gex_sss_chip_ctx.session)->s_ctx, list, &listlen); @@ -322,7 +333,7 @@ void delete_crypto_objects(void) } /* Get unused object id */ -SE05x_CryptoObjectID_t getObjID(void) +SE05x_CryptoObjectID_t se05x_getCryptoObjID(void) { SE05x_CryptoObjectID_t objId = (SE05x_CryptoObjectID_t) 0; SE05x_Result_t exists = kSE05x_Result_NA; @@ -353,7 +364,7 @@ SE05x_CryptoObjectID_t getObjID(void) } /* Set object id status */ -void setObjID(SE05x_CryptoObjectID_t objId, uint8_t status) +void se05x_setCryptoObjID(SE05x_CryptoObjectID_t objId, uint8_t status) { LOCK_SECURE_ELEMENT(); for (int i = 0; i < MAX_SPAKE_CRYPTO_OBJECT; i++) diff --git a/src/crypto/hsm/nxp/CHIPCryptoPALHsm_SE05X_utils.h b/src/platform/nxp/crypto/se05x/CHIPCryptoPALHsm_se05x_utils.h similarity index 82% rename from src/crypto/hsm/nxp/CHIPCryptoPALHsm_SE05X_utils.h rename to src/platform/nxp/crypto/se05x/CHIPCryptoPALHsm_se05x_utils.h index 75e59a64109649..a18e53e140f4a9 100644 --- a/src/crypto/hsm/nxp/CHIPCryptoPALHsm_SE05X_utils.h +++ b/src/platform/nxp/crypto/se05x/CHIPCryptoPALHsm_se05x_utils.h @@ -19,11 +19,11 @@ #include +#include #include -#include #include -#include +#include #include #include #include @@ -45,8 +45,9 @@ enum keyid_values kKeyId_pbkdf2_sha256_hmac_keyid = 0x7D000000, kKeyId_hkdf_sha256_hmac_keyid, kKeyId_hmac_sha256_keyid, - kKeyId_sha256_ecc_pub_keyid, - kKeyId_case_ephemeral_keyid, + kKeyId_sha256_ecc_pub_keyid, // Used for ECDSA verify + kKeyId_case_ephemeral_keyid, // Used for ECDH + kKeyId_node_op_keyid_start, // Node operational key pair }; // Enable the below macro to make spake HSM imlementation reentrant. @@ -71,7 +72,7 @@ extern "C" { #endif /* Open session to se05x */ -void se05x_sessionOpen(void); +CHIP_ERROR se05x_sessionOpen(void); /* Delete key in se05x */ void se05x_delete_key(uint32_t keyid); @@ -83,16 +84,16 @@ CHIP_ERROR se05x_set_key_for_spake(uint32_t keyid, const uint8_t * key, size_t k #if ENABLE_REENTRANCY /* Init crypto object mutext */ -void init_cryptoObj_mutex(void); +void se05x_init_cryptoObj_mutex(void); /* Delete all crypto objects in se05x */ -void delete_crypto_objects(void); +void se05x_delete_crypto_objects(void); /* Get unused object id */ -SE05x_CryptoObjectID_t getObjID(void); +SE05x_CryptoObjectID_t se05x_getCryptoObjID(void); /* Set object id status */ -void setObjID(SE05x_CryptoObjectID_t objId, uint8_t status); +void se05x_setCryptoObjID(SE05x_CryptoObjectID_t objId, uint8_t status); #endif //#if ENABLE_REENTRANCY diff --git a/src/platform/nxp/crypto/se05x/CHIPCryptoPAL_HostFallBack.cpp b/src/platform/nxp/crypto/se05x/CHIPCryptoPAL_HostFallBack.cpp new file mode 100644 index 00000000000000..c1e8d366656722 --- /dev/null +++ b/src/platform/nxp/crypto/se05x/CHIPCryptoPAL_HostFallBack.cpp @@ -0,0 +1,563 @@ +/* + * + * Copyright (c) 2020-2022 Project CHIP Authors + * + * 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. + */ + +/** + * @file + * mbedTLS based implementation of CHIP crypto primitives + */ + +#include "CHIPCryptoPAL.h" + +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#if defined(MBEDTLS_X509_CRT_PARSE_C) +#include +#endif // defined(MBEDTLS_X509_CRT_PARSE_C) +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +namespace chip { +namespace Crypto { + +#define MAX_ERROR_STR_LEN 128 +#define NUM_BYTES_IN_SHA256_HASH 32 + +// In mbedTLS 3.0.0 direct access to structure fields was replaced with using MBEDTLS_PRIVATE macro. +#if (MBEDTLS_VERSION_NUMBER >= 0x03000000) +#define CHIP_CRYPTO_PAL_PRIVATE(x) MBEDTLS_PRIVATE(x) +#else +#define CHIP_CRYPTO_PAL_PRIVATE(x) x +#endif + +#if (MBEDTLS_VERSION_NUMBER >= 0x03000000 && MBEDTLS_VERSION_NUMBER < 0x03010000) +#define CHIP_CRYPTO_PAL_PRIVATE_X509(x) MBEDTLS_PRIVATE(x) +#else +#define CHIP_CRYPTO_PAL_PRIVATE_X509(x) x +#endif + +static void _log_mbedTLS_error(int error_code) +{ + if (error_code != 0) + { +#if defined(MBEDTLS_ERROR_C) + char error_str[MAX_ERROR_STR_LEN]; + mbedtls_strerror(error_code, error_str, sizeof(error_str)); + ChipLogError(Crypto, "mbedTLS error: %s", error_str); +#else + // Error codes defined in 16-bit negative hex numbers. Ease lookup by printing likewise + ChipLogError(Crypto, "mbedTLS error: -0x%04X", -static_cast(error_code)); +#endif + } +} + +static_assert(kMAX_Hash_SHA256_Context_Size >= sizeof(mbedtls_sha256_context), + "kMAX_Hash_SHA256_Context_Size is too small for the size of underlying mbedtls_sha256_context"); + +static inline mbedtls_sha256_context * to_inner_hash_sha256_context(HashSHA256OpaqueContext * context) +{ + return SafePointerCast(context); +} + +static int CryptoRNG(void * ctxt, uint8_t * out_buffer, size_t out_length) +{ + return (chip::Crypto::DRBG_get_bytes(out_buffer, out_length) == CHIP_NO_ERROR) ? 0 : 1; +} + +extern mbedtls_ecp_group_id MapECPGroupId(SupportedECPKeyTypes keyType); + +static inline mbedtls_ecp_keypair * to_keypair(P256KeypairContext * context) +{ + return SafePointerCast(context); +} + +static inline const mbedtls_ecp_keypair * to_const_keypair(const P256KeypairContext * context) +{ + return SafePointerCast(context); +} + +void ClearSecretData(uint8_t * buf, size_t len) +{ + mbedtls_platform_zeroize(buf, len); +} + +CHIP_ERROR Initialize_H(P256Keypair * pk, P256PublicKey * mPublicKey, P256KeypairContext * mKeypair) +{ + CHIP_ERROR error = CHIP_NO_ERROR; + int result = 0; + + size_t pubkey_size = 0; + + pk->Clear(); + + mbedtls_ecp_group_id group = MapECPGroupId(mPublicKey->Type()); + + mbedtls_ecp_keypair * keypair = to_keypair(mKeypair); + mbedtls_ecp_keypair_init(keypair); + + result = mbedtls_ecp_gen_key(group, keypair, CryptoRNG, nullptr); + VerifyOrExit(result == 0, error = CHIP_ERROR_INTERNAL); + + result = mbedtls_ecp_point_write_binary(&keypair->CHIP_CRYPTO_PAL_PRIVATE(grp), &keypair->CHIP_CRYPTO_PAL_PRIVATE(Q), + MBEDTLS_ECP_PF_UNCOMPRESSED, &pubkey_size, Uint8::to_uchar(mPublicKey->Bytes()), + mPublicKey->Length()); + VerifyOrExit(result == 0, error = CHIP_ERROR_INVALID_ARGUMENT); + VerifyOrExit(pubkey_size == mPublicKey->Length(), error = CHIP_ERROR_INVALID_ARGUMENT); + + keypair = nullptr; + // mInitialized to be set in caller function + // pk.mInitialized = true; + +exit: + if (keypair != nullptr) + { + mbedtls_ecp_keypair_free(keypair); + keypair = nullptr; + } + + _log_mbedTLS_error(result); + return error; +} + +CHIP_ERROR ECDSA_sign_msg_H(P256KeypairContext * mKeypair, const uint8_t * msg, const size_t msg_length, + P256ECDSASignature & out_signature) +{ + // To be checked by the caller + // VerifyOrReturnError(mInitialized, CHIP_ERROR_WELL_UNINITIALIZED); + VerifyOrReturnError((msg != nullptr) && (msg_length > 0), CHIP_ERROR_INVALID_ARGUMENT); + + uint8_t digest[kSHA256_Hash_Length]; + memset(&digest[0], 0, sizeof(digest)); + ReturnErrorOnFailure(Hash_SHA256(msg, msg_length, &digest[0])); + +#if defined(MBEDTLS_ECDSA_C) + CHIP_ERROR error = CHIP_NO_ERROR; + int result = 0; + mbedtls_mpi r, s; + mbedtls_mpi_init(&r); + mbedtls_mpi_init(&s); + + const mbedtls_ecp_keypair * keypair = to_const_keypair(mKeypair); + + mbedtls_ecdsa_context ecdsa_ctxt; + mbedtls_ecdsa_init(&ecdsa_ctxt); + + result = mbedtls_ecdsa_from_keypair(&ecdsa_ctxt, keypair); + VerifyOrExit(result == 0, error = CHIP_ERROR_INTERNAL); + + result = mbedtls_ecdsa_sign(&ecdsa_ctxt.CHIP_CRYPTO_PAL_PRIVATE(grp), &r, &s, &ecdsa_ctxt.CHIP_CRYPTO_PAL_PRIVATE(d), + Uint8::to_const_uchar(digest), sizeof(digest), CryptoRNG, nullptr); + + VerifyOrExit(result == 0, error = CHIP_ERROR_INTERNAL); + + VerifyOrExit((mbedtls_mpi_size(&r) <= kP256_FE_Length) && (mbedtls_mpi_size(&s) <= kP256_FE_Length), + error = CHIP_ERROR_INTERNAL); + + // Concatenate r and s to output. Sizes were checked above. + result = mbedtls_mpi_write_binary(&r, out_signature.Bytes() + 0u, kP256_FE_Length); + VerifyOrExit(result == 0, error = CHIP_ERROR_INTERNAL); + + result = mbedtls_mpi_write_binary(&s, out_signature.Bytes() + kP256_FE_Length, kP256_FE_Length); + VerifyOrExit(result == 0, error = CHIP_ERROR_INTERNAL); + + VerifyOrExit(out_signature.SetLength(kP256_ECDSA_Signature_Length_Raw) == CHIP_NO_ERROR, error = CHIP_ERROR_INTERNAL); + +exit: + keypair = nullptr; + mbedtls_ecdsa_free(&ecdsa_ctxt); + mbedtls_mpi_free(&s); + mbedtls_mpi_free(&r); + _log_mbedTLS_error(result); + return error; +#else + return CHIP_ERROR_NOT_IMPLEMENTED; +#endif +} + +CHIP_ERROR ECDH_derive_secret_H(P256KeypairContext * mKeypair, const P256PublicKey & remote_public_key, + P256ECDHDerivedSecret & out_secret) +{ +#if defined(MBEDTLS_ECDH_C) + + CHIP_ERROR error = CHIP_NO_ERROR; + int result = 0; + size_t secret_length = (out_secret.Length() == 0) ? out_secret.Capacity() : out_secret.Length(); + + mbedtls_ecp_group ecp_grp; + mbedtls_ecp_group_init(&ecp_grp); + + mbedtls_mpi mpi_secret; + mbedtls_mpi_init(&mpi_secret); + + mbedtls_ecp_point ecp_pubkey; + mbedtls_ecp_point_init(&ecp_pubkey); + + const mbedtls_ecp_keypair * keypair = to_const_keypair(mKeypair); + + // To be checked by the caller + // VerifyOrExit(mInitialized, error = CHIP_ERROR_WELL_UNINITIALIZED); + + result = mbedtls_ecp_group_load(&ecp_grp, MapECPGroupId(remote_public_key.Type())); + VerifyOrExit(result == 0, error = CHIP_ERROR_INTERNAL); + + result = + mbedtls_ecp_point_read_binary(&ecp_grp, &ecp_pubkey, Uint8::to_const_uchar(remote_public_key), remote_public_key.Length()); + VerifyOrExit(result == 0, error = CHIP_ERROR_INVALID_ARGUMENT); + + result = + mbedtls_ecdh_compute_shared(&ecp_grp, &mpi_secret, &ecp_pubkey, &keypair->CHIP_CRYPTO_PAL_PRIVATE(d), CryptoRNG, nullptr); + VerifyOrExit(result == 0, error = CHIP_ERROR_INTERNAL); + + result = mbedtls_mpi_write_binary(&mpi_secret, out_secret.Bytes() /*Uint8::to_uchar(out_secret)*/, secret_length); + VerifyOrExit(result == 0, error = CHIP_ERROR_INTERNAL); + out_secret.SetLength(secret_length); + +exit: + keypair = nullptr; + mbedtls_ecp_group_free(&ecp_grp); + mbedtls_mpi_free(&mpi_secret); + mbedtls_ecp_point_free(&ecp_pubkey); + _log_mbedTLS_error(result); + return error; + +#else + return CHIP_ERROR_NOT_IMPLEMENTED; +#endif +} + +CHIP_ERROR ECDSA_validate_hash_signature_H(const P256PublicKey * public_key, const uint8_t * hash, const size_t hash_length, + const P256ECDSASignature & signature) +{ +#if defined(MBEDTLS_ECDSA_C) + VerifyOrReturnError(hash != nullptr, CHIP_ERROR_INVALID_ARGUMENT); + VerifyOrReturnError(hash_length == kSHA256_Hash_Length, CHIP_ERROR_INVALID_ARGUMENT); + VerifyOrReturnError(signature.Length() == kP256_ECDSA_Signature_Length_Raw, CHIP_ERROR_INVALID_ARGUMENT); + + CHIP_ERROR error = CHIP_NO_ERROR; + int result = 0; + mbedtls_mpi r, s; + + mbedtls_mpi_init(&r); + mbedtls_mpi_init(&s); + + mbedtls_ecp_keypair keypair; + mbedtls_ecp_keypair_init(&keypair); + + mbedtls_ecdsa_context ecdsa_ctxt; + mbedtls_ecdsa_init(&ecdsa_ctxt); + + result = mbedtls_ecp_group_load(&keypair.CHIP_CRYPTO_PAL_PRIVATE(grp), MapECPGroupId(public_key->Type())); + + VerifyOrExit(result == 0, error = CHIP_ERROR_INVALID_ARGUMENT); + + result = mbedtls_ecp_point_read_binary(&keypair.CHIP_CRYPTO_PAL_PRIVATE(grp), &keypair.CHIP_CRYPTO_PAL_PRIVATE(Q), + Uint8::to_const_uchar(*public_key), public_key->Length()); + + VerifyOrExit(result == 0, error = CHIP_ERROR_INVALID_ARGUMENT); + + result = mbedtls_ecdsa_from_keypair(&ecdsa_ctxt, &keypair); + VerifyOrExit(result == 0, error = CHIP_ERROR_INTERNAL); + + // Read the big nums from the signature + result = mbedtls_mpi_read_binary(&r, Uint8::to_const_uchar(signature.ConstBytes()) + 0u, kP256_FE_Length); + VerifyOrExit(result == 0, error = CHIP_ERROR_INTERNAL); + + result = mbedtls_mpi_read_binary(&s, Uint8::to_const_uchar(signature.ConstBytes()) + kP256_FE_Length, kP256_FE_Length); + VerifyOrExit(result == 0, error = CHIP_ERROR_INTERNAL); + + result = mbedtls_ecdsa_verify(&ecdsa_ctxt.CHIP_CRYPTO_PAL_PRIVATE(grp), Uint8::to_const_uchar(hash), hash_length, + &ecdsa_ctxt.CHIP_CRYPTO_PAL_PRIVATE(Q), &r, &s); + + VerifyOrExit(result == 0, error = CHIP_ERROR_INVALID_SIGNATURE); + +exit: + mbedtls_ecdsa_free(&ecdsa_ctxt); + mbedtls_ecp_keypair_free(&keypair); + mbedtls_mpi_free(&s); + mbedtls_mpi_free(&r); + _log_mbedTLS_error(result); + return error; +#else + return CHIP_ERROR_NOT_IMPLEMENTED; +#endif +} + +CHIP_ERROR ECDSA_validate_msg_signature_H(const P256PublicKey * public_key, const uint8_t * msg, const size_t msg_length, + const P256ECDSASignature & signature) +{ +#if defined(MBEDTLS_ECDSA_C) + VerifyOrReturnError((msg != nullptr) && (msg_length > 0), CHIP_ERROR_INVALID_ARGUMENT); + + uint8_t digest[kSHA256_Hash_Length]; + memset(&digest[0], 0, sizeof(digest)); + ReturnErrorOnFailure(Hash_SHA256(msg, msg_length, &digest[0])); + + return ECDSA_validate_hash_signature_H(public_key, &digest[0], sizeof(digest), signature); +#else + return CHIP_ERROR_NOT_IMPLEMENTED; +#endif +} + +CHIP_ERROR NewCertificateSigningRequest_H(P256KeypairContext * mKeypair, uint8_t * out_csr, size_t & csr_length) +{ +#if defined(MBEDTLS_X509_CSR_WRITE_C) + CHIP_ERROR error = CHIP_NO_ERROR; + int result = 0; + size_t out_length; + + mbedtls_x509write_csr csr; + mbedtls_x509write_csr_init(&csr); + + mbedtls_pk_context pk; + pk.CHIP_CRYPTO_PAL_PRIVATE(pk_info) = mbedtls_pk_info_from_type(MBEDTLS_PK_ECKEY); + pk.CHIP_CRYPTO_PAL_PRIVATE(pk_ctx) = to_keypair(mKeypair); + VerifyOrExit(pk.CHIP_CRYPTO_PAL_PRIVATE(pk_info) != nullptr, error = CHIP_ERROR_INTERNAL); + + // To be checked by the caller + // VerifyOrExit(mInitialized, error = CHIP_ERROR_WELL_UNINITIALIZED); + + mbedtls_x509write_csr_set_key(&csr, &pk); + + mbedtls_x509write_csr_set_md_alg(&csr, MBEDTLS_MD_SHA256); + + // TODO: mbedTLS CSR parser fails if the subject name is not set (or if empty). + // CHIP Spec doesn't specify the subject name that can be used. + // Figure out the correct value and update this code. + result = mbedtls_x509write_csr_set_subject_name(&csr, "O=CSR"); + VerifyOrExit(result == 0, error = CHIP_ERROR_INTERNAL); + + result = mbedtls_x509write_csr_der(&csr, out_csr, csr_length, CryptoRNG, nullptr); + VerifyOrExit(result > 0, error = CHIP_ERROR_INTERNAL); + VerifyOrExit(CanCastTo(result), error = CHIP_ERROR_INTERNAL); + + out_length = static_cast(result); + result = 0; + VerifyOrExit(out_length <= csr_length, error = CHIP_ERROR_INTERNAL); + + if (csr_length != out_length) + { + // mbedTLS API writes the CSR at the end of the provided buffer. + // Let's move it to the start of the buffer. + size_t offset = csr_length - out_length; + memmove(out_csr, &out_csr[offset], out_length); + } + + csr_length = out_length; + +exit: + mbedtls_x509write_csr_free(&csr); + + _log_mbedTLS_error(result); + return error; +#else + ChipLogError(Crypto, "MBEDTLS_X509_CSR_WRITE_C is not enabled. CSR cannot be created"); + return CHIP_ERROR_UNSUPPORTED_CHIP_FEATURE; +#endif +} + +CHIP_ERROR Serialize_H(const P256KeypairContext mKeypair, const P256PublicKey mPublicKey, P256SerializedKeypair & output) +{ + const mbedtls_ecp_keypair * keypair = to_const_keypair(&mKeypair); + size_t len = output.Length() == 0 ? output.Capacity() : output.Length(); + Encoding::BufferWriter bbuf(output.Bytes(), len); + uint8_t privkey[kP256_PrivateKey_Length]; + CHIP_ERROR error = CHIP_NO_ERROR; + int result = 0; + + bbuf.Put(mPublicKey, mPublicKey.Length()); + + VerifyOrExit(bbuf.Available() == sizeof(privkey), error = CHIP_ERROR_INTERNAL); + + VerifyOrExit(mbedtls_mpi_size(&keypair->CHIP_CRYPTO_PAL_PRIVATE(d)) <= bbuf.Available(), error = CHIP_ERROR_INTERNAL); + result = mbedtls_mpi_write_binary(&keypair->CHIP_CRYPTO_PAL_PRIVATE(d), Uint8::to_uchar(privkey), sizeof(privkey)); + + VerifyOrExit(result == 0, error = CHIP_ERROR_INTERNAL); + + bbuf.Put(privkey, sizeof(privkey)); + VerifyOrExit(bbuf.Fit(), error = CHIP_ERROR_BUFFER_TOO_SMALL); + + output.SetLength(bbuf.Needed()); + +exit: + ClearSecretData(privkey, sizeof(privkey)); + _log_mbedTLS_error(result); + return error; +} + +CHIP_ERROR Deserialize_H(P256Keypair * pk, P256PublicKey * mPublicKey, P256KeypairContext * mKeypair, P256SerializedKeypair & input) +{ + Encoding::BufferWriter bbuf(*mPublicKey, mPublicKey->Length()); + + int result = 0; + CHIP_ERROR error = CHIP_NO_ERROR; + + pk->Clear(); + + mbedtls_ecp_keypair * keypair = to_keypair(mKeypair); + mbedtls_ecp_keypair_init(keypair); + + result = mbedtls_ecp_group_load(&keypair->CHIP_CRYPTO_PAL_PRIVATE(grp), MapECPGroupId(mPublicKey->Type())); + + VerifyOrExit(result == 0, error = CHIP_ERROR_INTERNAL); + + VerifyOrExit(input.Length() == mPublicKey->Length() + kP256_PrivateKey_Length, error = CHIP_ERROR_INVALID_ARGUMENT); + bbuf.Put(input.ConstBytes(), mPublicKey->Length()); + VerifyOrExit(bbuf.Fit(), error = CHIP_ERROR_NO_MEMORY); + + printf("\n"); + for (size_t i = 0; i < mPublicKey->Length(); i++) + { + printf("0x%02X ", Uint8::to_const_uchar(*mPublicKey)[i]); + } + printf("\n"); + + result = mbedtls_ecp_point_read_binary(&keypair->CHIP_CRYPTO_PAL_PRIVATE(grp), &keypair->CHIP_CRYPTO_PAL_PRIVATE(Q), + Uint8::to_const_uchar(*mPublicKey), mPublicKey->Length()); + VerifyOrExit(result == 0, error = CHIP_ERROR_INVALID_ARGUMENT); + + { + const uint8_t * privkey = input.ConstBytes() /*Uint8::to_const_uchar(input)*/ + mPublicKey->Length(); + + result = mbedtls_mpi_read_binary(&keypair->CHIP_CRYPTO_PAL_PRIVATE(d), privkey, kP256_PrivateKey_Length); + VerifyOrExit(result == 0, error = CHIP_ERROR_INVALID_ARGUMENT); + } + +exit: + _log_mbedTLS_error(result); + return error; +} + +CHIP_ERROR HKDF_SHA256_H(const uint8_t * secret, const size_t secret_length, const uint8_t * salt, const size_t salt_length, + const uint8_t * info, const size_t info_length, uint8_t * out_buffer, size_t out_length) +{ + VerifyOrReturnError(secret != nullptr, CHIP_ERROR_INVALID_ARGUMENT); + VerifyOrReturnError(secret_length > 0, CHIP_ERROR_INVALID_ARGUMENT); + + // Salt is optional + if (salt_length > 0) + { + VerifyOrReturnError(salt != nullptr, CHIP_ERROR_INVALID_ARGUMENT); + } + + VerifyOrReturnError(info_length > 0, CHIP_ERROR_INVALID_ARGUMENT); + VerifyOrReturnError(info != nullptr, CHIP_ERROR_INVALID_ARGUMENT); + VerifyOrReturnError(out_length > 0, CHIP_ERROR_INVALID_ARGUMENT); + VerifyOrReturnError(out_buffer != nullptr, CHIP_ERROR_INVALID_ARGUMENT); + + const mbedtls_md_info_t * const md = mbedtls_md_info_from_type(MBEDTLS_MD_SHA256); + VerifyOrReturnError(md != nullptr, CHIP_ERROR_INTERNAL); + + const int result = mbedtls_hkdf(md, Uint8::to_const_uchar(salt), salt_length, Uint8::to_const_uchar(secret), secret_length, + Uint8::to_const_uchar(info), info_length, Uint8::to_uchar(out_buffer), out_length); + _log_mbedTLS_error(result); + VerifyOrReturnError(result == 0, CHIP_ERROR_INTERNAL); + + return CHIP_NO_ERROR; +} + +CHIP_ERROR pbkdf2_sha256_h(const uint8_t * password, size_t plen, const uint8_t * salt, size_t slen, unsigned int iteration_count, + uint32_t key_length, uint8_t * output) +{ + CHIP_ERROR error = CHIP_NO_ERROR; + int result = 0; + const mbedtls_md_info_t * md_info; + mbedtls_md_context_t md_ctxt; + constexpr int use_hmac = 1; + + bool free_md_ctxt = false; + + VerifyOrExit(password != nullptr, error = CHIP_ERROR_INVALID_ARGUMENT); + VerifyOrExit(plen > 0, error = CHIP_ERROR_INVALID_ARGUMENT); + VerifyOrExit(salt != nullptr, error = CHIP_ERROR_INVALID_ARGUMENT); + VerifyOrExit(slen >= kSpake2p_Min_PBKDF_Salt_Length, error = CHIP_ERROR_INVALID_ARGUMENT); + VerifyOrExit(slen <= kSpake2p_Max_PBKDF_Salt_Length, error = CHIP_ERROR_INVALID_ARGUMENT); + VerifyOrExit(key_length > 0, error = CHIP_ERROR_INVALID_ARGUMENT); + VerifyOrExit(output != nullptr, error = CHIP_ERROR_INVALID_ARGUMENT); + + md_info = mbedtls_md_info_from_type(MBEDTLS_MD_SHA256); + VerifyOrExit(md_info != nullptr, error = CHIP_ERROR_INTERNAL); + + mbedtls_md_init(&md_ctxt); + free_md_ctxt = true; + + result = mbedtls_md_setup(&md_ctxt, md_info, use_hmac); + VerifyOrExit(result == 0, error = CHIP_ERROR_INTERNAL); + + result = mbedtls_pkcs5_pbkdf2_hmac(&md_ctxt, Uint8::to_const_uchar(password), plen, Uint8::to_const_uchar(salt), slen, + iteration_count, key_length, Uint8::to_uchar(output)); + + VerifyOrExit(result == 0, error = CHIP_ERROR_INTERNAL); + +exit: + _log_mbedTLS_error(result); + + if (free_md_ctxt) + { + mbedtls_md_free(&md_ctxt); + } + + return error; +} + +CHIP_ERROR HMAC_SHA256_h(const uint8_t * key, size_t key_length, const uint8_t * message, size_t message_length, + uint8_t * out_buffer, size_t out_length) +{ + VerifyOrReturnError(key != nullptr, CHIP_ERROR_INVALID_ARGUMENT); + VerifyOrReturnError(key_length > 0, CHIP_ERROR_INVALID_ARGUMENT); + VerifyOrReturnError(message != nullptr, CHIP_ERROR_INVALID_ARGUMENT); + VerifyOrReturnError(message_length > 0, CHIP_ERROR_INVALID_ARGUMENT); + VerifyOrReturnError(out_length >= kSHA256_Hash_Length, CHIP_ERROR_INVALID_ARGUMENT); + VerifyOrReturnError(out_buffer != nullptr, CHIP_ERROR_INVALID_ARGUMENT); + + const mbedtls_md_info_t * const md = mbedtls_md_info_from_type(MBEDTLS_MD_SHA256); + VerifyOrReturnError(md != nullptr, CHIP_ERROR_INTERNAL); + + const int result = + mbedtls_md_hmac(md, Uint8::to_const_uchar(key), key_length, Uint8::to_const_uchar(message), message_length, out_buffer); + + _log_mbedTLS_error(result); + VerifyOrReturnError(result == 0, CHIP_ERROR_INTERNAL); + + return CHIP_NO_ERROR; +} + +} // namespace Crypto +} // namespace chip diff --git a/src/platform/nxp/crypto/se05x/CHIPCryptoPAL_se05x.h b/src/platform/nxp/crypto/se05x/CHIPCryptoPAL_se05x.h new file mode 100644 index 00000000000000..b1adef99b9ef52 --- /dev/null +++ b/src/platform/nxp/crypto/se05x/CHIPCryptoPAL_se05x.h @@ -0,0 +1,83 @@ +/* + * + * Copyright (c) 2020 Project CHIP Authors + * + * 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. + */ + +/** + * @file + * Header that exposes the platform agnostic CHIP crypto primitives + */ + +#pragma once + +#include "CHIPCryptoPALHsm_se05x_config.h" +#include + +#if ((ENABLE_SE05X_SPAKE_VERIFIER) || (ENABLE_SE05X_SPAKE_PROVER)) +typedef struct hsm_pake_context_s +{ + uint8_t spake_context[32]; + size_t spake_context_len; + uint8_t spake_objId; +} hsm_pake_context_t; +#endif //#if ((ENABLE_SE05X_SPAKE_VERIFIER) || (ENABLE_SE05X_SPAKE_PROVER)) + +namespace chip { +namespace Crypto { + +#define NXP_CRYPTO_KEY_MAGIC \ + { \ + 0xA5, 0xA6, 0xB5, 0xB6, 0xA5, 0xA6, 0xB5, 0xB6 \ + } + +static const uint8_t se05x_magic_no[] = NXP_CRYPTO_KEY_MAGIC; + +#if ((ENABLE_SE05X_SPAKE_VERIFIER) || (ENABLE_SE05X_SPAKE_PROVER)) +/* Spake HSM class */ + +class Spake2pHSM_P256_SHA256_HKDF_HMAC : public Spake2p_P256_SHA256_HKDF_HMAC +{ +public: + Spake2pHSM_P256_SHA256_HKDF_HMAC() {} + + ~Spake2pHSM_P256_SHA256_HKDF_HMAC() {} + + CHIP_ERROR Init(const uint8_t * context, size_t context_len) override; + +#if ENABLE_SE05X_SPAKE_VERIFIER + CHIP_ERROR BeginVerifier(const uint8_t * my_identity, size_t my_identity_len, const uint8_t * peer_identity, + size_t peer_identity_len, const uint8_t * w0in, size_t w0in_len, const uint8_t * Lin, + size_t Lin_len) override; +#endif + +#if ENABLE_SE05X_SPAKE_PROVER + CHIP_ERROR BeginProver(const uint8_t * my_identity, size_t my_identity_len, const uint8_t * peer_identity, + size_t peer_identity_len, const uint8_t * w0in, size_t w0in_len, const uint8_t * w1in, + size_t w1in_len) override; +#endif + + CHIP_ERROR ComputeRoundOne(const uint8_t * pab, size_t pab_len, uint8_t * out, size_t * out_len) override; + + CHIP_ERROR ComputeRoundTwo(const uint8_t * in, size_t in_len, uint8_t * out, size_t * out_len) override; + + CHIP_ERROR KeyConfirm(const uint8_t * in, size_t in_len) override; + + hsm_pake_context_t hsm_pake_context; +}; + +#endif //#if ((ENABLE_SE05X_SPAKE_VERIFIER) || (ENABLE_SE05X_SPAKE_PROVER)) + +} // namespace Crypto +} // namespace chip diff --git a/src/platform/nxp/crypto/se05x/args.gni b/src/platform/nxp/crypto/se05x/args.gni new file mode 100644 index 00000000000000..964e619aff2c9e --- /dev/null +++ b/src/platform/nxp/crypto/se05x/args.gni @@ -0,0 +1,20 @@ +# Copyright (c) 2020 Project CHIP Authors +# +# 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. + +import("//build_overrides/chip.gni") +import("${chip_root}/src/crypto/crypto.gni") + +nxp_crypto_impl = "se05x" +chip_crypto = "platform" +nxp_crypto_mw_root = "//third_party/simw-top-mini" diff --git a/src/protocols/secure_channel/CASESession.cpp b/src/protocols/secure_channel/CASESession.cpp index aaccba973b2f08..4974dd76a283cd 100644 --- a/src/protocols/secure_channel/CASESession.cpp +++ b/src/protocols/secure_channel/CASESession.cpp @@ -48,9 +48,6 @@ #include #include #include -#if CHIP_CRYPTO_HSM -#include -#endif namespace { @@ -1685,17 +1682,8 @@ CHIP_ERROR CASESession::HandleSigma3b(HandleSigma3Data & data, bool & cancel) // current flow of code, a malicious node can trigger a DoS style attack on the device. // The same change should be made in Sigma2 processing. // Step 7 - Validate Signature -#ifdef ENABLE_HSM_ECDSA_VERIFY - { - P256PublicKeyHSM initiatorPublicKeyHSM; - memcpy(Uint8::to_uchar(initiatorPublicKeyHSM), initiatorPublicKey.Bytes(), initiatorPublicKey.Length()); - ReturnErrorOnFailure(initiatorPublicKeyHSM.ECDSA_validate_msg_signature(data.msg_R3_Signed.Get(), data.msg_r3_signed_len, - data.tbsData3Signature)); - } -#else ReturnErrorOnFailure( initiatorPublicKey.ECDSA_validate_msg_signature(data.msg_R3_Signed.Get(), data.msg_r3_signed_len, data.tbsData3Signature)); -#endif return CHIP_NO_ERROR; } diff --git a/src/protocols/secure_channel/PASESession.h b/src/protocols/secure_channel/PASESession.h index 19918b7a3515d5..39508d8342d7b8 100644 --- a/src/protocols/secure_channel/PASESession.h +++ b/src/protocols/secure_channel/PASESession.h @@ -27,9 +27,6 @@ #pragma once #include -#if CHIP_CRYPTO_HSM -#include -#endif #include #include #include @@ -213,11 +210,7 @@ class DLL_EXPORT PASESession : public Messaging::UnsolicitedMessageHandler, // mNextExpectedMsg is set when we are expecting a message. Optional mNextExpectedMsg; -#ifdef ENABLE_HSM_SPAKE - Spake2pHSM_P256_SHA256_HKDF_HMAC mSpake2p; -#else Spake2p_P256_SHA256_HKDF_HMAC mSpake2p; -#endif Spake2pVerifier mPASEVerifier; diff --git a/third_party/simw-top-mini/BUILD.gn b/third_party/simw-top-mini/BUILD.gn index 0cd9eb9dc2a009..ed80ad0aea0db5 100644 --- a/third_party/simw-top-mini/BUILD.gn +++ b/third_party/simw-top-mini/BUILD.gn @@ -13,6 +13,10 @@ # limitations under the License. import("//build_overrides/chip.gni") +import("//build_overrides/nlassert.gni") + +import("${chip_root}/build/chip/buildconfig_header.gni") +import("${chip_root}/src/crypto/crypto.gni") import("${chip_root}/src/platform/device.gni") import("${chip_root}/third_party/simw-top-mini/simw_config.gni") @@ -25,7 +29,7 @@ config("se05x_config") { "SMCOM_T1oI2C", ] - #defines += ["FLOW_VERBOSE"] + # defines += ["FLOW_VERBOSE"] if (chip_device_platform == "k32w0") { defines += [ @@ -35,82 +39,76 @@ config("se05x_config") { ] } - if (chip_rpi_se05x_t4t_demo == 1) { - defines += [ "CHIP_RPI_SE05X_T4T_DEMO" ] - } - include_dirs = [ - "${chip_root}/third_party/simw-top-mini/repo", - "${chip_root}/third_party/simw-top-mini/repo/sss/inc", - "${chip_root}/third_party/simw-top-mini/repo/sss/port/default", - "${chip_root}/third_party/simw-top-mini/repo/sss/ex/src", - "${chip_root}/third_party/simw-top-mini/repo/sss/ex/inc", - "${chip_root}/third_party/simw-top-mini/repo/hostlib/hostLib/inc", - "${chip_root}/third_party/simw-top-mini/repo/hostlib/hostLib/libCommon/infra", - "${chip_root}/third_party/simw-top-mini/repo/hostlib/hostLib/libCommon/smCom", - "${chip_root}/third_party/simw-top-mini/repo/hostlib/hostLib/libCommon/log", - "${chip_root}/third_party/simw-top-mini/repo/hostlib/hostLib/libCommon/smCom/T1oI2C", - "${chip_root}/third_party/simw-top-mini/repo/hostlib/hostLib/se05x_03_xx_xx", - "${chip_root}/third_party/simw-top-mini/repo/hostlib/hostLib/platform/inc", - "${chip_root}/third_party/simw-top-mini/repo/hostlib/hostLib/libCommon/smCom", + "repo", + "repo/sss/inc", + "repo/sss/port/default", + "repo/sss/ex/src", + "repo/sss/ex/inc", + "repo/hostlib/hostLib/inc", + "repo/hostlib/hostLib/libCommon/infra", + "repo/hostlib/hostLib/libCommon/smCom", + "repo/hostlib/hostLib/libCommon/log", + "repo/hostlib/hostLib/se05x_03_xx_xx", + "repo/hostlib/hostLib/platform/inc", + "repo/hostlib/hostLib/libCommon/smCom", ] + include_dirs += [ "repo/hostlib/hostLib/libCommon/smCom/T1oI2C" ] if (chip_device_platform == "k32w0") { include_dirs += [ - "${chip_root}/third_party/simw-top-mini/repo/demos/ksdk/common/boards/DK6/wireless_examples/chip", - "${chip_root}/third_party/simw-top-mini/repo/demos/ksdk/common/freertos/boards/DK6", + "repo/demos/ksdk/common/boards/DK6/wireless_examples/chip", + "repo/demos/ksdk/common/freertos/boards/DK6", ] } } -source_set("se05x") { +static_library("se05x") { sources = [ - "${chip_root}/third_party/simw-top-mini/repo/hostlib/hostLib/libCommon/infra/global_platf.c", - "${chip_root}/third_party/simw-top-mini/repo/hostlib/hostLib/libCommon/infra/sm_apdu.c", - "${chip_root}/third_party/simw-top-mini/repo/hostlib/hostLib/libCommon/infra/sm_connect.c", - "${chip_root}/third_party/simw-top-mini/repo/hostlib/hostLib/libCommon/infra/sm_errors.c", - "${chip_root}/third_party/simw-top-mini/repo/hostlib/hostLib/libCommon/infra/sm_printf.c", - "${chip_root}/third_party/simw-top-mini/repo/hostlib/hostLib/libCommon/log/nxLog.c", - "${chip_root}/third_party/simw-top-mini/repo/hostlib/hostLib/libCommon/smCom/smCom.c", - "${chip_root}/third_party/simw-top-mini/repo/hostlib/hostLib/platform/generic/se05x_t4t_utils.cpp", - "${chip_root}/third_party/simw-top-mini/repo/hostlib/hostLib/platform/rsp/se05x_reset.c", - "${chip_root}/third_party/simw-top-mini/repo/hostlib/hostLib/se05x/src/se05x_ECC_curves.c", - "${chip_root}/third_party/simw-top-mini/repo/hostlib/hostLib/se05x/src/se05x_mw.c", - "${chip_root}/third_party/simw-top-mini/repo/hostlib/hostLib/se05x/src/se05x_tlv.c", - "${chip_root}/third_party/simw-top-mini/repo/hostlib/hostLib/se05x_03_xx_xx/se05x_APDU.c", - "${chip_root}/third_party/simw-top-mini/repo/sss/ex/src/ex_sss_boot.c", - "${chip_root}/third_party/simw-top-mini/repo/sss/ex/src/ex_sss_boot_connectstring.c", - "${chip_root}/third_party/simw-top-mini/repo/sss/ex/src/ex_sss_se05x.c", - "${chip_root}/third_party/simw-top-mini/repo/sss/ex/src/ex_sss_se05x_auth.c", - "${chip_root}/third_party/simw-top-mini/repo/sss/src/fsl_sss_apis.c", - "${chip_root}/third_party/simw-top-mini/repo/sss/src/fsl_sss_util_asn1_der.c", - "${chip_root}/third_party/simw-top-mini/repo/sss/src/fsl_sss_util_rsa_sign_utils.c", - "${chip_root}/third_party/simw-top-mini/repo/sss/src/keystore/keystore_cmn.c", - "${chip_root}/third_party/simw-top-mini/repo/sss/src/keystore/keystore_pc.c", - "${chip_root}/third_party/simw-top-mini/repo/sss/src/mbedtls/fsl_sss_mbedtls_apis.c", - "${chip_root}/third_party/simw-top-mini/repo/sss/src/se05x/fsl_sss_se05x_apis.c", - "${chip_root}/third_party/simw-top-mini/repo/sss/src/se05x/fsl_sss_se05x_mw.c", - "${chip_root}/third_party/simw-top-mini/repo/sss/src/se05x/fsl_sss_se05x_policy.c", + "repo/hostlib/hostLib/libCommon/infra/global_platf.c", + "repo/hostlib/hostLib/libCommon/infra/sm_apdu.c", + "repo/hostlib/hostLib/libCommon/infra/sm_connect.c", + "repo/hostlib/hostLib/libCommon/infra/sm_errors.c", + "repo/hostlib/hostLib/libCommon/infra/sm_printf.c", + "repo/hostlib/hostLib/libCommon/log/nxLog.c", + "repo/hostlib/hostLib/libCommon/smCom/smCom.c", + "repo/hostlib/hostLib/platform/rsp/se05x_reset.c", + "repo/hostlib/hostLib/se05x/src/se05x_ECC_curves.c", + "repo/hostlib/hostLib/se05x/src/se05x_mw.c", + "repo/hostlib/hostLib/se05x/src/se05x_tlv.c", + "repo/hostlib/hostLib/se05x_03_xx_xx/se05x_APDU.c", + "repo/sss/ex/src/ex_sss_boot.c", + "repo/sss/ex/src/ex_sss_boot_connectstring.c", + "repo/sss/ex/src/ex_sss_se05x.c", + "repo/sss/ex/src/ex_sss_se05x_auth.c", + "repo/sss/src/fsl_sss_apis.c", + "repo/sss/src/fsl_sss_util_asn1_der.c", + "repo/sss/src/fsl_sss_util_rsa_sign_utils.c", + "repo/sss/src/keystore/keystore_cmn.c", + "repo/sss/src/keystore/keystore_pc.c", + "repo/sss/src/mbedtls/fsl_sss_mbedtls_apis.c", + "repo/sss/src/se05x/fsl_sss_se05x_apis.c", + "repo/sss/src/se05x/fsl_sss_se05x_mw.c", + "repo/sss/src/se05x/fsl_sss_se05x_policy.c", ] sources += [ - "${chip_root}/third_party/simw-top-mini/repo/hostlib/hostLib/libCommon/smCom/T1oI2C/phNxpEsePal_i2c.c", - "${chip_root}/third_party/simw-top-mini/repo/hostlib/hostLib/libCommon/smCom/T1oI2C/phNxpEseProto7816_3.c", - "${chip_root}/third_party/simw-top-mini/repo/hostlib/hostLib/libCommon/smCom/T1oI2C/phNxpEse_Api.c", - "${chip_root}/third_party/simw-top-mini/repo/hostlib/hostLib/libCommon/smCom/smComT1oI2C.c", + "repo/hostlib/hostLib/libCommon/smCom/T1oI2C/phNxpEsePal_i2c.c", + "repo/hostlib/hostLib/libCommon/smCom/T1oI2C/phNxpEseProto7816_3.c", + "repo/hostlib/hostLib/libCommon/smCom/T1oI2C/phNxpEse_Api.c", + "repo/hostlib/hostLib/libCommon/smCom/smComT1oI2C.c", ] if (chip_device_platform == "k32w0") { sources += [ - "${chip_root}/third_party/simw-top-mini/repo/hostlib/hostLib/platform/ksdk/i2c_dk6.c", - "${chip_root}/third_party/simw-top-mini/repo/hostlib/hostLib/platform/ksdk/timer_kinetis_freertos.c", + "repo/hostlib/hostLib/platform/ksdk/i2c_dk6.c", + "repo/hostlib/hostLib/platform/ksdk/timer_kinetis_freertos.c", ] } else if (chip_device_platform == "linux") { sources += [ - "${chip_root}/third_party/simw-top-mini/repo/hostlib/hostLib/platform/generic/sm_timer.c", - "${chip_root}/third_party/simw-top-mini/repo/hostlib/hostLib/platform/linux/i2c_a7.c", + "repo/hostlib/hostLib/platform/generic/sm_timer.c", + "repo/hostlib/hostLib/platform/linux/i2c_a7.c", ] } - public_deps = [ "${chip_root}/third_party/mbedtls:mbedtls" ] - configs += [ ":se05x_config" ] + public_configs = [ ":se05x_config" ] } diff --git a/third_party/simw-top-mini/repo b/third_party/simw-top-mini/repo index be0dfb64b28dea..2e9189d97010b5 160000 --- a/third_party/simw-top-mini/repo +++ b/third_party/simw-top-mini/repo @@ -1 +1 @@ -Subproject commit be0dfb64b28dea3509425755e3b4b5b35c38d327 +Subproject commit 2e9189d97010b5d9d380d975ee09b7277221f890 diff --git a/third_party/simw-top-mini/simw_config.gni b/third_party/simw-top-mini/simw_config.gni index 2bffa51eaa6c42..d5871fed7c72d9 100644 --- a/third_party/simw-top-mini/simw_config.gni +++ b/third_party/simw-top-mini/simw_config.gni @@ -13,7 +13,3 @@ # limitations under the License. # Configuration file - -declare_args() { - chip_rpi_se05x_t4t_demo = 0 -}