diff --git a/.github/.wordlist.txt b/.github/.wordlist.txt
index f45270454a88a5..543786c1473460 100644
--- a/.github/.wordlist.txt
+++ b/.github/.wordlist.txt
@@ -643,6 +643,8 @@ HomePods
hostapd
hostname
href
+HSM
+hsm
HTTPS
HW
hwadr
@@ -965,6 +967,7 @@ objcopy
OccupancySensing
OctetString
OECORE
+OID
ol
Onboarding
onboardingcodes
@@ -986,6 +989,7 @@ openweave
OperationalCredentials
operationalDataset
opkg
+OPTIGA
optionMask
optionOverride
optionsMask
@@ -1429,6 +1433,7 @@ transitionTime
TransportMgrBase
TriggerEffect
TRNG
+trustm
TrustedRootCertificates
tsan
TSG
diff --git a/.gitmodules b/.gitmodules
index fa3dfcfdaea9aa..03554f83b5aac6 100644
--- a/.gitmodules
+++ b/.gitmodules
@@ -324,3 +324,9 @@
path = third_party/infineon/psoc6/psoc6_sdk/libs/lwip-network-interface-integration
url = https://github.com/Infineon/lwip-network-interface-integration.git
platforms = infineon
+[submodule "third_party/infineon/trustm/optiga-trust-m"]
+ path = third_party/infineon/trustm/optiga-trust-m
+ url = https://github.com/Infineon/optiga-trust-m.git
+ branch = matter_support
+ platforms = infineon
+
diff --git a/docs/guides/README.md b/docs/guides/README.md
index 4f4ddb231f577b..dbdda1bba07de4 100644
--- a/docs/guides/README.md
+++ b/docs/guides/README.md
@@ -7,6 +7,7 @@
- [ASR - Getting Started Guide](./asr_getting_started_guide.md)
- [Espressif (ESP32) - Getting Started Guide](./esp32/README.md)
- [Infineon PSoC6 - Software Update](./infineon_psoc6_software_update.md)
+- [Infineon Trust M Provisioning](./infineon_trustm_provisioning.md)
- [Linux - Simulated Devices](./simulated_device_linux.md)
- [mbedOS - Adding a new target](./mbedos_add_new_target.md)
- [mbedOS - Commissioning](./mbedos_commissioning.md)
diff --git a/docs/guides/infineon_trustm_provisioning.md b/docs/guides/infineon_trustm_provisioning.md
new file mode 100644
index 00000000000000..cd7fe6b14cb8c0
--- /dev/null
+++ b/docs/guides/infineon_trustm_provisioning.md
@@ -0,0 +1,61 @@
+# Infineon OPTIGA™ Trust M Provisioning for Matter
+
+To use Infineon OPTIGA™ Trust M for device attestation, Provisioning for
+OPTIGA™ Trust M with Matter test device Attestation certificate is needed.
+
+## Hardware setup:
+
+[Raspberry Pi 4](https://www.raspberrypi.com/products/raspberry-pi-4-model-b/)
+
+[OPTIGA™ Trust M MTR](https://www.infineon.com/cms/en/product/evaluation-boards/trust-m-mtr-shield/)
+
+[Shield2Go Adapter for Raspberry Pi](https://www.infineon.com/cms/en/product/evaluation-boards/s2go-adapter-rasp-pi-iot/)
+or Jumping Wire
+
+## Provisioning for OPTIGA™ Trust M
+
+The
+[Linux Tools for OPTIGA™ Trust M ](https://github.com/Infineon/linux-optiga-trust-m)
+can be used to perform provisioning by following the steps mentioned below.
+
+- Set up chip-tool on Raspberry Pi 4 by following the instruction listed at
+ [Building chip-tool on Raspberry Pi ](https://github.com/project-chip/connectedhomeip/blob/master/docs/guides/BUILDING.md#installing-prerequisites-on-raspberry-pi-4)
+- Clone the repo from Infineon Public GitHub
+
+```
+ $ git clone --recurse-submodules https://github.com/Infineon/linux-optiga-trust-m.git
+```
+
+- Build the Linux tools for OPTIGA™ Trust M
+
+```
+ $ cd linux-optiga-trust-m/
+ $ ./trustm_installation_aarch64_script.sh
+```
+
+- Run the script to generate Matter test DAC for lock-app using the public key
+ extracted from the Infineon pre-provisioned Certificate and store it into
+ 0xE0E0
+
+```
+$ cd scripts/matter_provisioning/
+$ ./matter_dac_provisioning.sh
+```
+
+_Note:_
+
+_By running this example matter_dac_provisioning.sh, the steps shown below are
+executed:_
+
+_Step1: Extract the public key from the Infineon pre-provisioned
+Certificate(0xE0E0) using openssl command._
+
+_Step2: Generate DAC test certificate using the extracted public key, Signed by
+[Matter test PAI](https://github.com/project-chip/connectedhomeip/blob/v1.1-branch/credentials/development/attestation/Matter-Development-PAI-FFF1-noPID-Cert.pem)_.
+Please note that production devices cannot re-use these test keys/certificates.
+
+_Step3: Write DAC test certificate into OPTIGA™ Trust M certificate slot
+0xE0E0_
+
+_Step4: Write Matter test PAI into OPTIGA™ Trust M certificate slot 0xE0E8
+and test CD into OPTIGA™ Trust M Arbitrary OID 0xF1E0.
diff --git a/examples/lock-app/infineon/psoc6/BUILD.gn b/examples/lock-app/infineon/psoc6/BUILD.gn
index b575a7517cd4e9..6714fc03ef9af8 100644
--- a/examples/lock-app/infineon/psoc6/BUILD.gn
+++ b/examples/lock-app/infineon/psoc6/BUILD.gn
@@ -15,9 +15,11 @@
import("//build_overrides/build.gni")
import("//build_overrides/chip.gni")
import("//build_overrides/psoc6.gni")
-
import("${build_root}/config/defaults.gni")
+import("${chip_root}/src/crypto/crypto.gni")
+import("${chip_root}/src/platform/Infineon/crypto/infineon_crypto.gni")
import("${chip_root}/src/platform/device.gni")
+import("${chip_root}/third_party/infineon/trustm/trustm_config.gni")
import("${psoc6_sdk_build_root}/psoc6_executable.gni")
import("${psoc6_sdk_build_root}/psoc6_sdk.gni")
@@ -117,6 +119,19 @@ psoc6_executable("lock_app") {
"${psoc6_project_dir}/include",
]
+ if (chip_crypto == "platform") {
+ include_dirs += [ "${chip_root}/third_party/infineon/trustm" ]
+ include_dirs += [ "${chip_root}/examples/platform/infineon/trustm" ]
+ include_dirs += [ "${chip_root}/src/platform/Infineon/crypto/trustm" ]
+
+ defines = [ "ENABLE_DEVICE_ATTESTATION=1" ]
+
+ public_deps += [
+ "${chip_root}/src/platform/Infineon/crypto/${infineon_crypto_impl}:infineon_crypto_lib",
+ "${chip_root}/third_party/infineon/trustm:optiga-trust-m",
+ ]
+ }
+
sources = [
"${examples_plat_dir}/LEDWidget.cpp",
"${examples_plat_dir}/init_psoc6Platform.cpp",
diff --git a/examples/lock-app/infineon/psoc6/README.md b/examples/lock-app/infineon/psoc6/README.md
index 7adc1b9b41b481..e205d3d22bc440 100644
--- a/examples/lock-app/infineon/psoc6/README.md
+++ b/examples/lock-app/infineon/psoc6/README.md
@@ -14,6 +14,8 @@ An example showing the use of Matter on the Infineon CY8CKIT-062S2-43012 board.
- [Notes](#notes)
- [Cluster control](#cluster-control)
- [Factory Reset](#factory-reset)
+ - [Building with OPTIGA™ Trust M as HSM](#build-trustm-hsm)
+ - [OPTIGA™ Trust M Provisioning](#provisioning-trustm)
- [OTA Software Update](#ota-software-update)
@@ -55,6 +57,10 @@ will then join the network.
$ cd ~/connectedhomeip
$ rm -rf out/
+_To build with Infineon Hardware Security Module-OPTIGA™ Trust M for Device
+attestation and other security use cases, please refer to the
+[Building with OPTIGA™ Trust M as HSM](#build-trustm-hsm) for more instructions_
+
## Flashing the Application
- Put CY8CKIT-062S2-43012 board on KitProg3 CMSIS-DAP Mode by pressing the
@@ -128,10 +134,52 @@ commands. These power cycle the BlueTooth hardware and disable BR/EDR mode.
on the board. All the data configured on the device during the initial
commissioning will be deleted and device will be ready for commissioning
again.
-
- Pressing the button again within 5 seconds will cancel the factory reset of
the board.
+##
+
+## Building with OPTIGA™ Trust M as HSM
+
+Infineon Hardware Security Module-OPTIGA™ Trust M is a high-end security
+solution that provides an anchor of trust for connecting IoT devices to the
+cloud, giving every IoT device its own unique identity.
+
+- Supported hardware setup:
+ [CY8CKIT-062S2-43012](https://www.cypress.com/CY8CKIT-062S2-43012)
+
+ [OPTIGA™ Trust M MTR](https://www.infineon.com/cms/en/product/evaluation-boards/trust-m-mtr-shield/)
+
+ [OPTIGA™ Trust Adapter](https://www.infineon.com/cms/en/product/evaluation-boards/optiga-trust-adapter/)
+
+- Building
+
+ Follow the steps to build with OPTIGA™ Trust M for device attestation use case:
+
+ ```
+ $ source scripts/activate.sh
+ $ scripts/build/build_examples.py --no-log-timestamps --target 'infineon-psoc6-lock-trustm' build
+ ```
+- To delete generated executable, libraries and object files use:
+
+ $ cd ~/connectedhomeip
+ $ rm -rf out/
+
+- Proceed to OPTIGA™ Trust M Provisioning section to complete the credential
+ storage into HSM.
+
+###
+
+### OPTIGA™ Trust M Provisioning
+
+For the description of OPTIGA™ Trust M Provisioning with test DAC generation and
+PAI and CD storage, please refer to
+[Infineon OPTIGA™ Trust M Provisioning](../../../../docs/guides/infineon_trustm_provisioning.md)
+
+After completing OPTIGA™ Trust M Provisioning, proceed to
+[Flashing the Application](#flashing-the-application) section to continue with
+subsequent steps.
+
## OTA Software Update
For the description of Software Update process with infineon PSoC6 example
diff --git a/examples/lock-app/infineon/psoc6/args.gni b/examples/lock-app/infineon/psoc6/args.gni
index b65d0d8885e25d..cb8fec6c390fe9 100644
--- a/examples/lock-app/infineon/psoc6/args.gni
+++ b/examples/lock-app/infineon/psoc6/args.gni
@@ -15,7 +15,10 @@
import("//build_overrides/chip.gni")
import("//build_overrides/pigweed.gni")
import("${chip_root}/config/standalone/args.gni")
+import("${chip_root}/src/crypto/crypto.gni")
import("${chip_root}/src/platform/Infineon/PSOC6/args.gni")
psoc6_target_project =
get_label_info(":lock_app_sdk_sources", "label_no_toolchain")
+
+import("${chip_root}/src/platform/Infineon/crypto/trustm/args.gni")
diff --git a/examples/lock-app/infineon/psoc6/src/AppTask.cpp b/examples/lock-app/infineon/psoc6/src/AppTask.cpp
index 9f29e32e6c618a..106da8eecbf69f 100644
--- a/examples/lock-app/infineon/psoc6/src/AppTask.cpp
+++ b/examples/lock-app/infineon/psoc6/src/AppTask.cpp
@@ -45,6 +45,10 @@
#include
#include
+#if ENABLE_DEVICE_ATTESTATION
+#include
+#endif
+
/* OTA related includes */
#if CHIP_DEVICE_CONFIG_ENABLE_OTA_REQUESTOR
#include
@@ -157,7 +161,12 @@ static void InitServer(intptr_t context)
chip::DeviceLayer::SetDeviceInfoProvider(&gExampleDeviceInfoProvider);
// Initialize device attestation config
+#if ENABLE_DEVICE_ATTESTATION
+ SetDeviceAttestationCredentialsProvider(Examples::GetExampleTrustMDACProvider());
+#else
SetDeviceAttestationCredentialsProvider(Examples::GetExampleDACProvider());
+#endif
+
#if CHIP_DEVICE_CONFIG_ENABLE_OTA_REQUESTOR
GetAppTask().InitOTARequestor();
#endif
diff --git a/scripts/build/build/targets.py b/scripts/build/build/targets.py
index e2ec1f22bb30df..2c3d2b95232474 100755
--- a/scripts/build/build/targets.py
+++ b/scripts/build/build/targets.py
@@ -409,6 +409,7 @@ def BuildInfineonTarget():
# modifiers
target.AppendModifier('ota', enable_ota_requestor=True)
target.AppendModifier('updateimage', update_image=True)
+ target.AppendModifier('trustm', enable_trustm=True)
return target
diff --git a/scripts/build/builders/infineon.py b/scripts/build/builders/infineon.py
index 7237f0625cc92e..8983bed475c488 100644
--- a/scripts/build/builders/infineon.py
+++ b/scripts/build/builders/infineon.py
@@ -80,7 +80,8 @@ def __init__(self,
app: InfineonApp = InfineonApp.LOCK,
board: InfineonBoard = InfineonBoard.PSOC6BOARD,
enable_ota_requestor: bool = False,
- update_image: bool = False):
+ update_image: bool = False,
+ enable_trustm: bool = False):
super(InfineonBuilder, self).__init__(
root=app.BuildRoot(root),
runner=runner)
@@ -92,7 +93,10 @@ def __init__(self,
self.extra_gn_options.append('chip_enable_ota_requestor=true')
if update_image:
self.extra_gn_options.append('build_update_image=true')
-
+ if enable_trustm:
+ self.extra_gn_options.append('chip_crypto=\"platform\"')
+ if enable_trustm is False:
+ self.extra_gn_options.append('chip_crypto=\"mbedtls\"')
def GnBuildArgs(self):
return self.extra_gn_options
diff --git a/scripts/build/testdata/all_targets_linux_x64.txt b/scripts/build/testdata/all_targets_linux_x64.txt
index cba8fe6534b96f..f258645fcbe554 100644
--- a/scripts/build/testdata/all_targets_linux_x64.txt
+++ b/scripts/build/testdata/all_targets_linux_x64.txt
@@ -13,7 +13,7 @@ linux-fake-tests[-mbedtls][-boringssl][-asan][-tsan][-ubsan][-libfuzzer][-ossfuz
linux-{x64,arm64}-{rpc-console,all-clusters,all-clusters-minimal,chip-tool,thermostat,java-matter-controller,kotlin-matter-controller,minmdns,light,lock,shell,ota-provider,ota-requestor,simulated-app1,simulated-app2,python-bindings,tv-app,tv-casting-app,bridge,tests,chip-cert,address-resolve-tool,contact-sensor,dishwasher,microwave-oven,refrigerator,rvc,air-purifier,lit-icd,air-quality-sensor,network-manager,energy-management}[-nodeps][-nlfaultinject][-platform-mdns][-minmdns-verbose][-libnl][-same-event-loop][-no-interactive][-ipv6only][-no-ble][-no-wifi][-no-thread][-mbedtls][-boringssl][-asan][-tsan][-ubsan][-libfuzzer][-ossfuzz][-coverage][-dmalloc][-clang][-test][-rpc][-with-ui][-evse-test-event]
linux-x64-efr32-test-runner[-clang]
imx-{chip-tool,lighting-app,thermostat,all-clusters-app,all-clusters-minimal-app,ota-provider-app}[-release]
-infineon-psoc6-{lock,light,all-clusters,all-clusters-minimal}[-ota][-updateimage]
+infineon-psoc6-{lock,light,all-clusters,all-clusters-minimal}[-ota][-updateimage][-trustm]
rw61x-{all-clusters-app,thermostat,laundry-washer}[-ota][-wifi][-thread][-factory-data][-matter-shell]
nxp-{k32w0,k32w1}-{lighting,contact-sensor}[-factory][-low-power][-lit][-fro32k][-smu2][-dac-conversion][-rotating-id][-sw-v2]
mbed-cy8cproto_062_4343w-{lock,light,all-clusters,all-clusters-minimal,pigweed,ota-requestor,shell}[-release][-develop][-debug]
diff --git a/src/crypto/crypto.gni b/src/crypto/crypto.gni
index 4fc63b800826b8..9e019bc767b466 100644
--- a/src/crypto/crypto.gni
+++ b/src/crypto/crypto.gni
@@ -16,7 +16,7 @@ declare_args() {
# Crypto implementation: mbedtls, openssl, boringssl, platform.
chip_crypto = ""
chip_with_se05x = 0
-
+
# Compile mbedtls externally. Only used if chip_crypto == "mbedtls"
chip_external_mbedtls = false
}
diff --git a/src/platform/Infineon/crypto/infineon_crypto.gni b/src/platform/Infineon/crypto/infineon_crypto.gni
new file mode 100644
index 00000000000000..cae4709c0f0610
--- /dev/null
+++ b/src/platform/Infineon/crypto/infineon_crypto.gni
@@ -0,0 +1,20 @@
+# Copyright (c) 2024 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() {
+ infineon_crypto_impl = ""
+ infineon_crypto_root = ""
+}
+assert(infineon_crypto_impl != "", "infineon_crypto_impl should be defined")
+assert(infineon_crypto_root != "", "infineon_crypto_root should be defined")
diff --git a/src/platform/Infineon/crypto/trustm/BUILD.gn b/src/platform/Infineon/crypto/trustm/BUILD.gn
new file mode 100644
index 00000000000000..a0df672b4e8c46
--- /dev/null
+++ b/src/platform/Infineon/crypto/trustm/BUILD.gn
@@ -0,0 +1,68 @@
+# Copyright (c) 2024 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/Infineon/crypto/trustm/args.gni")
+
+if (chip_crypto == "platform") {
+ import("//build_overrides/mbedtls.gni")
+}
+
+source_set("public_headers") {
+ sources = [
+ ]
+
+ public_deps = [
+ "${chip_root}/src/lib/asn1",
+ "${chip_root}/src/lib/core",
+ "${chip_root}/src/lib/support",
+ "${nlassert_root}:nlassert",
+ "${chip_root}/src/crypto",
+
+ ]
+}
+
+static_library("infineon_crypto_lib") {
+ sources = [
+ "CHIPCryptoPAL_HostFallBack.cpp",
+ "CHIPCryptoPALHost.cpp",
+ "CHIPCryptoPALHsm_HKDF_trustm.cpp",
+ "CHIPCryptoPALHsm_HMAC_trustm.cpp",
+ "CHIPCryptoPALHsm_P256_trustm.cpp",
+ "CHIPCryptoPALHsm_rng_trustm.cpp",
+ "CHIPCryptoPALHsm_utils_trustm.cpp",
+ "DeviceAttestationCredsExampleTrustM.cpp",
+ ]
+
+ public_deps = [ ":public_headers" ]
+ public_configs = []
+ public_deps += [ "${chip_root}/third_party/infineon/trustm:optiga-trust-m" ]
+ public_configs +=
+ [ "${chip_root}/third_party/infineon/trustm:trustm_config" ]
+ deps = [ "${chip_root}/${infineon_crypto_root}:optiga-trust-m" ]
+ external_mbedtls = current_os == "zephyr"
+
+ if (!external_mbedtls) {
+ public_deps += [ "${mbedtls_root}:mbedtls" ]
+ }
+ include_dirs = [
+ ".",
+ "${chip_root}/src/crypto",
+ "${chip_root}/src/platform/Infineon/crypto/trustm",
+ ]
+
+}
diff --git a/src/platform/Infineon/crypto/trustm/CHIPCryptoPALHost.cpp b/src/platform/Infineon/crypto/trustm/CHIPCryptoPALHost.cpp
new file mode 100644
index 00000000000000..cdf8491afc8779
--- /dev/null
+++ b/src/platform/Infineon/crypto/trustm/CHIPCryptoPALHost.cpp
@@ -0,0 +1,1478 @@
+/*
+ *
+ * Copyright (c) 2020-2024 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 mbedtls_ccm_context ccm_context;
+
+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_init(&ccm_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(&ccm_context, MBEDTLS_CIPHER_ID_AES, key.As(), sizeof(Symmetric128BitsKeyByteArray) * 8);
+ VerifyOrExit(result == 0, error = CHIP_ERROR_INTERNAL);
+
+ // Encrypt
+ result = mbedtls_ccm_encrypt_and_tag(&ccm_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(&ccm_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_init(&ccm_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(&ccm_context, MBEDTLS_CIPHER_ID_AES, key.As(), sizeof(Symmetric128BitsKeyByteArray) * 8);
+ VerifyOrExit(result == 0, error = CHIP_ERROR_INTERNAL);
+
+ // Decrypt
+ result = mbedtls_ccm_auth_decrypt(&ccm_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(&ccm_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 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 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));
+}
+
+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)
+{
+ CHIP_ERROR error = CHIP_NO_ERROR;
+ int result = 0;
+#if !defined(MBEDTLS_DEPRECATED_REMOVED) || MBEDTLS_VERSION_NUMBER < 0x03030000
+ const mbedtls_md_info_t * md_info;
+ mbedtls_md_context_t md_ctxt;
+ constexpr int use_hmac = 1;
+ bool free_md_ctxt = false;
+#endif // !defined(MBEDTLS_DEPRECATED_REMOVED) || MBEDTLS_VERSION_NUMBER < 0x03030000
+
+ 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);
+#if !defined(MBEDTLS_DEPRECATED_REMOVED) || MBEDTLS_VERSION_NUMBER < 0x03030000
+ 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));
+#else
+ result = mbedtls_pkcs5_pbkdf2_hmac_ext(MBEDTLS_MD_SHA256, Uint8::to_const_uchar(password), plen, Uint8::to_const_uchar(salt),
+ slen, iteration_count, key_length, Uint8::to_uchar(output));
+#endif // !defined(MBEDTLS_DEPRECATED_REMOVED) || MBEDTLS_VERSION_NUMBER < 0x03030000
+ VerifyOrExit(result == 0, error = CHIP_ERROR_INTERNAL);
+
+exit:
+ _log_mbedTLS_error(result);
+#if !defined(MBEDTLS_DEPRECATED_REMOVED) || MBEDTLS_VERSION_NUMBER < 0x03030000
+ if (free_md_ctxt)
+ {
+ mbedtls_md_free(&md_ctxt);
+ }
+#endif // !defined(MBEDTLS_DEPRECATED_REMOVED) || MBEDTLS_VERSION_NUMBER < 0x03030000
+
+ return error;
+}
+
+static EntropyContext * get_entropy_context()
+{
+ if (!gsEntropyContext.mInitialized)
+ {
+ mbedtls_entropy_init(&gsEntropyContext.mEntropy);
+ mbedtls_ctr_drbg_init(&gsEntropyContext.mDRBGCtxt);
+
+ gsEntropyContext.mInitialized = true;
+ }
+
+ return &gsEntropyContext;
+}
+
+static mbedtls_ctr_drbg_context * get_drbg_context()
+{
+ EntropyContext * const context = get_entropy_context();
+
+ mbedtls_ctr_drbg_context * const drbgCtxt = &context->mDRBGCtxt;
+
+ if (!context->mDRBGSeeded)
+ {
+ const int status = mbedtls_ctr_drbg_seed(drbgCtxt, mbedtls_entropy_func, &context->mEntropy, nullptr, 0);
+ if (status != 0)
+ {
+ _log_mbedTLS_error(status);
+ return nullptr;
+ }
+
+ context->mDRBGSeeded = true;
+ }
+
+ return drbgCtxt;
+}
+
+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;
+}
+
+CHIP_ERROR DRBG_get_bytes(uint8_t * out_buffer, const size_t out_length)
+{
+ VerifyOrReturnError(out_buffer != nullptr, CHIP_ERROR_INVALID_ARGUMENT);
+ VerifyOrReturnError(out_length > 0, CHIP_ERROR_INVALID_ARGUMENT);
+
+ mbedtls_ctr_drbg_context * const drbg_ctxt = get_drbg_context();
+ VerifyOrReturnError(drbg_ctxt != nullptr, CHIP_ERROR_INTERNAL);
+
+ const int result = mbedtls_ctr_drbg_random(drbg_ctxt, Uint8::to_uchar(out_buffer), out_length);
+ 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/Infineon/crypto/trustm/CHIPCryptoPALHsm_HKDF_trustm.cpp b/src/platform/Infineon/crypto/trustm/CHIPCryptoPALHsm_HKDF_trustm.cpp
new file mode 100644
index 00000000000000..957630bd03da4a
--- /dev/null
+++ b/src/platform/Infineon/crypto/trustm/CHIPCryptoPALHsm_HKDF_trustm.cpp
@@ -0,0 +1,105 @@
+/*
+ *
+ * Copyright (c) 2024 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_utils_trustm.h"
+#include "optiga/optiga_util.h"
+#include "optiga_crypt.h"
+#include "optiga_lib_types.h"
+#include
+
+static const uint8_t metadata[] = {
+ // Metadata tag in the data object
+ 0x20,
+ 0x06,
+ // Data object type set to PRESSEC
+ 0xE8,
+ 0x01,
+ 0x21,
+ 0xD3,
+ 0x01,
+ 0x00,
+};
+
+namespace chip {
+namespace Crypto {
+
+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_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)
+{
+#if !ENABLE_TRUSTM_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;
+ optiga_lib_status_t return_status = OPTIGA_LIB_BUSY;
+
+ uint16_t salt_length_u16 = static_cast(salt_length);
+ uint16_t info_length_u16 = static_cast(info_length);
+ uint16_t out_length_u16 = static_cast(out_length);
+ uint16_t secret_length_u16 = static_cast(secret_length);
+
+ if (salt_length > 64 || info_length > 80 || secret_length > 256 || out_length > 768)
+ {
+ /* Length not supported by trustm. Rollback to SW */
+ return HKDF_SHA256_H(secret, secret_length, salt, salt_length, info, info_length, out_buffer, out_length);
+ }
+
+ // 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);
+ VerifyOrReturnError(secret != nullptr, CHIP_ERROR_INVALID_ARGUMENT);
+
+ // Trust M init
+ trustm_Open();
+ // Write metada(Done during provisioning)
+ // write_metadata(TRUSTM_HKDF_OID_KEY, metadata, sizeof(metadata));
+ // Write the secret key
+ write_data(TRUSTM_HKDF_OID_KEY, secret, secret_length_u16);
+
+ return_status = OPTIGA_LIB_BUSY;
+
+ return_status = deriveKey_HKDF(salt, salt_length_u16, info, info_length_u16, out_length_u16, TRUE, out_buffer);
+
+ VerifyOrExit(return_status == OPTIGA_LIB_SUCCESS, error = CHIP_ERROR_INTERNAL);
+ error = CHIP_NO_ERROR;
+
+exit:
+ if (error != CHIP_NO_ERROR)
+ {
+ trustm_close();
+ }
+ return error;
+#endif
+}
+} // namespace Crypto
+} // namespace chip
diff --git a/src/platform/Infineon/crypto/trustm/CHIPCryptoPALHsm_HMAC_trustm.cpp b/src/platform/Infineon/crypto/trustm/CHIPCryptoPALHsm_HMAC_trustm.cpp
new file mode 100644
index 00000000000000..cf8ba2e43cd08f
--- /dev/null
+++ b/src/platform/Infineon/crypto/trustm/CHIPCryptoPALHsm_HMAC_trustm.cpp
@@ -0,0 +1,108 @@
+/*
+ *
+ * Copyright (c) 2024 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_utils_trustm.h"
+#include "optiga/optiga_util.h"
+#include "optiga_crypt.h"
+#include "optiga_lib_types.h"
+#include
+
+static const uint8_t metadata_hmac[] = {
+ // Metadata tag in the data object
+ 0x20,
+ 0x06,
+ // Data object type set to PRESSEC
+ 0xE8,
+ 0x01,
+ 0x21,
+ 0xD3,
+ 0x01,
+ 0x00,
+};
+
+namespace chip {
+namespace Crypto {
+
+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_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_TRUSTM_HMAC_SHA256
+ return HMAC_SHA256_h(key, key_length, message, message_length, out_buffer, out_length);
+#else
+ CHIP_ERROR error = CHIP_ERROR_INTERNAL;
+ optiga_lib_status_t return_status = OPTIGA_LIB_BUSY;
+
+ uint16_t key_length_u16 = static_cast(key_length);
+ uint32_t message_length_u32 = static_cast(message_length);
+ uint32_t out_length_u32 = static_cast(out_length);
+
+ if (key_length > 64)
+ {
+ return HMAC_sha::HMAC_SHA256_h(key, key_length, message, message_length, out_buffer, out_length);
+ }
+ 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 > 0, CHIP_ERROR_INVALID_ARGUMENT);
+ VerifyOrReturnError(out_buffer != nullptr, CHIP_ERROR_INVALID_ARGUMENT);
+ VerifyOrReturnError(key != nullptr, CHIP_ERROR_INVALID_ARGUMENT);
+
+ // Trust M init
+ trustm_Open();
+ // Write metada for secret OID(Done during Provisioning)
+ //write_metadata(TRUSTM_HMAC_OID_KEY, metadata_hmac, sizeof(metadata_hmac));
+ // Update the secret key
+ write_data(TRUSTM_HMAC_OID_KEY, key, key_length_u16);
+
+ // Start HMAC operation
+ return_status = OPTIGA_LIB_BUSY;
+
+ // What is the max length supported ?
+ return_status = hmac_sha256(OPTIGA_HMAC_SHA_256, message, message_length_u32, out_buffer, &out_length_u32);
+
+ VerifyOrExit(return_status == OPTIGA_LIB_SUCCESS, error = CHIP_ERROR_INTERNAL);
+ error = CHIP_NO_ERROR;
+
+exit:
+ if (error != CHIP_NO_ERROR)
+ {
+ trustm_close();
+ }
+ return error;
+#endif
+}
+
+CHIP_ERROR HMAC_sha::HMAC_SHA256(const Hmac128KeyHandle & key, const uint8_t * message, size_t message_length, uint8_t * out_buffer,
+ size_t out_length)
+{
+ return HMAC_SHA256(key.As(), sizeof(Symmetric128BitsKeyByteArray), message, message_length,
+ out_buffer, out_length);
+}
+
+} // namespace Crypto
+} // namespace chip
diff --git a/src/platform/Infineon/crypto/trustm/CHIPCryptoPALHsm_P256_trustm.cpp b/src/platform/Infineon/crypto/trustm/CHIPCryptoPALHsm_P256_trustm.cpp
new file mode 100644
index 00000000000000..92ba0b839d2073
--- /dev/null
+++ b/src/platform/Infineon/crypto/trustm/CHIPCryptoPALHsm_P256_trustm.cpp
@@ -0,0 +1,601 @@
+/*
+ *
+ * Copyright (c) 2024 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_utils_trustm.h"
+#include "optiga/optiga_util.h"
+#include "optiga_crypt.h"
+#include "optiga_lib_common.h"
+#include "optiga_lib_types.h"
+#include
+
+#define NIST256_HEADER_OFFSET 26
+#define CRYPTO_KEYPAIR_KEYID_OFFSET 4
+
+/* Used for CSR generation */
+// Organisation info.
+#define SUBJECT_STR "CSR"
+#define ASN1_BIT_STRING 0x03
+#define ASN1_NULL 0x05
+#define ASN1_OID 0x06
+#define ASN1_SEQUENCE 0x10
+#define ASN1_SET 0x11
+#define ASN1_UTF8_STRING 0x0C
+#define ASN1_CONSTRUCTED 0x20
+#define ASN1_CONTEXT_SPECIFIC 0x80
+
+const uint8_t kTlvHeader = 2;
+
+// Define keyid
+uint32_t keyid =0;
+namespace chip {
+namespace Crypto {
+
+#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, \
+ }
+
+#define NIST256_HEADER_LENGTH (26)
+
+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_TRUSTM_GENERATE_EC_KEY || ENABLE_TRUSTM_ECDSA_VERIFY)
+static CHIP_ERROR get_trustm_keyid_from_keypair(const P256KeypairContext mKeypair, uint32_t * key_id)
+{
+ if (0 != memcmp(&mKeypair.mBytes[0], trustm_magic_no, sizeof(trustm_magic_no)))
+ {
+ return CHIP_ERROR_INTERNAL;
+ }
+
+ *key_id += (mKeypair.mBytes[CRYPTO_KEYPAIR_KEYID_OFFSET]) | (mKeypair.mBytes[CRYPTO_KEYPAIR_KEYID_OFFSET + 1] << 8 );
+
+ return CHIP_NO_ERROR;
+}
+#endif //#if (ENABLE_TRUSTM_GENERATE_EC_KEY || ENABLE_TRUSTM_ECDSA_VERIFY)
+
+P256Keypair::~P256Keypair()
+{
+ // Add method to get the keyid
+ if (CHIP_NO_ERROR != get_trustm_keyid_from_keypair(mKeypair, &keyid))
+ {
+ Clear();
+ }
+ else
+ {
+ // Delete the key in SE
+ }
+}
+
+
+CHIP_ERROR P256Keypair::Initialize(ECPKeyTarget key_target)
+{
+ CHIP_ERROR error = CHIP_ERROR_INTERNAL;
+
+#if !ENABLE_TRUSTM_GENERATE_EC_KEY
+ if (CHIP_NO_ERROR == Initialize_H(this, &mPublicKey, &mKeypair))
+ {
+ mInitialized = true;
+ }
+ error = CHIP_NO_ERROR;
+ return error;
+#else
+ uint8_t pubkey[128] = {
+ 0,
+ };
+ uint16_t pubKeyLen = sizeof(pubkey);
+ optiga_lib_status_t return_status = OPTIGA_LIB_BUSY;
+ P256PublicKey & public_key = const_cast(Pubkey());
+ optiga_key_usage_t key_usage;
+ uint16_t keyid;
+
+ if (key_target == ECPKeyTarget::ECDH) {
+ keyid = TRUSTM_ECDH_OID_KEY;
+
+ // Trust M ECC 256 Key Gen
+ ChipLogDetail(Crypto, "Generating NIST256 key in TrustM for ECDH!");
+ key_usage = OPTIGA_KEY_USAGE_KEY_AGREEMENT;
+ } else {
+ // Add the logic to use different keyid
+ keyid = TRUSTM_NODE_OID_KEY_START;
+ // Trust M ECC 256 Key Gen
+ ChipLogDetail(Crypto, "Generating NIST256 key in TrustM !");
+ key_usage = (optiga_key_usage_t)(OPTIGA_KEY_USAGE_SIGN | OPTIGA_KEY_USAGE_AUTHENTICATION);
+ }
+ // Trust M init
+ trustm_Open();
+ return_status = trustm_ecc_keygen(keyid, key_usage, OPTIGA_ECC_CURVE_NIST_P_256, pubkey, &pubKeyLen);
+
+ // Add signature length
+ VerifyOrExit(return_status == OPTIGA_LIB_SUCCESS, error = CHIP_ERROR_INTERNAL);
+
+ /* Set the public key */
+ VerifyOrReturnError((size_t) pubKeyLen > NIST256_HEADER_OFFSET, CHIP_ERROR_INTERNAL);
+ VerifyOrReturnError(((size_t) 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], trustm_magic_no, sizeof(trustm_magic_no));
+ mKeypair.mBytes[CRYPTO_KEYPAIR_KEYID_OFFSET] = (keyid >> (0 * 8)) & 0xFF;
+ mKeypair.mBytes[CRYPTO_KEYPAIR_KEYID_OFFSET + 1] = (keyid >> (1 * 8)) & 0xFF;
+
+ mInitialized = true;
+ error = CHIP_NO_ERROR;
+
+exit:
+ if (error != CHIP_NO_ERROR)
+ {
+ trustm_close();
+ }
+ return error;
+#endif
+}
+
+CHIP_ERROR P256Keypair::ECDSA_sign_msg(const uint8_t * msg, size_t msg_length, P256ECDSASignature & out_signature) const
+{
+#if !ENABLE_TRUSTM_GENERATE_EC_KEY
+ return ECDSA_sign_msg_H(&mKeypair, msg, msg_length, out_signature);
+#else
+ CHIP_ERROR error = CHIP_ERROR_INTERNAL;
+ optiga_lib_status_t return_status = OPTIGA_LIB_BUSY;
+
+ uint8_t signature_trustm[kMax_ECDSA_Signature_Length_Der] = { 0 };
+ uint16_t signature_trustm_len = (uint16_t) kMax_ECDSA_Signature_Length_Der;
+ uint8_t digest[32];
+ uint8_t digest_length = sizeof(digest);
+
+ memset(&digest[0], 0, sizeof(digest));
+ 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);
+ ChipLogDetail(Crypto, "ECDSA_sign_msg: Using TrustM for ecdsa sign!");
+ // Trust M Init
+ trustm_Open();
+ // Hash to get the digest
+ Hash_SHA256(msg, msg_length, &digest[0]);
+ uint16_t keyid = (mKeypair.mBytes[CRYPTO_KEYPAIR_KEYID_OFFSET]) | (mKeypair.mBytes[CRYPTO_KEYPAIR_KEYID_OFFSET+1] << 8);
+ // Api call to calculate the signature
+ if (keyid == OPTIGA_KEY_ID_E0F2) {
+ return_status = trustm_ecdsa_sign(OPTIGA_KEY_ID_E0F2, digest, digest_length, signature_trustm, &signature_trustm_len);
+ } else {
+ return_status = trustm_ecdsa_sign(OPTIGA_KEY_ID_E0F0, digest, digest_length, signature_trustm, &signature_trustm_len);
+ }
+
+ VerifyOrExit(return_status == OPTIGA_LIB_SUCCESS, error = CHIP_ERROR_INTERNAL);
+
+ error = EcdsaAsn1SignatureToRaw(kP256_FE_Length, ByteSpan{ signature_trustm, signature_trustm_len }, out_raw_sig_span);
+
+ // ChipLogError(NotSpecified, "EcdsaAsn1SignatureToRaw %" CHIP_ERROR_FORMAT, error.Format());
+
+ SuccessOrExit(error);
+
+ SuccessOrExit(out_signature.SetLength(2 * kP256_FE_Length));
+
+ error = CHIP_NO_ERROR;
+
+exit:
+ if (error != CHIP_NO_ERROR)
+ {
+ trustm_close();
+ }
+ return error;
+#endif
+}
+
+CHIP_ERROR P256Keypair::ECDH_derive_secret(const P256PublicKey & remote_public_key, P256ECDHDerivedSecret & out_secret) const
+{
+#if !ENABLE_TRUSTM_GENERATE_EC_KEY
+ return ECDH_derive_secret_H(&mKeypair, remote_public_key, out_secret);
+#else
+ CHIP_ERROR error = CHIP_ERROR_INTERNAL;
+ optiga_lib_status_t return_status = OPTIGA_LIB_BUSY;
+ size_t secret_length = (out_secret.Length() == 0) ? out_secret.Capacity() : out_secret.Length();
+ uint32_t keyid = 0;
+ if (CHIP_NO_ERROR != get_trustm_keyid_from_keypair(mKeypair, &keyid))
+ {
+ ChipLogDetail(Crypto, "ECDH_derive_secret : Using Host for ECDH");
+ return ECDH_derive_secret_H(&mKeypair, remote_public_key, out_secret);
+ }
+
+ ChipLogDetail(Crypto, "ECDH_derive_secret: Using TrustM for ECDH !");
+ trustm_Open();
+
+ const uint8_t * const rem_pubKey = Uint8::to_const_uchar(remote_public_key);
+ const size_t rem_pubKeyLen = remote_public_key.Length();
+
+ uint8_t remote_key[68];
+ uint8_t header[3] = {0x03, 0x42, 0x00};
+
+ memcpy(remote_key, &header, 3);
+ memcpy(remote_key+3, rem_pubKey, rem_pubKeyLen);
+
+ return_status = trustm_ecdh_derive_secret(OPTIGA_KEY_ID_E100, (uint8_t*)remote_key, (uint16_t)rem_pubKeyLen+3,
+ out_secret.Bytes(), (uint8_t)secret_length);
+
+ VerifyOrExit(return_status == OPTIGA_LIB_SUCCESS, error = CHIP_ERROR_INTERNAL) ;
+
+ exit:
+ if (error != CHIP_NO_ERROR)
+ {
+ trustm_close();
+ }
+ return out_secret.SetLength(secret_length);
+#endif
+}
+
+CHIP_ERROR P256PublicKey::ECDSA_validate_hash_signature(const uint8_t * hash, size_t hash_length,
+ const P256ECDSASignature & signature) const
+{
+#if !ENABLE_TRUSTM_ECDSA_VERIFY
+ return ECDSA_validate_hash_signature_H(this, hash, hash_length, signature);
+#else
+ CHIP_ERROR error = CHIP_ERROR_INTERNAL;
+ optiga_lib_status_t return_status = OPTIGA_LIB_BUSY;
+ uint8_t signature_trustm[kMax_ECDSA_Signature_Length_Der] = { 0 };
+ size_t signature_trustm_len = sizeof(signature_trustm);
+ MutableByteSpan out_der_sig_span(signature_trustm, signature_trustm_len);
+
+ uint8_t hash_length_u8 = static_cast(hash_length);
+ uint16_t signature_trustm_len_u16 = static_cast(signature_trustm_len);
+
+ VerifyOrReturnError(hash != nullptr, CHIP_ERROR_INVALID_ARGUMENT);
+ VerifyOrReturnError(hash_length > 0, CHIP_ERROR_INVALID_ARGUMENT);
+ ChipLogDetail(Crypto, "ECDSA_validate_hash_signature: Using TrustM for TrustM verify (hash) !");
+
+ // Trust M init
+ trustm_Open();
+ error = EcdsaRawSignatureToAsn1(kP256_FE_Length, ByteSpan{ Uint8::to_const_uchar(signature.ConstBytes()), signature.Length() },
+ out_der_sig_span);
+ SuccessOrExit(error);
+
+ /* Set the public key */
+ // P256PublicKeyHSM & public_key = const_cast(Pubkey());
+ signature_trustm_len = out_der_sig_span.size();
+ // ECC verify
+ return_status = trustm_ecdsa_verify((uint8_t *) hash, hash_length_u8, (uint8_t *) signature_trustm, signature_trustm_len_u16,
+ (uint8_t *) bytes, (uint8_t) kP256_PublicKey_Length);
+
+ VerifyOrExit(return_status == OPTIGA_LIB_SUCCESS, error = CHIP_ERROR_INTERNAL);
+
+exit:
+ if (error != CHIP_NO_ERROR)
+ {
+ trustm_close();
+ }
+ return error;
+#endif
+}
+
+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,
+ };
+
+ /* Set the public key */
+ P256PublicKey & public_key = const_cast(Pubkey());
+ bbuf.Put(Uint8::to_uchar(public_key), public_key.Length());
+
+ VerifyOrReturnError(bbuf.Available() == sizeof(privkey), CHIP_ERROR_INTERNAL);
+
+ /* Set the private key trustm_magic_no */
+ bbuf.Put(mKeypair.mBytes, kP256_PrivateKey_Length);
+ VerifyOrReturnError(bbuf.Fit(), CHIP_ERROR_BUFFER_TOO_SMALL);
+
+ output.SetLength(bbuf.Needed());
+
+ return CHIP_NO_ERROR;
+}
+
+CHIP_ERROR P256Keypair::Deserialize(P256SerializedKeypair & input)
+{
+ CHIP_ERROR error = CHIP_ERROR_INTERNAL;
+ const uint8_t * privkey;
+ /* Set the public key */
+ 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);
+
+ privkey = input.ConstBytes() /*Uint8::to_const_uchar(input) */ + public_key.Length();
+
+ if (0 == memcmp(privkey, trustm_magic_no, sizeof(trustm_magic_no)))
+ {
+ /* trustm_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], trustm_magic_no, sizeof(trustm_magic_no));
+
+ mKeypair.mBytes[4] = *(privkey + 4);
+ mKeypair.mBytes[5] = *(privkey + 5);
+ // ChipLogDetail(Crypto, "Parsed keyId = 0x%02X%02X", mKeypair.mBytes[4], mKeypair.mBytes[5]);
+
+ mInitialized = true;
+
+ return CHIP_NO_ERROR;
+ }
+ else
+ {
+#if !ENABLE_TRUSTM_KEY_IMPORT
+ if (CHIP_NO_ERROR == (error = Deserialize_H(this, &mPublicKey, &mKeypair, input)))
+ {
+ mInitialized = true;
+ }
+ return error;
+#else
+ // Add in code for Trust M
+ return CHIP_NO_ERROR;
+#endif
+ }
+}
+
+CHIP_ERROR P256PublicKey::ECDSA_validate_msg_signature(const uint8_t * msg, size_t msg_length,
+ const P256ECDSASignature & signature) const
+{
+#if !ENABLE_TRUSTM_ECDSA_VERIFY
+ return ECDSA_validate_msg_signature_H(this, msg, msg_length, signature);
+#else
+ CHIP_ERROR error = CHIP_ERROR_INTERNAL;
+ uint8_t signature_trustm[kMax_ECDSA_Signature_Length_Der] = { 0 };
+ size_t signature_trustm_len = sizeof(signature_trustm);
+ uint8_t digest[32];
+ uint8_t digest_length = sizeof(digest);
+ MutableByteSpan out_der_sig_span(signature_trustm, signature_trustm_len);
+ optiga_lib_status_t return_status = OPTIGA_LIB_BUSY;
+ uint16_t signature_trustm_len_u16 = static_cast(signature_trustm_len);
+
+ VerifyOrReturnError(msg != nullptr, CHIP_ERROR_INVALID_ARGUMENT);
+ VerifyOrReturnError(msg_length > 0, CHIP_ERROR_INVALID_ARGUMENT);
+
+ ChipLogDetail(Crypto, "ECDSA_validate_msg_signature: Using TrustM for TrustM verify (msg) !");
+
+ // Trust M init
+ trustm_Open();
+
+ error = EcdsaRawSignatureToAsn1(kP256_FE_Length, ByteSpan{ Uint8::to_const_uchar(signature.ConstBytes()), signature.Length() },
+ out_der_sig_span);
+ SuccessOrExit(error);
+
+ /* Set the public key */
+ // P256PublicKeyHSM & public_key = const_cast(Pubkey());
+ signature_trustm_len = out_der_sig_span.size();
+ // Hash to get the digest
+ memset(&digest[0], 0, sizeof(digest));
+ Hash_SHA256(msg, msg_length, &digest[0]);
+ // ECC verify
+ return_status = trustm_ecdsa_verify(digest, digest_length, (uint8_t *) signature_trustm, signature_trustm_len_u16,
+ (uint8_t *) bytes, (uint8_t) kP256_PublicKey_Length);
+
+ VerifyOrExit(return_status == OPTIGA_LIB_SUCCESS, error = CHIP_ERROR_INTERNAL);
+
+exit:
+ if (error != CHIP_NO_ERROR)
+ {
+ trustm_close();
+ }
+ return error;
+#endif
+}
+
+static 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;
+ if (len > 0 && val != NULL)
+ {
+ memcpy(&buf[buf_index], val, len);
+ buf_index = buf_index + len;
+ }
+}
+
+CHIP_ERROR P256Keypair::NewCertificateSigningRequest(uint8_t * csr, size_t & csr_length) const
+{
+#if !ENABLE_TRUSTM_GENERATE_EC_KEY
+ return NewCertificateSigningRequest_H(&mKeypair, csr, csr_length);
+#else
+ CHIP_ERROR error = CHIP_ERROR_INTERNAL;
+ optiga_lib_status_t return_status = OPTIGA_LIB_BUSY;
+
+ 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 digest[32] = { 0 };
+ uint8_t digest_length = sizeof(digest);
+ uint8_t signature_trustm[128] = { 0 };
+ uint16_t signature_len = sizeof(signature_trustm);
+
+ size_t csr_index = 0;
+ size_t buffer_index = data_to_hash_len;
+
+ // Dummy value
+ 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 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 };
+
+ VerifyOrReturnError(mInitialized, CHIP_ERROR_UNINITIALIZED);
+
+ if (CHIP_NO_ERROR != get_trustm_keyid_from_keypair(mKeypair, &keyid))
+ {
+ ChipLogDetail(Crypto, "NewCertificateSigningRequest : Not hsm key. Using host for CSR");
+ return NewCertificateSigningRequest_H(&mKeypair, csr, csr_length);
+ }
+ ChipLogDetail(Crypto, "NewCertificateSigningRequest: Using TrustM for CSR Creating!");
+
+ // No extensions are copied
+ buffer_index -= kTlvHeader;
+ add_tlv(data_to_hash, buffer_index, (ASN1_CONSTRUCTED | ASN1_CONTEXT_SPECIFIC), 0, NULL);
+
+ // Copy public key (with header)
+ {
+ P256PublicKey & public_key = const_cast(Pubkey());
+
+ VerifyOrExit((sizeof(nist256_header) + public_key.Length()) <= sizeof(pubkey), error = CHIP_ERROR_INTERNAL);
+
+ memcpy(pubkey, nist256_header, sizeof(nist256_header));
+ pubKeyLen = pubKeyLen + sizeof(nist256_header);
+
+ memcpy((pubkey + pubKeyLen), Uint8::to_uchar(public_key), public_key.Length());
+ pubKeyLen = pubKeyLen + public_key.Length();
+ }
+
+ buffer_index -= pubKeyLen;
+ VerifyOrExit(buffer_index > 0, error = CHIP_ERROR_INTERNAL);
+ memcpy((void *) &data_to_hash[buffer_index], pubkey, pubKeyLen);
+
+ // Copy subject (in the current implementation only organisation name info is added) and organisation OID
+ buffer_index -= (kTlvHeader + sizeof(SUBJECT_STR) - 1);
+ VerifyOrExit(buffer_index > 0, error = CHIP_ERROR_INTERNAL);
+ add_tlv(data_to_hash, buffer_index, ASN1_UTF8_STRING, sizeof(SUBJECT_STR) - 1, (uint8_t *) SUBJECT_STR);
+
+ buffer_index -= (kTlvHeader + sizeof(organisation_oid));
+ VerifyOrExit(buffer_index > 0, error = CHIP_ERROR_INTERNAL);
+ add_tlv(data_to_hash, buffer_index, ASN1_OID, sizeof(organisation_oid), organisation_oid);
+
+ // Add length
+ buffer_index -= kTlvHeader;
+ // Subject TLV ==> 1 + 1 + len(subject)
+ // Org OID TLV ==> 1 + 1 + len(organisation_oid)
+ VerifyOrExit(buffer_index > 0, error = CHIP_ERROR_INTERNAL);
+ add_tlv(data_to_hash, buffer_index, (ASN1_CONSTRUCTED | ASN1_SEQUENCE),
+ ((2 * kTlvHeader) + (sizeof(SUBJECT_STR) - 1) + sizeof(organisation_oid)), NULL);
+
+ buffer_index -= kTlvHeader;
+ VerifyOrExit(buffer_index > 0, error = CHIP_ERROR_INTERNAL);
+ add_tlv(data_to_hash, buffer_index, (ASN1_CONSTRUCTED | ASN1_SET),
+ ((3 * kTlvHeader) + (sizeof(SUBJECT_STR) - 1) + sizeof(organisation_oid)), NULL);
+
+ buffer_index -= kTlvHeader;
+ VerifyOrExit(buffer_index > 0, error = CHIP_ERROR_INTERNAL);
+ add_tlv(data_to_hash, buffer_index, (ASN1_CONSTRUCTED | ASN1_SEQUENCE),
+ ((4 * kTlvHeader) + (sizeof(SUBJECT_STR) - 1) + sizeof(organisation_oid)), NULL);
+
+ buffer_index -= 3;
+ VerifyOrExit(buffer_index > 0, error = CHIP_ERROR_INTERNAL);
+ memcpy((void *) &data_to_hash[buffer_index], version, sizeof(version));
+
+ buffer_index -= kTlvHeader;
+ VerifyOrExit(buffer_index > 0, error = CHIP_ERROR_INTERNAL);
+ add_tlv(data_to_hash, buffer_index, (ASN1_CONSTRUCTED | ASN1_SEQUENCE), (data_to_hash_len - buffer_index - kTlvHeader), NULL);
+
+ // TLV data is created by copying from backwards. move it to start of buffer.
+ data_to_hash_len = (data_to_hash_len - buffer_index);
+ memmove(data_to_hash, (data_to_hash + buffer_index), data_to_hash_len);
+
+ //Hash to get the digest
+ memset(&digest[0], 0, sizeof(digest));
+ error = Hash_SHA256(data_to_hash, data_to_hash_len, digest);
+ SuccessOrExit(error);
+
+ // Trust M Init
+ trustm_Open();
+
+ // Sign on hash
+ return_status = trustm_ecdsa_sign(OPTIGA_KEY_ID_E0F2, digest, digest_length,
+ signature_trustm, &signature_len);
+
+ VerifyOrExit(return_status == OPTIGA_LIB_SUCCESS, error = CHIP_ERROR_INTERNAL) ;
+ VerifyOrExit((csr_index + 3) <= csr_length, error = CHIP_ERROR_INTERNAL);
+ csr[csr_index++] = (ASN1_CONSTRUCTED | ASN1_SEQUENCE);
+ if ((data_to_hash_len + 14 + kTlvHeader + signature_len) >= 0x80)
+ {
+ csr[csr_index++] = 0x81;
+ }
+ csr[csr_index++] = (uint8_t)(data_to_hash_len + 14 + kTlvHeader + signature_len);
+
+ VerifyOrExit((csr_index + data_to_hash_len) <= csr_length, error = CHIP_ERROR_INTERNAL);
+ memcpy((csr + csr_index), data_to_hash, data_to_hash_len);
+ csr_index = csr_index + data_to_hash_len;
+
+ // ECDSA SHA256 Signature OID TLV ==> 1 + 1 + len(signature_oid) (8)
+ // ASN_NULL ==> 1 + 1
+ VerifyOrExit((csr_index + kTlvHeader) <= csr_length, error = CHIP_ERROR_INTERNAL);
+ add_tlv(csr, csr_index, (ASN1_CONSTRUCTED | ASN1_SEQUENCE), 0x0C, NULL);
+ csr_index = csr_index + kTlvHeader;
+
+ VerifyOrExit((csr_index + sizeof(signature_oid) + kTlvHeader) <= csr_length, error = CHIP_ERROR_INTERNAL);
+ add_tlv(csr, csr_index, ASN1_OID, sizeof(signature_oid), signature_oid);
+ csr_index = csr_index + kTlvHeader + sizeof(signature_oid);
+
+ VerifyOrExit((csr_index + kTlvHeader) <= csr_length, error = CHIP_ERROR_INTERNAL);
+ add_tlv(csr, csr_index, ASN1_NULL, 0x00, NULL);
+ csr_index = csr_index + kTlvHeader;
+
+ VerifyOrExit((csr_index + kTlvHeader) <= csr_length, error = CHIP_ERROR_INTERNAL);
+ csr[csr_index++] = ASN1_BIT_STRING;
+ csr[csr_index++] = (uint8_t)((signature_trustm[0] != 0) ? (signature_len + 1) : (signature_len));
+
+ if (signature_trustm[0] != 0)
+ {
+ VerifyOrExit(csr_index <= csr_length, error = CHIP_ERROR_INTERNAL);
+ csr[csr_index++] = 0x00;
+ // Increament total count by 1
+ csr[2]++;
+ }
+ VerifyOrExit((csr_index + signature_len) <= csr_length, error = CHIP_ERROR_INTERNAL);
+ memcpy(&csr[csr_index], signature_trustm, signature_len);
+
+ csr_length = (csr_index + signature_len);
+
+ error = CHIP_NO_ERROR;
+ exit:
+ if (error != CHIP_NO_ERROR)
+ {
+ trustm_close();
+ }
+ return error;
+ // MutableByteSpan out_csr(csr, csr_length);
+ // CHIP_ERROR err = GenerateCertificateSigningRequest(this, out_csr);
+ // csr_length = (CHIP_NO_ERROR == err) ? out_csr.size() : 0;
+ // return err;
+ #endif
+}
+
+} // namespace Crypto
+} // namespace chip
diff --git a/src/platform/Infineon/crypto/trustm/CHIPCryptoPALHsm_config_trustm.h b/src/platform/Infineon/crypto/trustm/CHIPCryptoPALHsm_config_trustm.h
new file mode 100644
index 00000000000000..67e024dc313f5a
--- /dev/null
+++ b/src/platform/Infineon/crypto/trustm/CHIPCryptoPALHsm_config_trustm.h
@@ -0,0 +1,53 @@
+/*
+ *
+ * Copyright (c) 2024 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 trustm for required crypto operations.
+ */
+
+#pragma once
+
+/*
+ * Enable trustm for Generate EC Key
+ */
+#define ENABLE_TRUSTM_GENERATE_EC_KEY 1
+
+/*
+ * Enable ECDSA Verify using trustm
+ */
+#define ENABLE_TRUSTM_ECDSA_VERIFY 1
+
+/*
+ * Enable Key Import for trustm
+ */
+#define ENABLE_TRUSTM_KEY_IMPORT 0
+
+/*
+ * Enable trustm for HKDF SHA256
+ */
+#define ENABLE_TRUSTM_HKDF_SHA256 0
+
+/*
+ * Enable trustm for HMAC SHA256
+ */
+#define ENABLE_TRUSTM_HMAC_SHA256 0
+
+/*
+ * Enable trustm for DA
+ */
+#define ENABLE_TRUSTM_DEVICE_ATTESTATION 1
diff --git a/src/platform/Infineon/crypto/trustm/CHIPCryptoPALHsm_rng_trustm.cpp b/src/platform/Infineon/crypto/trustm/CHIPCryptoPALHsm_rng_trustm.cpp
new file mode 100644
index 00000000000000..629c61ef9f6f3d
--- /dev/null
+++ b/src/platform/Infineon/crypto/trustm/CHIPCryptoPALHsm_rng_trustm.cpp
@@ -0,0 +1,61 @@
+/*
+ *
+ * Copyright (c) 2024 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_utils_trustm.h"
+#include "optiga/optiga_util.h"
+#include "optiga_crypt.h"
+#include "optiga_lib_types.h"
+#include
+
+
+namespace chip {
+namespace Crypto {
+
+CHIP_ERROR DRBG_get_bytes(uint8_t * out_buffer, const size_t out_length)
+{
+ CHIP_ERROR error = CHIP_ERROR_INTERNAL;
+ optiga_lib_status_t return_status = OPTIGA_LIB_BUSY;
+
+ VerifyOrReturnError(out_buffer != nullptr, CHIP_ERROR_INVALID_ARGUMENT);
+ VerifyOrReturnError(out_length > 0, CHIP_ERROR_INVALID_ARGUMENT);
+ // Trust M init
+ trustm_Open();
+
+ ChipLogDetail(Crypto, "Random Number: Using TrustM for Rondom Number Generate !");
+ return_status = optiga_crypt_rng(out_buffer, out_length);
+
+ VerifyOrExit(return_status == OPTIGA_LIB_SUCCESS, error = CHIP_ERROR_INTERNAL);
+
+ error = CHIP_NO_ERROR;
+
+exit:
+ if (error != CHIP_NO_ERROR)
+ {
+ trustm_close();
+ }
+ return CHIP_NO_ERROR;
+}
+
+} // namespace Crypto
+} // namespace chip
diff --git a/src/platform/Infineon/crypto/trustm/CHIPCryptoPALHsm_utils_trustm.cpp b/src/platform/Infineon/crypto/trustm/CHIPCryptoPALHsm_utils_trustm.cpp
new file mode 100644
index 00000000000000..dfd986c5e8cea0
--- /dev/null
+++ b/src/platform/Infineon/crypto/trustm/CHIPCryptoPALHsm_utils_trustm.cpp
@@ -0,0 +1,965 @@
+/*
+ *
+ * Copyright (c) 2024 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.
+ */
+
+/* OPTIGA(TM) Trust M includes */
+#include "CHIPCryptoPALHsm_utils_trustm.h"
+#include "ifx_i2c_config.h"
+#include "mbedtls/base64.h"
+#include "optiga_crypt.h"
+#include "optiga_lib_types.h"
+#include "optiga_util.h"
+#include "pal.h"
+#include "pal_ifx_i2c_config.h"
+#include "pal_os_event.h"
+#include "pal_os_memory.h"
+#include "pal_os_timer.h"
+#include
+
+optiga_crypt_t * p_local_crypt = NULL;
+optiga_util_t * p_local_util = NULL;
+static bool trustm_isOpen = false;
+#define ENABLE_HMAC_MULTI_STEP (0)
+#define OPTIGA_UTIL_DER_BITSTRING_TAG (0x03)
+#define OPTIGA_UTIL_DER_NUM_UNUSED_BITS (0x00)
+
+#if ENABLE_HMAC_MULTI_STEP
+#define MAX_MAC_DATA_LEN 640
+#endif
+
+// ================================================================================
+// FreeRTOS Callbacks
+// ================================================================================
+
+/* This is a place from which we can poll the status of operation */
+
+void vApplicationTickHook(void);
+
+void vApplicationTickHook(void)
+{
+ pal_os_event_trigger_registered_callback();
+}
+
+#define WAIT_FOR_COMPLETION(ret) \
+ if (OPTIGA_LIB_SUCCESS != ret) \
+ { \
+ break; \
+ } \
+ while (optiga_lib_status == OPTIGA_LIB_BUSY) \
+ { \
+ pal_os_event_trigger_registered_callback(); \
+ } \
+ \
+ if (OPTIGA_LIB_SUCCESS != optiga_lib_status) \
+ { \
+ ret = optiga_lib_status; \
+ printf("Error: 0x%02X \r\n", optiga_lib_status); \
+ break; \
+ }
+
+#define CHECK_RESULT(expr) \
+ optiga_lib_status_t return_status = (int32_t) OPTIGA_DEVICE_ERROR; \
+ \
+ do \
+ { \
+ optiga_lib_status = OPTIGA_LIB_BUSY; \
+ return_status = expr; \
+ WAIT_FOR_COMPLETION(return_status); \
+ } while (0); \
+ \
+ return return_status;
+
+static volatile optiga_lib_status_t optiga_lib_status;
+
+static void optiga_util_callback(void * context, optiga_lib_status_t return_status)
+{
+ optiga_lib_status = return_status;
+}
+
+// lint --e{818} suppress "argument "context" is not used in the sample provided"
+static void optiga_crypt_callback(void * context, optiga_lib_status_t return_status)
+{
+ optiga_lib_status = return_status;
+ if (NULL != context)
+ {
+ // callback to upper layer here
+ }
+}
+
+/* Open session to trustm */
+/**********************************************************************
+ * trustm_Open()
+ **********************************************************************/
+void trustm_Open(void)
+{
+ if (!trustm_isOpen)
+ {
+ optiga_lib_status_t return_status;
+ do
+ {
+ /**
+ * 1. Create OPTIGA Crypt Instance
+ */
+ p_local_crypt = optiga_crypt_create(0, optiga_crypt_callback, NULL);
+ if (NULL == p_local_crypt)
+ {
+ break;
+ }
+ // printf("trustm created crypt Instance \r\n");
+ /**
+ * 1. Create OPTIGA Util Instance
+ */
+ p_local_util = optiga_util_create(0, optiga_util_callback, NULL);
+ if (NULL == p_local_util)
+ {
+ break;
+ }
+ // printf("trustm created util Instance \r\n");
+ /**
+ * Open the application on OPTIGA which is a precondition to perform any other operations
+ * using optiga_util_open_application
+ */
+ optiga_lib_status = OPTIGA_LIB_BUSY;
+ return_status = optiga_util_open_application(p_local_util, 0); // skip restore
+ while (optiga_lib_status == OPTIGA_LIB_BUSY)
+ ;
+
+ if (OPTIGA_LIB_SUCCESS != return_status)
+ {
+ // optiga_util_open_application api returns error !!!
+ printf("optiga_util_open_application api returns error !!!\n");
+ break;
+ }
+
+ while (optiga_lib_status == OPTIGA_LIB_BUSY)
+ ;
+ if (OPTIGA_LIB_SUCCESS != optiga_lib_status)
+ {
+ // optiga_util_open_application failed
+ printf("optiga_util_open_application failed\n");
+ break;
+ }
+
+ // printf("trustm open application successful \r\n");
+
+ } while (0);
+
+ // p_local_util and p_local_crypt instance can be destroyed
+ // if no close_application w.r.t hibernate is required to be performed
+ if (p_local_util || p_local_crypt)
+ {
+ optiga_util_destroy(p_local_util);
+ optiga_crypt_destroy(p_local_crypt);
+ }
+ trustm_isOpen = true;
+ }
+}
+
+void trustm_close(void)
+{
+ optiga_lib_status_t return_status = OPTIGA_DEVICE_ERROR;
+
+ do
+ {
+ /**
+ * Close the application on OPTIGA after all the operations are executed
+ * using optiga_util_close_application
+ */
+ optiga_lib_status = OPTIGA_LIB_BUSY;
+ return_status = optiga_util_close_application(p_local_util, 0);
+ if (OPTIGA_LIB_SUCCESS != return_status)
+ break;
+
+ while (optiga_lib_status == OPTIGA_LIB_BUSY)
+ {
+ pal_os_event_trigger_registered_callback();
+ }
+
+ // destroy util and crypt instances
+ optiga_util_destroy(p_local_util);
+ optiga_crypt_destroy(p_local_crypt);
+ pal_os_event_destroy(NULL);
+
+ return_status = OPTIGA_LIB_SUCCESS;
+ } while (0);
+}
+
+void read_certificate_from_optiga(uint16_t optiga_oid, char * cert_pem, uint16_t * cert_pem_length)
+{
+ size_t ifx_cert_b64_len = 0;
+ uint8_t ifx_cert_b64_temp[1200];
+ uint16_t offset_to_write = 0, offset_to_read = 0;
+ uint16_t size_to_copy = 0;
+ optiga_lib_status_t return_status;
+
+ optiga_util_t * me_util = NULL;
+ uint8_t ifx_cert_hex[1024];
+ uint16_t ifx_cert_hex_len = sizeof(ifx_cert_hex);
+
+ do
+ {
+ // Create an instance of optiga_util to read the certificate from OPTIGA.
+ me_util = optiga_util_create(0, optiga_util_callback, NULL);
+ if (!me_util)
+ {
+ optiga_lib_print_message("optiga_util_create failed !!!", OPTIGA_UTIL_SERVICE, OPTIGA_UTIL_SERVICE_COLOR);
+ break;
+ }
+ optiga_lib_status = OPTIGA_LIB_BUSY;
+ return_status = optiga_util_read_data(me_util, optiga_oid, 0, ifx_cert_hex, &ifx_cert_hex_len);
+ if (OPTIGA_LIB_SUCCESS != return_status)
+ {
+ // optiga_util_read_data api returns error !!!
+ optiga_lib_print_message("optiga_util_read_data api returns error !!!", OPTIGA_UTIL_SERVICE, OPTIGA_UTIL_SERVICE_COLOR);
+ break;
+ }
+
+ while (optiga_lib_status == OPTIGA_LIB_BUSY)
+ ;
+ if (OPTIGA_LIB_SUCCESS != optiga_lib_status)
+ {
+ // optiga_util_read_data failed
+ optiga_lib_print_message("optiga_util_read_data failed", OPTIGA_UTIL_SERVICE, OPTIGA_UTIL_SERVICE_COLOR);
+ break;
+ }
+
+ // convert to PEM format
+ // If the first byte is TLS Identity Tag, than we need to skip 9 first bytes
+ offset_to_read = ifx_cert_hex[0] == 0xc0 ? 9 : 0;
+ mbedtls_base64_encode((unsigned char *) ifx_cert_b64_temp, sizeof(ifx_cert_b64_temp), &ifx_cert_b64_len,
+ ifx_cert_hex + offset_to_read, ifx_cert_hex_len - offset_to_read);
+
+ memcpy(cert_pem, "-----BEGIN CERTIFICATE-----\n", 28);
+ offset_to_write += 28;
+
+ // Properly copy certificate and format it as pkcs expects
+ for (offset_to_read = 0; offset_to_read < (uint16_t) ifx_cert_b64_len;)
+ {
+ // The last block of data usually is less than 64, thus we need to find the leftover
+ if ((offset_to_read + 64) >= (uint16_t) ifx_cert_b64_len)
+ size_to_copy = (uint16_t) ifx_cert_b64_len - offset_to_read;
+ else
+ size_to_copy = 64;
+ memcpy(cert_pem + offset_to_write, ifx_cert_b64_temp + offset_to_read, size_to_copy);
+ offset_to_write += size_to_copy;
+ offset_to_read += size_to_copy;
+ cert_pem[offset_to_write] = '\n';
+ offset_to_write++;
+ }
+
+ memcpy(cert_pem + offset_to_write, "-----END CERTIFICATE-----\n\0", 27);
+
+ *cert_pem_length = offset_to_write + 27;
+
+ } while (0);
+
+ // me_util instance to be destroyed
+ if (me_util)
+ {
+ optiga_util_destroy(me_util);
+ }
+}
+void write_data(uint16_t optiga_oid, const uint8_t * p_data, uint16_t length)
+{
+ optiga_util_t * me_util = NULL;
+ optiga_lib_status_t return_status;
+
+ do
+ {
+ // Create an instance of optiga_util to open the application on OPTIGA.
+ me_util = optiga_util_create(0, optiga_util_callback, NULL);
+ if (!me_util)
+ {
+ optiga_lib_print_message("optiga_util_create failed !!!", OPTIGA_UTIL_SERVICE, OPTIGA_UTIL_SERVICE_COLOR);
+ break;
+ }
+
+ optiga_lib_status = OPTIGA_LIB_BUSY;
+ return_status = optiga_util_write_data(me_util, optiga_oid, OPTIGA_UTIL_ERASE_AND_WRITE, 0, p_data, length);
+ {
+ if (OPTIGA_LIB_SUCCESS != return_status)
+ {
+ optiga_lib_print_message("optiga_util_wirte_data api returns error !!!", OPTIGA_UTIL_SERVICE,
+ OPTIGA_UTIL_SERVICE_COLOR);
+ break;
+ }
+
+ while (OPTIGA_LIB_BUSY == optiga_lib_status)
+ {
+ // Wait until the optiga_util_write_data operation is completed
+ }
+
+ if (OPTIGA_LIB_SUCCESS != optiga_lib_status)
+ {
+ optiga_lib_print_message("optiga_util_write_data failed", OPTIGA_UTIL_SERVICE, OPTIGA_UTIL_SERVICE_COLOR);
+ return_status = optiga_lib_status;
+ break;
+ }
+ else
+ {
+ optiga_lib_print_message("optiga_util_write_data successful", OPTIGA_UTIL_SERVICE, OPTIGA_UTIL_SERVICE_COLOR);
+ }
+ }
+ } while (0);
+
+ // me_util instance can be destroyed
+ // if no close_application w.r.t hibernate is required to be performed
+ if (me_util)
+ {
+ optiga_util_destroy(me_util);
+ }
+}
+
+void write_metadata(uint16_t optiga_oid, const uint8_t * p_data, uint8_t length)
+{
+ optiga_util_t * me_util = NULL;
+ optiga_lib_status_t return_status;
+
+ do
+ {
+ // Create an instance of optiga_util to open the application on OPTIGA.
+ me_util = optiga_util_create(0, optiga_util_callback, NULL);
+ if (!me_util)
+ {
+ optiga_lib_print_message("optiga_util_create failed !!!", OPTIGA_UTIL_SERVICE, OPTIGA_UTIL_SERVICE_COLOR);
+ break;
+ }
+
+ optiga_lib_status = OPTIGA_LIB_BUSY;
+ return_status = optiga_util_write_metadata(me_util, optiga_oid, p_data, length);
+ {
+ if (OPTIGA_LIB_SUCCESS != return_status)
+ {
+ optiga_lib_print_message("optiga_util_wirte_data api returns error !!!", OPTIGA_UTIL_SERVICE,
+ OPTIGA_UTIL_SERVICE_COLOR);
+ break;
+ }
+
+ while (OPTIGA_LIB_BUSY == optiga_lib_status)
+ {
+ // Wait until the optiga_util_write_metadata operation is completed
+ }
+
+ if (OPTIGA_LIB_SUCCESS != optiga_lib_status)
+ {
+ optiga_lib_print_message("optiga_util_write_metadata failed", OPTIGA_UTIL_SERVICE, OPTIGA_UTIL_SERVICE_COLOR);
+ return_status = optiga_lib_status;
+ break;
+ }
+ else
+ {
+ optiga_lib_print_message("optiga_util_write_metadata successful", OPTIGA_UTIL_SERVICE, OPTIGA_UTIL_SERVICE_COLOR);
+ }
+ }
+ } while (0);
+
+ // me_util instance can be destroyed
+ // if no close_application w.r.t hibernate is required to be performed
+ if (me_util)
+ {
+ optiga_util_destroy(me_util);
+ }
+}
+
+optiga_lib_status_t deriveKey_HKDF(const uint8_t * salt, uint16_t salt_length, const uint8_t * info, uint16_t info_length,
+ uint16_t derived_key_length, bool_t export_to_host, uint8_t * derived_key)
+{
+ optiga_lib_status_t return_status;
+
+ do
+ {
+ // Create an instance of optiga_crypt_t
+ p_local_crypt = optiga_crypt_create(0, optiga_crypt_callback, NULL);
+ if (NULL == p_local_crypt)
+ {
+ optiga_lib_print_message("optiga_crypt_create failed !!!", OPTIGA_UTIL_SERVICE, OPTIGA_UTIL_SERVICE_COLOR);
+ break;
+ }
+
+ optiga_lib_status = OPTIGA_LIB_BUSY;
+ return_status = optiga_crypt_hkdf(p_local_crypt, OPTIGA_HKDF_SHA_256, TRUSTM_HKDF_OID_KEY, /* Input secret OID */
+ salt, salt_length, info, info_length, derived_key_length, TRUE, derived_key);
+ if (OPTIGA_LIB_SUCCESS != return_status)
+ {
+ // optiga_crypt_hkdf api returns error !!!
+ optiga_lib_print_message("optiga_crypt_hkdf api returns error !!!", OPTIGA_UTIL_SERVICE, OPTIGA_UTIL_SERVICE_COLOR);
+ break;
+ }
+
+ while (optiga_lib_status == OPTIGA_LIB_BUSY)
+ ;
+ if (OPTIGA_LIB_SUCCESS != optiga_lib_status)
+ {
+ // optiga_crypt_hkdf failed
+ optiga_lib_print_message("optiga_crypt_hkdf failed", OPTIGA_UTIL_SERVICE, OPTIGA_UTIL_SERVICE_COLOR);
+ break;
+ }
+ } while (0);
+
+ if (p_local_crypt)
+ {
+ optiga_crypt_destroy(p_local_crypt);
+ }
+ return return_status;
+}
+
+optiga_lib_status_t hmac_sha256(optiga_hmac_type_t type, const uint8_t * input_data, uint32_t input_data_length, uint8_t * mac,
+ uint32_t * mac_length)
+{
+ optiga_lib_status_t return_status;
+
+ do
+ {
+ // Create an instance of optiga_crypt_t
+ p_local_crypt = optiga_crypt_create(0, optiga_crypt_callback, NULL);
+ if (NULL == p_local_crypt)
+ {
+ optiga_lib_print_message("optiga_crypt_create failed !!!", OPTIGA_UTIL_SERVICE, OPTIGA_UTIL_SERVICE_COLOR);
+ break;
+ }
+
+ return_status = OPTIGA_LIB_BUSY;
+#if ENABLE_HMAC_MULTI_STEP
+ // If the size is less than the max length supported
+ if (input_data_length <= MAX_MAC_DATA_LEN)
+ {
+ return_status =
+ optiga_crypt_hmac(p_local_crypt, type, TRUSTM_HMAC_OID_KEY, input_data, input_data_length, mac, mac_length);
+ if (OPTIGA_LIB_SUCCESS != return_status)
+ {
+ // optiga_crypt_hmac api returns error !!!
+ optiga_lib_print_message("optiga_crypt_hmac api returns error !!!", OPTIGA_UTIL_SERVICE, OPTIGA_UTIL_SERVICE_COLOR);
+ break;
+ }
+ }
+ else
+ {
+ // Calculate HMAC in multiple steps
+ uint32_t dataLenTemp = 0;
+ uint32_t remainingLen = input_data_length;
+ // Start the HMAC Operation
+ return_status = optiga_crypt_hmac_start(p_local_crypt, type, TRUSTM_HMAC_OID_KEY, input_data, MAX_MAC_DATA_LEN);
+
+ if (OPTIGA_LIB_SUCCESS != return_status)
+ {
+ // optiga_crypt_hmac_start api returns error !!!
+ optiga_lib_print_message("optiga_crypt_hmac_start api returns error !!!", OPTIGA_UTIL_SERVICE,
+ OPTIGA_UTIL_SERVICE_COLOR);
+ break;
+ }
+ remainingLen = input_data_length - MAX_MAC_DATA_LEN;
+
+ while (remainingLen > 0)
+ {
+ dataLenTemp = (remainingLen > MAX_MAC_DATA_LEN) ? MAX_MAC_DATA_LEN : remainingLen;
+
+ if (remainingLen > MAX_MAC_DATA_LEN)
+ {
+ return_status = OPTIGA_LIB_BUSY;
+ // printf("HMAC Update\n");
+ // Continue HMAC operation on input data
+ return_status =
+ optiga_crypt_hmac_update(p_local_crypt, (input_data + (input_data_length - remainingLen)), dataLenTemp);
+ remainingLen = remainingLen - dataLenTemp;
+
+ if (OPTIGA_LIB_SUCCESS != return_status)
+ {
+ // optiga_crypt_hmac_update api returns error !!!
+ optiga_lib_print_message("optiga_crypt_hmac_update api returns error !!!", OPTIGA_UTIL_SERVICE,
+ OPTIGA_UTIL_SERVICE_COLOR);
+ break;
+ }
+ }
+ else
+ {
+ // End HMAC sequence and return the MAC generated
+ // printf("HMAC Finalize\n");
+ return_status = OPTIGA_LIB_BUSY;
+ return_status = optiga_crypt_hmac_finalize(p_local_crypt, (input_data + (input_data_length - remainingLen)),
+ dataLenTemp, mac, mac_length);
+
+ if (OPTIGA_LIB_SUCCESS != return_status)
+ {
+ // optiga_crypt_hmac_finalize api returns error !!!
+ optiga_lib_print_message("optiga_crypt_hmac_finalize api returns error !!!", OPTIGA_UTIL_SERVICE,
+ OPTIGA_UTIL_SERVICE_COLOR);
+ break;
+ }
+ }
+ }
+ }
+#else
+
+ return_status = optiga_crypt_hmac(p_local_crypt, type, TRUSTM_HMAC_OID_KEY, input_data, input_data_length, mac, mac_length);
+ // printf("Output Length %ld Input Length %ld \n", *mac_length, input_data_length);
+ if (OPTIGA_LIB_SUCCESS != return_status)
+ {
+ // optiga_crypt_hmac api returns error !!!
+ optiga_lib_print_message("optiga_crypt_hmac api returns error !!!", OPTIGA_UTIL_SERVICE, OPTIGA_UTIL_SERVICE_COLOR);
+ break;
+ }
+
+ while (optiga_lib_status == OPTIGA_LIB_BUSY)
+ ;
+ if (OPTIGA_LIB_SUCCESS != optiga_lib_status)
+ {
+ // optiga_crypt_hkdf failed
+ optiga_lib_print_message("optiga_crypt_hkdf failed", OPTIGA_UTIL_SERVICE, OPTIGA_UTIL_SERVICE_COLOR);
+ break;
+ }
+#endif
+ } while (0);
+
+ if (p_local_crypt)
+ {
+ optiga_crypt_destroy(p_local_crypt);
+ }
+ return return_status;
+}
+optiga_lib_status_t optiga_crypt_rng(uint8_t * random_data, uint16_t random_data_length)
+{
+ optiga_lib_status_t return_status;
+ do
+ {
+ // Create an instance of optiga_crypt_t
+ p_local_crypt = optiga_crypt_create(0, optiga_crypt_callback, NULL);
+ if (NULL == p_local_crypt)
+ {
+ optiga_lib_print_message("optiga_crypt_create failed !!!", OPTIGA_UTIL_SERVICE, OPTIGA_UTIL_SERVICE_COLOR);
+ break;
+ }
+
+ return_status = OPTIGA_LIB_BUSY;
+ return_status = optiga_crypt_random(p_local_crypt,
+ OPTIGA_RNG_TYPE_DRNG,
+ random_data,
+ random_data_length);
+if (OPTIGA_LIB_SUCCESS != return_status)
+ {
+ // optiga_crypt_random api returns error !!!
+ optiga_lib_print_message("optiga_crypt_random api returns error !!!", OPTIGA_UTIL_SERVICE, OPTIGA_UTIL_SERVICE_COLOR);
+ break;
+ }
+
+ while (optiga_lib_status == OPTIGA_LIB_BUSY)
+ ;
+ if (OPTIGA_LIB_SUCCESS != optiga_lib_status)
+ {
+ // optiga_crypt_random failed
+ optiga_lib_print_message("optiga_crypt_random failed", OPTIGA_UTIL_SERVICE, OPTIGA_UTIL_SERVICE_COLOR);
+ break;
+ }
+ } while (0);
+
+ if (p_local_crypt)
+ {
+ optiga_crypt_destroy(p_local_crypt);
+ }
+ return return_status;
+}
+optiga_lib_status_t trustm_ecc_keygen(uint16_t optiga_key_id, uint8_t key_type, optiga_ecc_curve_t curve_id, uint8_t * pubkey,
+ uint16_t *pubkey_length)
+{
+ optiga_lib_status_t return_status;
+ uint8_t header256[] = { 0x30, 0x59, 0x30, 0x13, 0x06, 0x07, 0x2A, 0x86, 0x48, 0xCE, 0x3D, 0x02,
+ 0x01, 0x06, 0x08, 0x2A, 0x86, 0x48, 0xCE, 0x3D, 0x03, 0x01, 0x07 };
+ uint16_t i;
+ for (i = 0; i < sizeof(header256); i++)
+ {
+ pubkey[i] = header256[i];
+ }
+ do
+ {
+ // Create an instance of optiga_crypt_t
+ p_local_crypt = optiga_crypt_create(0, optiga_crypt_callback, NULL);
+ if (NULL == p_local_crypt)
+ {
+ optiga_lib_print_message("optiga_crypt_create failed !!!", OPTIGA_UTIL_SERVICE, OPTIGA_UTIL_SERVICE_COLOR);
+ break;
+ }
+
+ optiga_lib_status = OPTIGA_LIB_BUSY;
+ return_status = optiga_crypt_ecc_generate_keypair(p_local_crypt, curve_id, key_type, FALSE, &optiga_key_id, (pubkey + i),
+ pubkey_length);
+ if (OPTIGA_LIB_SUCCESS != return_status)
+ {
+ // optiga_crypt_ecc_generate_keypair api returns error !!!
+ optiga_lib_print_message("optiga_crypt_ecc_generate_keypair api returns error !!!", OPTIGA_UTIL_SERVICE,
+ OPTIGA_UTIL_SERVICE_COLOR);
+ break;
+ }
+
+ while (optiga_lib_status == OPTIGA_LIB_BUSY)
+ ;
+
+ } while (0);
+
+ if (p_local_crypt)
+ {
+ optiga_crypt_destroy(p_local_crypt);
+ }
+
+ *pubkey_length += sizeof(header256);
+ return return_status;
+}
+void trustmGetKey(uint16_t optiga_oid, uint8_t * pubkey, uint16_t * pubkeyLen)
+{
+ optiga_lib_status_t return_status;
+ uint16_t offset = 0;
+ do
+ {
+ // Create an instance of optiga_crypt_t
+ p_local_util = optiga_util_create(0, optiga_util_callback, NULL);
+ if (NULL == p_local_util)
+ {
+ optiga_lib_print_message("optiga_util_create failed !!!", OPTIGA_UTIL_SERVICE, OPTIGA_UTIL_SERVICE_COLOR);
+ break;
+ }
+
+ optiga_lib_status = OPTIGA_LIB_BUSY;
+ return_status = optiga_util_read_data(p_local_util, optiga_oid, offset, pubkey, pubkeyLen);
+ if (OPTIGA_LIB_SUCCESS != return_status)
+ {
+ // optiga_util_read_pubkey api returns error !!!
+ optiga_lib_print_message("optiga_util_read_pubkey returns error !!!", OPTIGA_UTIL_SERVICE, OPTIGA_UTIL_SERVICE_COLOR);
+ break;
+ }
+
+ while (optiga_lib_status == OPTIGA_LIB_BUSY)
+ ;
+
+ } while (0);
+
+ if (p_local_util)
+ {
+ optiga_util_destroy(p_local_util);
+ }
+}
+optiga_lib_status_t trustm_hash(uint8_t * msg, uint16_t msg_length, uint8_t * digest, uint8_t digest_length)
+{
+ optiga_lib_status_t return_status;
+ hash_data_from_host_t hash_data_host;
+ do
+ {
+ // Create an instance of optiga_crypt_t
+ p_local_crypt = optiga_crypt_create(0, optiga_crypt_callback, NULL);
+ if (NULL == p_local_crypt)
+ {
+ optiga_lib_print_message("optiga_crypt_create failed !!!", OPTIGA_UTIL_SERVICE, OPTIGA_UTIL_SERVICE_COLOR);
+ break;
+ }
+ hash_data_host.buffer = msg;
+ hash_data_host.length = msg_length;
+ optiga_lib_status = OPTIGA_LIB_BUSY;
+ return_status = optiga_crypt_hash(p_local_crypt, OPTIGA_HASH_TYPE_SHA_256, OPTIGA_CRYPT_HOST_DATA, &hash_data_host, digest);
+
+ if (OPTIGA_LIB_SUCCESS != return_status)
+ {
+ // optiga_crypt_ecdsa_sign api returns error !!!
+ optiga_lib_print_message("optiga_crypt_hash api returns error !!!", OPTIGA_UTIL_SERVICE, OPTIGA_UTIL_SERVICE_COLOR);
+ break;
+ }
+ while (optiga_lib_status == OPTIGA_LIB_BUSY)
+ ;
+ } while (0);
+
+ if (p_local_crypt)
+ {
+ optiga_crypt_destroy(p_local_crypt);
+ }
+ return return_status;
+}
+optiga_lib_status_t trustm_ecdsa_sign(optiga_key_id_t optiga_key_id, uint8_t * digest, uint8_t digest_length, uint8_t * signature,
+ uint16_t * signature_length)
+{
+ optiga_lib_status_t return_status;
+ int i;
+ do
+ {
+ // Create an instance of optiga_crypt_t
+ p_local_crypt = optiga_crypt_create(0, optiga_crypt_callback, NULL);
+ if (NULL == p_local_crypt)
+ {
+ optiga_lib_print_message("optiga_crypt_create failed !!!", OPTIGA_UTIL_SERVICE, OPTIGA_UTIL_SERVICE_COLOR);
+ break;
+ }
+ optiga_lib_status = OPTIGA_LIB_BUSY;
+ return_status = optiga_crypt_ecdsa_sign(p_local_crypt, digest, digest_length, optiga_key_id, signature, signature_length);
+ if (OPTIGA_LIB_SUCCESS != return_status)
+ {
+ // optiga_crypt_ecdsa_sign api returns error !!!
+ optiga_lib_print_message("optiga_crypt_ecdsa_sign api returns error !!!", OPTIGA_UTIL_SERVICE,
+ OPTIGA_UTIL_SERVICE_COLOR);
+ break;
+ }
+ while (optiga_lib_status == OPTIGA_LIB_BUSY)
+ ;
+
+ for (i = (*signature_length - 1); i >= 0; i--)
+ {
+ signature[i + 2] = signature[i];
+ }
+
+ signature[0] = 0x30; // Insert SEQUENCE
+ signature[1] = (uint8_t)(*signature_length); // insert length
+ *signature_length = *signature_length + 2;
+
+ } while (0);
+
+ if (p_local_crypt)
+ {
+ optiga_crypt_destroy(p_local_crypt);
+ }
+ return return_status;
+}
+void ecc_pub_key_bit(uint8_t * q_buffer, uint8_t q_length, uint8_t * pub_key_buffer, uint16_t * pub_key_length)
+{
+#define OPTIGA_UTIL_ECC_DER_ADDITIONAL_LENGTH (0x02)
+
+ uint16_t index = 0;
+
+ pub_key_buffer[index++] = OPTIGA_UTIL_DER_BITSTRING_TAG;
+ pub_key_buffer[index++] = q_length + OPTIGA_UTIL_ECC_DER_ADDITIONAL_LENGTH;
+ pub_key_buffer[index++] = OPTIGA_UTIL_DER_NUM_UNUSED_BITS;
+ // Compression format. Supports only 04 [uncompressed]
+ pub_key_buffer[index++] = 0x04;
+
+ pal_os_memcpy(&pub_key_buffer[index], q_buffer, q_length);
+ index += q_length;
+
+ *pub_key_length = index;
+
+#undef OPTIGA_UTIL_ECC_DER_ADDITIONAL_LENGTH
+}
+optiga_lib_status_t trustm_ecdsa_verify(uint8_t * digest, uint8_t digest_length, uint8_t * signature, uint16_t signature_length,
+ uint8_t * ecc_pubkey, uint8_t ecc_pubkey_length)
+{
+ optiga_lib_status_t return_status;
+ uint8_t ecc_public_key[70] = { 0x00 };
+ uint16_t i;
+ uint16_t ecc_public_key_length = 0;
+ ecc_pub_key_bit(ecc_pubkey, ecc_pubkey_length, ecc_public_key, &ecc_public_key_length);
+
+ public_key_from_host_t public_key_details = { ecc_public_key, ecc_public_key_length, (uint8_t) OPTIGA_ECC_CURVE_NIST_P_256 };
+ do
+ {
+ // Create an instance of optiga_crypt_t
+ p_local_crypt = optiga_crypt_create(0, optiga_crypt_callback, NULL);
+
+ if (NULL == p_local_crypt)
+ {
+ optiga_lib_print_message("optiga_crypt_create failed !!!", OPTIGA_UTIL_SERVICE, OPTIGA_UTIL_SERVICE_COLOR);
+ break;
+ }
+ signature_length = signature[1];
+ for (i = 0; i < signature_length; i++)
+ {
+ signature[i] = signature[i + 2];
+ }
+ return_status = OPTIGA_LIB_BUSY;
+ return_status = optiga_crypt_ecdsa_verify(p_local_crypt, digest, digest_length, signature, signature_length,
+ OPTIGA_CRYPT_HOST_DATA, &public_key_details);
+ if (OPTIGA_LIB_SUCCESS != return_status)
+ {
+ // optiga_crypt_ecdsa_verify api returns error !!!
+ optiga_lib_print_message("optiga_crypt_ecdsa_verify api returns error !!!", OPTIGA_UTIL_SERVICE,
+ OPTIGA_UTIL_SERVICE_COLOR);
+ break;
+ }
+ while (optiga_lib_status == OPTIGA_LIB_BUSY)
+ ;
+ } while (0);
+
+ if (p_local_crypt)
+ {
+ optiga_crypt_destroy(p_local_crypt);
+ }
+ return return_status;
+}
+
+CHIP_ERROR trustmGetCertificate(uint16_t optiga_oid, uint8_t * buf, uint16_t * buflen)
+{
+ optiga_lib_status_t return_status;
+ VerifyOrReturnError(buf != nullptr, CHIP_ERROR_INTERNAL);
+ VerifyOrReturnError(buflen != nullptr, CHIP_ERROR_INTERNAL);
+
+ uint8_t ifx_cert_hex[1024];
+ uint16_t ifx_cert_hex_len = sizeof(ifx_cert_hex);
+
+ trustm_Open();
+ do
+ {
+ // Create an instance of optiga_util to read the certificate from OPTIGA.
+ p_local_util = optiga_util_create(0, optiga_util_callback, NULL);
+ if (!p_local_util)
+ {
+ optiga_lib_print_message("optiga_util_create failed !!!", OPTIGA_UTIL_SERVICE, OPTIGA_UTIL_SERVICE_COLOR);
+ break;
+ }
+ optiga_lib_status = OPTIGA_LIB_BUSY;
+ return_status = optiga_util_read_data(p_local_util, optiga_oid, 0, ifx_cert_hex, &ifx_cert_hex_len);
+ if (OPTIGA_LIB_SUCCESS != return_status)
+ {
+ // optiga_util_read_data api returns error !!!
+ optiga_lib_print_message("optiga_util_read_data api returns error !!!", OPTIGA_UTIL_SERVICE, OPTIGA_UTIL_SERVICE_COLOR);
+ break;
+ }
+ while (optiga_lib_status == OPTIGA_LIB_BUSY)
+ ;
+ if (OPTIGA_LIB_SUCCESS != optiga_lib_status)
+ {
+ // optiga_util_read_data failed
+ optiga_lib_print_message("optiga_util_read_data failed", OPTIGA_UTIL_SERVICE, OPTIGA_UTIL_SERVICE_COLOR);
+ break;
+ }
+
+ memcpy(buf, ifx_cert_hex, ifx_cert_hex_len);
+ *buflen = ifx_cert_hex_len;
+ while (optiga_lib_status == OPTIGA_LIB_BUSY)
+ ;
+ if (OPTIGA_LIB_SUCCESS != optiga_lib_status)
+ {
+ // optiga_util_read_data failed
+ optiga_lib_print_message("optiga_util_read_data failed", OPTIGA_UTIL_SERVICE, OPTIGA_UTIL_SERVICE_COLOR);
+ break;
+ }
+ } while (0);
+
+ if (p_local_util)
+ {
+ optiga_util_destroy(p_local_util);
+ }
+ return CHIP_NO_ERROR;
+}
+optiga_lib_status_t trustm_ecdh_derive_secret(optiga_key_id_t optiga_key_id, uint8_t * public_key, uint16_t public_key_length,
+ uint8_t * shared_secret, uint8_t shared_secret_length)
+{
+ optiga_lib_status_t return_status;
+ static public_key_from_host_t public_key_details = {
+ (uint8_t *) public_key,
+ public_key_length,
+ (uint8_t) OPTIGA_ECC_CURVE_NIST_P_256,
+ };
+ do
+ {
+ // Create an instance of optiga_crypt_t
+ p_local_crypt = optiga_crypt_create(0, optiga_crypt_callback, NULL);
+
+ if (NULL == p_local_crypt)
+ {
+ optiga_lib_print_message("optiga_crypt_create failed !!!", OPTIGA_UTIL_SERVICE, OPTIGA_UTIL_SERVICE_COLOR);
+ break;
+ }
+
+ optiga_lib_status = OPTIGA_LIB_BUSY;
+ return_status = optiga_crypt_ecdh(p_local_crypt, optiga_key_id, &public_key_details, TRUE, shared_secret);
+ if (OPTIGA_LIB_SUCCESS != return_status)
+ {
+ // optiga_crypt_ecdh api returns error !!!
+ optiga_lib_print_message("optiga_crypt_ecdh api returns error !!!", OPTIGA_UTIL_SERVICE,
+ OPTIGA_UTIL_SERVICE_COLOR);
+ break;
+ }
+ while (optiga_lib_status == OPTIGA_LIB_BUSY)
+ ;
+ } while (0);
+
+ if (p_local_crypt)
+ {
+ optiga_crypt_destroy(p_local_crypt);
+ }
+ return return_status;
+}
+
+optiga_lib_status_t trustm_PBKDF2_HMAC(const unsigned char * salt, size_t slen, unsigned int iteration_count, uint32_t key_length,
+ unsigned char * output)
+{
+ optiga_lib_status_t return_status;
+ uint8_t md1[32];
+ uint32_t md1_len = sizeof(md1);
+ uint8_t work[32];
+ uint32_t work_len = sizeof(work);
+
+ unsigned char * out_p = output;
+ do
+ {
+ // Create an instance of optiga_crypt_t
+ p_local_crypt = optiga_crypt_create(0, optiga_crypt_callback, NULL);
+ if (NULL == p_local_crypt)
+ {
+ optiga_lib_print_message("optiga_crypt_create failed!!!", OPTIGA_UTIL_SERVICE, OPTIGA_UTIL_SERVICE_COLOR);
+ break;
+ }
+
+ // Calculate U1, U1 ends up in work
+ return_status =
+ optiga_crypt_hmac(p_local_crypt, OPTIGA_HMAC_SHA_256, TRUSTM_HMAC_OID_KEY, salt, (uint32_t) slen, work, &work_len);
+
+ if (OPTIGA_LIB_SUCCESS != return_status)
+ {
+ optiga_lib_print_message("optiga_crypt_hmac api returns error!!!", OPTIGA_UTIL_SERVICE, OPTIGA_UTIL_SERVICE_COLOR);
+ break;
+ }
+ return_status = OPTIGA_LIB_BUSY;
+ memcpy(md1, work, md1_len);
+ for (unsigned int i = 1; i < iteration_count; i++)
+ {
+ // Calculated subsequent U, which ends up in md1
+ return_status = optiga_crypt_hmac(p_local_crypt, OPTIGA_HMAC_SHA_256, TRUSTM_HMAC_OID_KEY, md1, md1_len, md1, &md1_len);
+
+ if (OPTIGA_LIB_SUCCESS != return_status)
+ {
+ optiga_lib_print_message("optiga_crypt_hmac api returns error!!!", OPTIGA_UTIL_SERVICE, OPTIGA_UTIL_SERVICE_COLOR);
+ break;
+ }
+ return_status = OPTIGA_LIB_BUSY;
+
+ // U1 xor U2
+ for (int j = 0; j < (int) md1_len; j++)
+ {
+ work[j] ^= md1[j];
+ }
+ }
+
+ while (optiga_lib_status == OPTIGA_LIB_BUSY)
+ ;
+
+ if (OPTIGA_LIB_SUCCESS != optiga_lib_status)
+
+ {
+
+ // optiga_crypt_hkdf failed
+
+ optiga_lib_print_message("optiga_crypt_pbkdf_hmac failed failed", OPTIGA_UTIL_SERVICE, OPTIGA_UTIL_SERVICE_COLOR);
+
+ break;
+ }
+ memcpy(out_p, work, key_length);
+ } while (0);
+
+ if (p_local_crypt)
+ {
+ optiga_crypt_destroy(p_local_crypt);
+ }
+ return return_status;
+}
\ No newline at end of file
diff --git a/src/platform/Infineon/crypto/trustm/CHIPCryptoPALHsm_utils_trustm.h b/src/platform/Infineon/crypto/trustm/CHIPCryptoPALHsm_utils_trustm.h
new file mode 100644
index 00000000000000..b6fce44f10bfff
--- /dev/null
+++ b/src/platform/Infineon/crypto/trustm/CHIPCryptoPALHsm_utils_trustm.h
@@ -0,0 +1,83 @@
+/*
+ *
+ * Copyright (c) 2024 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.
+ */
+
+#pragma once
+
+#include
+
+#include
+#include
+
+#include "optiga_crypt.h"
+#include
+#include
+#include
+#include
+#include
+/* trustm includes */
+#include "optiga_util.h"
+#include
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+extern optiga_crypt_t * p_local_crypt;
+extern optiga_util_t * p_local_util;
+
+#define TRUSTM_HKDF_OID_KEY (0xF1D8)
+#define TRUSTM_HMAC_OID_KEY (0xF1D9)
+#define TRUSTM_P256_PUBKEY_OID_KEY (0xF1DA)
+#define TRUSTM_ECDH_OID_KEY (0xE100)
+#define TRUSTM_NODE_OID_KEY_START (0xE0F2)
+
+#define IFX_CRYPTO_KEY_MAGIC \
+ { \
+ 0xA0, 0x10, 0xA0, 0x10 \
+ }
+
+static const uint8_t trustm_magic_no[] = IFX_CRYPTO_KEY_MAGIC;
+static const uint8_t DA_KEY_ID[] = {0xE0, 0xF0};
+/* Open session to trustm */
+void trustm_Open(void);
+void read_certificate_from_optiga(uint16_t optiga_oid, char * cert_pem, uint16_t * cert_pem_length);
+void write_data(uint16_t optiga_oid, const uint8_t * p_data, uint16_t length);
+void write_metadata(uint16_t optiga_oid, const uint8_t * p_data, uint8_t length);
+void trustmGetKey(uint16_t optiga_oid, uint8_t * pubkey, uint16_t * pubKeyLen);
+optiga_lib_status_t deriveKey_HKDF(const uint8_t * salt, uint16_t salt_length, const uint8_t * info, uint16_t info_length,
+ uint16_t derived_key_length, bool_t export_to_host, uint8_t * derived_key);
+optiga_lib_status_t hmac_sha256(optiga_hmac_type_t type, const uint8_t * input_data, uint32_t input_data_length, uint8_t * mac,
+ uint32_t * mac_length);
+optiga_lib_status_t trustm_ecc_keygen(uint16_t optiga_key_id, uint8_t key_type, optiga_ecc_curve_t curve_id, uint8_t * pubkey,
+ uint16_t *pubkey_length);
+optiga_lib_status_t trustm_hash(uint8_t * msg, uint16_t msg_length, uint8_t * digest, uint8_t digest_length);
+optiga_lib_status_t trustm_ecdsa_sign(optiga_key_id_t optiga_key_id, uint8_t * digest, uint8_t digest_length, uint8_t * signature,
+ uint16_t * signature_length);
+void ecc_public_key_in_bit(const uint8_t * q_buffer, uint8_t q_length, uint8_t * pub_key_buffer, uint16_t pub_key_length);
+optiga_lib_status_t trustm_ecdsa_verify(uint8_t * digest, uint8_t digest_length, uint8_t * signature, uint16_t signature_length,
+ uint8_t * ecc_pubkey, uint8_t ecc_pubkey_length);
+/* Close session to trustm */
+void trustm_close(void);
+CHIP_ERROR trustmGetCertificate(uint16_t optiga_oid, uint8_t * buf, uint16_t * buflen);
+optiga_lib_status_t trustm_ecdh_derive_secret(optiga_key_id_t optiga_key_id, uint8_t * public_key, uint16_t public_key_length,
+ uint8_t * shared_secret, uint8_t shared_secret_length);
+optiga_lib_status_t optiga_crypt_rng(uint8_t * random_data, uint16_t random_data_length);
+optiga_lib_status_t trustm_PBKDF2_HMAC(const unsigned char * salt, size_t slen, unsigned int iteration_count, uint32_t key_length,
+ unsigned char * output);
+#ifdef __cplusplus
+}
+#endif
diff --git a/src/platform/Infineon/crypto/trustm/CHIPCryptoPAL_HostFallBack.cpp b/src/platform/Infineon/crypto/trustm/CHIPCryptoPAL_HostFallBack.cpp
new file mode 100644
index 00000000000000..d0f321863dfe9d
--- /dev/null
+++ b/src/platform/Infineon/crypto/trustm/CHIPCryptoPAL_HostFallBack.cpp
@@ -0,0 +1,512 @@
+/*
+ *
+ * Copyright (c) 2020-2024 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);
+
+ 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 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/Infineon/crypto/trustm/DeviceAttestationCredsExampleTrustM.cpp b/src/platform/Infineon/crypto/trustm/DeviceAttestationCredsExampleTrustM.cpp
new file mode 100644
index 00000000000000..c9cc791e4d650d
--- /dev/null
+++ b/src/platform/Infineon/crypto/trustm/DeviceAttestationCredsExampleTrustM.cpp
@@ -0,0 +1,140 @@
+/*
+ *
+ * Copyright (c) 2024 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.
+ */
+
+#include "DeviceAttestationCredsExampleTrustM.h"
+#include
+#include
+#include
+#include
+
+#ifdef ENABLE_TRUSTM_DEVICE_ATTESTATION
+#include
+
+/* Device attestation key ids for Trust M */
+#define DEV_ATTESTATION_KEY_ID 0xE0F0
+#define DEV_ATTESTATION_CERT_ID 0xE0E0
+#define PAI_CERT_ID 0xE0E8
+#define CERT_DECLARATION_ID 0xF1E0
+
+namespace chip {
+namespace Credentials {
+namespace Examples {
+
+namespace {
+
+class ExampleTrustMDACProvider : public DeviceAttestationCredentialsProvider
+{
+public:
+ CHIP_ERROR GetCertificationDeclaration(MutableByteSpan & out_cd_buffer) override;
+ CHIP_ERROR GetFirmwareInformation(MutableByteSpan & out_firmware_info_buffer) override;
+ CHIP_ERROR GetDeviceAttestationCert(MutableByteSpan & out_dac_buffer) override;
+ CHIP_ERROR GetProductAttestationIntermediateCert(MutableByteSpan & out_pai_buffer) override;
+ CHIP_ERROR SignWithDeviceAttestationKey(const ByteSpan & message_to_sign, MutableByteSpan & out_signature_buffer) override;
+};
+
+CHIP_ERROR ExampleTrustMDACProvider::GetDeviceAttestationCert(MutableByteSpan & out_dac_buffer)
+{
+ uint16_t buflen = (uint16_t) out_dac_buffer.size();
+ ChipLogDetail(Crypto, "Get DAC certificate from trustm");
+ ReturnErrorOnFailure(trustmGetCertificate(DEV_ATTESTATION_CERT_ID, out_dac_buffer.data(), &buflen));
+ out_dac_buffer.reduce_size(buflen);
+ return CHIP_NO_ERROR;
+}
+
+CHIP_ERROR ExampleTrustMDACProvider::GetProductAttestationIntermediateCert(MutableByteSpan & out_pai_buffer)
+{
+ uint16_t buflen = (uint16_t) out_pai_buffer.size();
+ ChipLogDetail(Crypto, "Get PAI certificate from trustm");
+ ReturnErrorOnFailure(trustmGetCertificate(PAI_CERT_ID, out_pai_buffer.data(), &buflen));
+ out_pai_buffer.reduce_size(buflen);
+ return CHIP_NO_ERROR;
+}
+
+CHIP_ERROR ExampleTrustMDACProvider::GetCertificationDeclaration(MutableByteSpan & out_cd_buffer)
+{
+ //-> format_version = 1
+ //-> vendor_id = 0xFFF1
+ //-> product_id_array = [ 0x8000, 0x8001, 0x8002, 0x8003, 0x8004, 0x8005, 0x8006, 0x8007, 0x8008, 0x8009, 0x800A, 0x800B,
+ // 0x800C, 0x800D, 0x800E, 0x800F, 0x8010, 0x8011, 0x8012, 0x8013, 0x8014, 0x8015, 0x8016, 0x8017, 0x8018, 0x8019, 0x801A,
+ // 0x801B, 0x801C, 0x801D, 0x801E, 0x801F, 0x8020, 0x8021, 0x8022, 0x8023, 0x8024, 0x8025, 0x8026, 0x8027, 0x8028, 0x8029,
+ // 0x802A, 0x802B, 0x802C, 0x802D, 0x802E, 0x802F, 0x8030, 0x8031, 0x8032, 0x8033, 0x8034, 0x8035, 0x8036, 0x8037, 0x8038,
+ // 0x8039, 0x803A, 0x803B, 0x803C, 0x803D, 0x803E, 0x803F, 0x8040, 0x8041, 0x8042, 0x8043, 0x8044, 0x8045, 0x8046, 0x8047,
+ // 0x8048, 0x8049, 0x804A, 0x804B, 0x804C, 0x804D, 0x804E, 0x804F, 0x8050, 0x8051, 0x8052, 0x8053, 0x8054, 0x8055, 0x8056,
+ // 0x8057, 0x8058, 0x8059, 0x805A, 0x805B, 0x805C, 0x805D, 0x805E, 0x805F, 0x8060, 0x8061, 0x8062, 0x8063 ]
+ //-> device_type_id = 0x0016
+ //-> certificate_id = "ZIG20142ZB330003-24"
+ //-> security_level = 0
+ //-> security_information = 0
+ //-> version_number = 0x2694
+ //-> certification_type = 0
+ //-> dac_origin_vendor_id is not present
+ //-> dac_origin_product_id is not present
+ size_t buflen = out_cd_buffer.size();
+ ChipLogDetail(Crypto, "Get certificate declaration from trustm");
+ ReturnErrorOnFailure(trustmGetCertificate(CERT_DECLARATION_ID, out_cd_buffer.data(), (uint16_t *) &buflen));
+ out_cd_buffer.reduce_size(buflen);
+ return CHIP_NO_ERROR;
+}
+
+CHIP_ERROR ExampleTrustMDACProvider::GetFirmwareInformation(MutableByteSpan & out_firmware_info_buffer)
+{
+ // TODO: We need a real example FirmwareInformation to be populated.
+ out_firmware_info_buffer.reduce_size(0);
+
+ return CHIP_NO_ERROR;
+}
+
+CHIP_ERROR ExampleTrustMDACProvider::SignWithDeviceAttestationKey(const ByteSpan & message_to_sign,
+ MutableByteSpan & out_signature_buffer)
+{
+ Crypto::P256ECDSASignature signature;
+ Crypto::P256Keypair keypair;
+ Crypto::P256SerializedKeypair serialized_keypair;
+
+ ChipLogDetail(Crypto, "Sign using DA key from trustm");
+
+ VerifyOrReturnError(IsSpanUsable(out_signature_buffer), CHIP_ERROR_INVALID_ARGUMENT);
+ VerifyOrReturnError(IsSpanUsable(message_to_sign), CHIP_ERROR_INVALID_ARGUMENT);
+ VerifyOrReturnError(out_signature_buffer.size() >= signature.Capacity(), CHIP_ERROR_BUFFER_TOO_SMALL);
+
+ 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, trustm_magic_no, sizeof(trustm_magic_no));
+ memcpy(serialized_keypair.Bytes() + (Crypto::kP256_PublicKey_Length + sizeof (trustm_magic_no)), DA_KEY_ID, 2);
+
+ ReturnErrorOnFailure(keypair.Deserialize(serialized_keypair));
+
+ ReturnErrorOnFailure(keypair.ECDSA_sign_msg(message_to_sign.data(), message_to_sign.size(), signature));
+
+ return CopySpanToMutableSpan(ByteSpan{ signature.ConstBytes(), signature.Length() }, out_signature_buffer);
+}
+
+} // namespace
+
+DeviceAttestationCredentialsProvider * GetExampleTrustMDACProvider()
+{
+ static ExampleTrustMDACProvider example_dac_provider;
+
+ return &example_dac_provider;
+}
+
+} // namespace Examples
+} // namespace Credentials
+} // namespace chip
+
+#endif //#ifdef ENABLE_TRUSTM_DEVICE_ATTESTATION
diff --git a/src/platform/Infineon/crypto/trustm/DeviceAttestationCredsExampleTrustM.h b/src/platform/Infineon/crypto/trustm/DeviceAttestationCredsExampleTrustM.h
new file mode 100644
index 00000000000000..84c25fe22dfbb8
--- /dev/null
+++ b/src/platform/Infineon/crypto/trustm/DeviceAttestationCredsExampleTrustM.h
@@ -0,0 +1,36 @@
+/*
+ *
+ * Copyright (c) 2024 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.
+ */
+#pragma once
+
+#include
+
+namespace chip {
+namespace Credentials {
+namespace Examples {
+
+/**
+ * @brief Get implementation of a sample DAC provider to validate device
+ * attestation procedure.
+ *
+ * @returns a singleton DeviceAttestationCredentialsProvider that relies on no
+ * storage abstractions.
+ */
+DeviceAttestationCredentialsProvider * GetExampleTrustMDACProvider();
+
+} // namespace Examples
+} // namespace Credentials
+} // namespace chip
diff --git a/src/platform/Infineon/crypto/trustm/args.gni b/src/platform/Infineon/crypto/trustm/args.gni
new file mode 100644
index 00000000000000..412b4988aaacc7
--- /dev/null
+++ b/src/platform/Infineon/crypto/trustm/args.gni
@@ -0,0 +1,19 @@
+# Copyright (c) 2024 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")
+
+infineon_crypto_impl = "trustm"
+infineon_crypto_root = "//third_party/infineon/trustm"
diff --git a/third_party/infineon/psoc6/BUILD.gn b/third_party/infineon/psoc6/BUILD.gn
index 59464a8e2a7cf5..19fe610b1e6777 100644
--- a/third_party/infineon/psoc6/BUILD.gn
+++ b/third_party/infineon/psoc6/BUILD.gn
@@ -1,4 +1,4 @@
-# Copyright (c) 2021 Project CHIP Authors
+# Copyright (c) 2023 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.
diff --git a/third_party/infineon/psoc6/psoc6_sdk/build/CY8CKIT-062S2-43012/Debug/GCC_ARM.json b/third_party/infineon/psoc6/psoc6_sdk/build/CY8CKIT-062S2-43012/Debug/GCC_ARM.json
index d55c68af229eda..bdf407807c5a42 100644
--- a/third_party/infineon/psoc6/psoc6_sdk/build/CY8CKIT-062S2-43012/Debug/GCC_ARM.json
+++ b/third_party/infineon/psoc6/psoc6_sdk/build/CY8CKIT-062S2-43012/Debug/GCC_ARM.json
@@ -221,7 +221,11 @@
"-DCOMPONENT_SOFTFP",
"-DCOMPONENT_WICED_BLE",
"-DDEBUG",
- "-DCY_SUPPORTS_DEVICE_VALIDATION"
+ "-DCY_SUPPORTS_DEVICE_VALIDATION",
+ "-DCY_CRYPTO_HAL_DISABLE",
+ "-DCOMPONENT_SECURE_SOCKETS",
+ "-DCOMPONENT_PSOC6_FREERTOS",
+ "-DOPTIGA_LIB_EXTERNAL="
],
"c_source": [
"./libs/abstraction-rtos/source/cy_worker_thread.c",
diff --git a/third_party/infineon/psoc6/psoc6_sdk/build/CY8CKIT-062S2-43012/Release/GCC_ARM.json b/third_party/infineon/psoc6/psoc6_sdk/build/CY8CKIT-062S2-43012/Release/GCC_ARM.json
index d8859347f78d72..917160ac8f83e7 100644
--- a/third_party/infineon/psoc6/psoc6_sdk/build/CY8CKIT-062S2-43012/Release/GCC_ARM.json
+++ b/third_party/infineon/psoc6/psoc6_sdk/build/CY8CKIT-062S2-43012/Release/GCC_ARM.json
@@ -221,7 +221,11 @@
"-DCOMPONENT_SOFTFP",
"-DCOMPONENT_WICED_BLE",
"-DNDEBUG",
- "-DCY_SUPPORTS_DEVICE_VALIDATION"
+ "-DCY_SUPPORTS_DEVICE_VALIDATION",
+ "-DCY_CRYPTO_HAL_DISABLE",
+ "-DCOMPONENT_SECURE_SOCKETS",
+ "-DCOMPONENT_PSOC6_FREERTOS",
+ "-DOPTIGA_LIB_EXTERNAL="
],
"c_source": [
"./libs/abstraction-rtos/source/cy_worker_thread.c",
diff --git a/third_party/infineon/psoc6/psoc6_sdk/configs/FreeRTOSConfig.h b/third_party/infineon/psoc6/psoc6_sdk/configs/FreeRTOSConfig.h
index 38e058fbec9fbf..8478bf2eecff3c 100644
--- a/third_party/infineon/psoc6/psoc6_sdk/configs/FreeRTOSConfig.h
+++ b/third_party/infineon/psoc6/psoc6_sdk/configs/FreeRTOSConfig.h
@@ -75,7 +75,13 @@ extern uint32_t SystemCoreClock;
#define configTOTAL_HEAP_SIZE ((size_t)(CY_SRAM_SIZE - (64 * 1024)))
/* Hook function related definitions. */
#define configUSE_IDLE_HOOK 0
+
+#ifdef ENABLE_HSM_DEVICE_ATTESTATION
+#define configUSE_TICK_HOOK 1
+#else
#define configUSE_TICK_HOOK 0
+#endif
+
#define configCHECK_FOR_STACK_OVERFLOW 2
#define configUSE_MALLOC_FAILED_HOOK 1
@@ -96,7 +102,7 @@ extern uint32_t SystemCoreClock;
#define configUSE_TIMERS 1
#define configTIMER_TASK_PRIORITY 2
#define configTIMER_QUEUE_LENGTH 10
-#define configTIMER_TASK_STACK_DEPTH (configMINIMAL_STACK_SIZE * 2)
+#define configTIMER_TASK_STACK_DEPTH (configMINIMAL_STACK_SIZE * 6)
/* Queue Creation Fix to not use static queue */
#define LWIP_FREERTOS_USE_STATIC_TCPIP_QUEUE 0
diff --git a/third_party/infineon/psoc6/psoc6_sdk/configs/optiga_lib_config_mtb.h b/third_party/infineon/psoc6/psoc6_sdk/configs/optiga_lib_config_mtb.h
new file mode 100644
index 00000000000000..25251ba988392a
--- /dev/null
+++ b/third_party/infineon/psoc6/psoc6_sdk/configs/optiga_lib_config_mtb.h
@@ -0,0 +1,196 @@
+/**
+ * \copyright
+ * MIT License
+ *
+ * Copyright (c) 2023 Infineon Technologies AG
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE
+ *
+ * \endcopyright
+ *
+ * \author Infineon Technologies AG
+ *
+ * \file optiga_lib_config_m_v3.h
+ *
+ * \brief This file is defines the compilation switches to build code with required features.
+ *
+ * \ingroup grOptigaLibCommon
+ *
+ * @{
+ */
+
+#ifndef _OPTIGA_LIB_CONFIG_M_V3_H_
+#define _OPTIGA_LIB_CONFIG_M_V3_H_
+
+#include "cy_pdl.h"
+#include "cybsp.h"
+#include "cyhal.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/** @brief OPTIGA CRYPT random number generation feature enable/disable macro */
+#define OPTIGA_CRYPT_RANDOM_ENABLED
+/** @brief OPTIGA CRYPT hash feature enable/disable macro */
+#define OPTIGA_CRYPT_HASH_ENABLED
+/** @brief OPTIGA CRYPT ECC generate keypair feature enable/disable macro */
+#define OPTIGA_CRYPT_ECC_GENERATE_KEYPAIR_ENABLED
+/** @brief OPTIGA CRYPT ECDSA signature feature enable/disable macro */
+#define OPTIGA_CRYPT_ECDSA_SIGN_ENABLED
+/** @brief OPTIGA CRYPT verify ECDSA signature feature enable/disable macro */
+#define OPTIGA_CRYPT_ECDSA_VERIFY_ENABLED
+/** @brief OPTIGA CRYPT ECDH feature enable/disable macro */
+#define OPTIGA_CRYPT_ECDH_ENABLED
+/** @brief OPTIGA CRYPT ECC 521 feature enable/disable macro */
+#define OPTIGA_CRYPT_ECC_NIST_P_521_ENABLED
+/** @brief OPTIGA CRYPT ECC Brainpool feature enable/disable macro */
+#define OPTIGA_CRYPT_ECC_BRAINPOOL_P_R1_ENABLED
+/** @brief OPTIGA CRYPT TLS PRF sha256 feature enable/disable macro */
+#define OPTIGA_CRYPT_TLS_PRF_SHA256_ENABLED
+/** @brief OPTIGA CRYPT TLS PRF sha384 feature enable/disable macro */
+#define OPTIGA_CRYPT_TLS_PRF_SHA384_ENABLED
+/** @brief OPTIGA CRYPT TLS PRF sha512 feature enable/disable macro */
+#define OPTIGA_CRYPT_TLS_PRF_SHA512_ENABLED
+/** @brief OPTIGA CRYPT RSA generate keypair feature enable/disable macro */
+#define OPTIGA_CRYPT_RSA_GENERATE_KEYPAIR_ENABLED
+/** @brief OPTIGA CRYPT RSA sign feature enable/disable macro */
+#define OPTIGA_CRYPT_RSA_SIGN_ENABLED
+/** @brief OPTIGA CRYPT RSA verify sign feature enable/disable macro */
+#define OPTIGA_CRYPT_RSA_VERIFY_ENABLED
+/** @brief OPTIGA CRYPT RSA Encrypt feature enable/disable macro */
+#define OPTIGA_CRYPT_RSA_ENCRYPT_ENABLED
+/** @brief OPTIGA CRYPT RSA Decrypt feature enable/disable macro */
+#define OPTIGA_CRYPT_RSA_DECRYPT_ENABLED
+/** @brief OPTIGA CRYPT RSA pre-master feature enable/disable macro */
+#define OPTIGA_CRYPT_RSA_PRE_MASTER_SECRET_ENABLED
+/** @brief OPTIGA CRYPT RSA SSA with SHA512 as digest feature enable/disable macro */
+#define OPTIGA_CRYPT_RSA_SSA_SHA512_ENABLED
+/** @brief OPTIGA CRYPT symmetric encrypt feature enable/disable macro */
+#define OPTIGA_CRYPT_SYM_ENCRYPT_ENABLED
+/** @brief OPTIGA CRYPT symmetric decrypt feature enable/disable macro */
+#define OPTIGA_CRYPT_SYM_DECRYPT_ENABLED
+/** @brief OPTIGA CRYPT HMAC feature enable/disable macro */
+#define OPTIGA_CRYPT_HMAC_ENABLED
+/** @brief OPTIGA CRYPT HKDF feature enable/disable macro */
+#define OPTIGA_CRYPT_HKDF_ENABLED
+/** @brief OPTIGA CRYPT symmetric generate key feature enable/disable macro */
+#define OPTIGA_CRYPT_SYM_GENERATE_KEY_ENABLED
+/** @brief OPTIGA CRYPT generate auth code feature enable/disable macro */
+#define OPTIGA_CRYPT_GENERATE_AUTH_CODE_ENABLED
+/** @brief OPTIGA CRYPT HMAC verify feature enable/disable macro */
+#define OPTIGA_CRYPT_HMAC_VERIFY_ENABLED
+/** @brief OPTIGA CRYPT clear AUTO state feature enable/disable macro */
+#define OPTIGA_CRYPT_CLEAR_AUTO_STATE_ENABLED
+
+/** @brief OPTIGA COMMS shielded connection feature.
+ * To disable the feature, undefine the macro
+ */
+#define OPTIGA_COMMS_SHIELDED_CONNECTION
+
+/** @brief Default reset protection level for OPTIGA CRYPT and UTIL APIs */
+#define OPTIGA_COMMS_DEFAULT_PROTECTION_LEVEL OPTIGA_COMMS_NO_PROTECTION
+
+/** @brief NULL parameter check.
+ * To disable the check, undefine the macro
+ */
+#define OPTIGA_LIB_DEBUG_NULL_CHECK
+/** @brief Maximum number of instance registration */
+#define OPTIGA_CMD_MAX_REGISTRATIONS (0x06)
+/** @brief Maximum buffer size required to communicate with OPTIGA */
+#define OPTIGA_MAX_COMMS_BUFFER_SIZE (0x615) // 1557 in decimal
+
+/** @brief Macro to enable logger \n
+ * Enable macro OPTIGA_LIB_ENABLE_UTIL_LOGGING for Util Service layer logging \n
+ * Enable macro OPTIGA_LIB_ENABLE_CRYPT_LOGGING for Crypt Service layer logging \n
+ * Enable macro OPTIGA_LIB_ENABLE_CMD_LOGGING for Command layer logging \n
+ * Enable macro OPTIGA_LIB_ENABLE_COMMS_LOGGING for Communication layer logging */
+//#define OPTIGA_LIB_ENABLE_LOGGING
+/** @brief Enable macro OPTIGA_PAL_INIT_ENABLED for calling pal_init functionality */
+#define OPTIGA_PAL_INIT_ENABLED
+/// @cond
+#ifdef OPTIGA_LIB_ENABLE_LOGGING
+/** @brief Macro to enable logger for Util service */
+//#define OPTIGA_LIB_ENABLE_UTIL_LOGGING
+/** @brief Macro to enable logger for Crypt service */
+//#define OPTIGA_LIB_ENABLE_CRYPT_LOGGING
+/** @brief Macro to enable logger for Command layer */
+// #define OPTIGA_LIB_ENABLE_CMD_LOGGING
+/** @brief Macro to enable logger for Communication layer */
+//#define OPTIGA_LIB_ENABLE_COMMS_LOGGING
+#endif
+/// @endcond
+
+/* Below are the example macros for protected update not for any feature */
+/** @brief OPTIGA UTIL confidentiality protected update feature enable/disable macro */
+#define EXAMPLE_OPTIGA_UTIL_PROTECTED_UPDATE_CONFIDENTIALITY_ENABLED
+/** @brief OPTIGA UTIL key object protected update feature enable/disable macro */
+#define EXAMPLE_OPTIGA_UTIL_PROTECTED_UPDATE_OBJECT_KEY_ENABLED
+/** @brief OPTIGA UTIL metadata object protected update feature enable/disable macro */
+#define EXAMPLE_OPTIGA_UTIL_PROTECTED_UPDATE_OBJECT_METADATA_ENABLED
+
+/*
+ * The following GPIO settings are only ModusToolbox and specific PSoC6 family board relevant
+ */
+//#if defined(CYBSP_TRUSTM_I2C_SCL)
+// #define OPTIGA_TRUSTM_SCL CYBSP_TRUSTM_I2C_SCL
+//#elif defined(CYBSP_I2C_SCL)
+#define OPTIGA_TRUSTM_SCL CYBSP_I2C_SCL
+//#else
+// #error "You need to define the OPTIGA_TRUSTM_SCL macro for OPTIGA to know what to use for the communication"
+//#endif
+
+//#if defined(CYBSP_TRUSTM_I2C_SDA)
+// #define OPTIGA_TRUSTM_SDA CYBSP_TRUSTM_I2C_SDA
+//#elif defined(CYBSP_I2C_SDA)
+#define OPTIGA_TRUSTM_SDA CYBSP_I2C_SDA
+//#else
+// #error "You need to define the OPTIGA_TRUSTM_SDA macro for OPTIGA to know what to use for the communication"
+//#endif
+
+#if defined(CYBSP_TRUSTM_RST)
+#define OPTIGA_TRUSTM_RST CYBSP_TRUSTM_RST
+#endif
+#if defined(CYBSP_TRUSTM_VDD)
+#define OPTIGA_TRUSTM_VDD CYBSP_TRUSTM_VDD
+#endif
+
+/** @brief Default reset type in optiga_comms_open. \n
+ * Cold Reset - (0) : This is applicable if the host platform has GPIO option for RST and VDD. \n
+ * Soft Reset - (1) : This is applicable if the host platform doesn't have GPIO options for VDD and RST. \n
+ * Warm Reset - (2) : This is applicable if the host platform doesn't have GPIO option for VDD. \n
+ * Any other value will lead to error
+ */
+#if defined(CYBSP_TRUSTM_RST) || defined(CYBSP_TRUSTM_VDD)
+#define OPTIGA_COMMS_DEFAULT_RESET_TYPE (0U)
+#elif !defined(CYBSP_TRUSTM_RST) && !defined(CYBSP_TRUSTM_VDD)
+#define OPTIGA_COMMS_DEFAULT_RESET_TYPE (1U)
+#elif defined(CYBSP_TRUSTM_RST) && !defined(CYBSP_TRUSTM_VDD)
+#define OPTIGA_COMMS_DEFAULT_RESET_TYPE (0U)
+#endif
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _OPTIGA_LIB_CONFIG_M_V3_H_*/
+
+/**
+ * @}
+ */
diff --git a/third_party/infineon/trustm/BUILD.gn b/third_party/infineon/trustm/BUILD.gn
new file mode 100644
index 00000000000000..70b0a6997b853b
--- /dev/null
+++ b/third_party/infineon/trustm/BUILD.gn
@@ -0,0 +1,73 @@
+# Copyright (c) 2023 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/platform/device.gni")
+import("${chip_root}/third_party/infineon/trustm/trustm_config.gni")
+
+config("trustm_config") {
+ if (chip_trustm_da == 1) {
+ defines += [ "CHIP_TRUSTM_DA" ]
+ }
+
+ include_dirs = [
+ "${chip_root}/third_party/infineon/trustm/optiga-trust-m/optiga/include",
+ "${chip_root}/third_party/infineon/trustm/optiga-trust-m/optiga/include/optiga",
+ "${chip_root}/third_party/infineon/trustm/optiga-trust-m/optiga/include/optiga/ifx_i2c",
+ "${chip_root}/third_party/infineon/trustm/optiga-trust-m/optiga/include/optiga/comms",
+ "${chip_root}/third_party/infineon/trustm/optiga-trust-m/optiga/include/optiga/common",
+ "${chip_root}/third_party/infineon/trustm/optiga-trust-m/optiga/include/optiga/cmd",
+ "${chip_root}/third_party/infineon/trustm/optiga-trust-m/optiga/include/optiga/pal",
+ "${chip_root}/third_party/infineon/trustm/optiga-trust-m/externals/mbedtls/include",
+ "${chip_root}/third_party/infineon/trustm",
+ ]
+ if (chip_device_platform == "psoc6") {
+ include_dirs += [ "${chip_root}/third_party/infineon/trustm/optiga-trust-m/pal/COMPONENT_PSOC6_FREERTOS/COMPONENT_CM4" ]
+ }
+}
+
+source_set("optiga-trust-m") {
+ sources = [
+ "${chip_root}/third_party/infineon/trustm/optiga-trust-m/optiga/cmd/optiga_cmd.c",
+ "${chip_root}/third_party/infineon/trustm/optiga-trust-m/optiga/common/optiga_lib_common.c",
+ "${chip_root}/third_party/infineon/trustm/optiga-trust-m/optiga/common/optiga_lib_logger.c",
+ "${chip_root}/third_party/infineon/trustm/optiga-trust-m/optiga/comms/ifx_i2c/ifx_i2c.c",
+ "${chip_root}/third_party/infineon/trustm/optiga-trust-m/optiga/comms/ifx_i2c/ifx_i2c_config.c",
+ "${chip_root}/third_party/infineon/trustm/optiga-trust-m/optiga/comms/ifx_i2c/ifx_i2c_data_link_layer.c",
+ "${chip_root}/third_party/infineon/trustm/optiga-trust-m/optiga/comms/ifx_i2c/ifx_i2c_physical_layer.c",
+ "${chip_root}/third_party/infineon/trustm/optiga-trust-m/optiga/comms/ifx_i2c/ifx_i2c_presentation_layer.c",
+ "${chip_root}/third_party/infineon/trustm/optiga-trust-m/optiga/comms/ifx_i2c/ifx_i2c_transport_layer.c",
+ "${chip_root}/third_party/infineon/trustm/optiga-trust-m/optiga/comms/optiga_comms_ifx_i2c.c",
+ "${chip_root}/third_party/infineon/trustm/optiga-trust-m/optiga/crypt/optiga_crypt.c",
+ "${chip_root}/third_party/infineon/trustm/optiga-trust-m/optiga/util/optiga_util.c",
+ "${chip_root}/third_party/infineon/trustm/optiga-trust-m/pal/pal_crypt_mbedtls.c",
+ ]
+
+ if (chip_device_platform == "psoc6") {
+ sources += [
+ "${chip_root}/third_party/infineon/trustm/optiga-trust-m/pal/COMPONENT_PSOC6_FREERTOS/COMPONENT_CM4/pal.c",
+ "${chip_root}/third_party/infineon/trustm/optiga-trust-m/pal/COMPONENT_PSOC6_FREERTOS/COMPONENT_CM4/pal_gpio.c",
+ "${chip_root}/third_party/infineon/trustm/optiga-trust-m/pal/COMPONENT_PSOC6_FREERTOS/COMPONENT_CM4/pal_i2c.c",
+ "${chip_root}/third_party/infineon/trustm/optiga-trust-m/pal/COMPONENT_PSOC6_FREERTOS/COMPONENT_CM4/pal_ifx_i2c_config.c",
+ "${chip_root}/third_party/infineon/trustm/optiga-trust-m/pal/COMPONENT_PSOC6_FREERTOS/COMPONENT_CM4/pal_logger.c",
+ "${chip_root}/third_party/infineon/trustm/optiga-trust-m/pal/COMPONENT_PSOC6_FREERTOS/COMPONENT_CM4/pal_os_datastore.c",
+ "${chip_root}/third_party/infineon/trustm/optiga-trust-m/pal/COMPONENT_PSOC6_FREERTOS/COMPONENT_CM4/pal_os_event.c",
+ "${chip_root}/third_party/infineon/trustm/optiga-trust-m/pal/COMPONENT_PSOC6_FREERTOS/COMPONENT_CM4/pal_os_lock.c",
+ "${chip_root}/third_party/infineon/trustm/optiga-trust-m/pal/COMPONENT_PSOC6_FREERTOS/COMPONENT_CM4/pal_os_memory.c",
+ "${chip_root}/third_party/infineon/trustm/optiga-trust-m/pal/COMPONENT_PSOC6_FREERTOS/COMPONENT_CM4/pal_os_timer.c",
+ ]
+ }
+ public_deps = [ "${chip_root}/third_party/mbedtls:mbedtls" ]
+ configs += [ ":trustm_config" ]
+}
diff --git a/third_party/infineon/trustm/optiga-trust-m b/third_party/infineon/trustm/optiga-trust-m
new file mode 160000
index 00000000000000..f80296882bbd67
--- /dev/null
+++ b/third_party/infineon/trustm/optiga-trust-m
@@ -0,0 +1 @@
+Subproject commit f80296882bbd67c0ee84829d12845729d5075970
diff --git a/third_party/infineon/trustm/trustm_config.gni b/third_party/infineon/trustm/trustm_config.gni
new file mode 100644
index 00000000000000..8893a1372f958f
--- /dev/null
+++ b/third_party/infineon/trustm/trustm_config.gni
@@ -0,0 +1,19 @@
+# Copyright (c) 2023 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.
+
+# Configuration file
+
+declare_args() {
+ chip_trustm_da = 0
+}