From 9b2c88954ba39a93f0846e68a35538b01a589e4d Mon Sep 17 00:00:00 2001 From: doru91 Date: Fri, 22 Jul 2022 21:40:26 +0300 Subject: [PATCH] [K32W0] SVE fixes (#20471) Main fixes/functionalities brought in this PR: * add initial enablement for K32W041A/AM * add linker file fixes for OTA enablement * add detokenizer support for the elock and moved the script location to a generic location * move tinycrypt implementation in a separate class * enable low power with SDK 2.6.6 * enable MACv2 * refactoring around PDM storage * add size-optimized BLE libraries Signed-off-by: Doru Gucea Signed-off-by: Marius Tache Signed-off-by: Andrei Menzopol --- .github/workflows/examples-k32w.yaml | 10 +- examples/lighting-app/nxp/k32w/k32w0/BUILD.gn | 18 +- .../lighting-app/nxp/k32w/k32w0/README.md | 52 +- .../lighting-app/nxp/k32w/k32w0/main/main.cpp | 7 + examples/lock-app/nxp/k32w/k32w0/BUILD.gn | 21 +- examples/lock-app/nxp/k32w/k32w0/README.md | 130 +- examples/lock-app/nxp/k32w/k32w0/args.gni | 2 - .../lock-app/nxp/k32w/k32w0/main/AppTask.cpp | 5 +- .../lock-app/nxp/k32w/k32w0/main/main.cpp | 62 +- ...32w061-linker.ld => chip-k32w0x-linker.ld} | 21 +- .../app/project_include/OpenThreadConfig.h | 2 + .../k32w/k32w0/app/support/FreeRtosHooks.c | 7 + .../nxp/k32w/k32w0/scripts}/detokenizer.py | 0 examples/shell/nxp/k32w/k32w0/BUILD.gn | 4 +- gn_build.sh | 8 +- scripts/build/build/targets.py | 2 +- scripts/build/builders/k32w.py | 17 +- scripts/build/test.py | 2 +- .../build/testdata/build_all_except_host.txt | 10 +- scripts/examples/k32w_se_example.sh | 2 +- src/crypto/BUILD.gn | 5 + src/crypto/CHIPCryptoPALTinyCrypt.cpp | 1500 +++++++++++++++++ src/crypto/CHIPCryptoPALmbedTLS.cpp | 374 +--- src/crypto/crypto.gni | 4 +- src/lib/shell/streamer_k32w.cpp | 4 +- .../nxp/k32w/k32w0/BLEManagerImpl.cpp | 1 + src/platform/nxp/k32w/k32w0/BUILD.gn | 2 - src/platform/nxp/k32w/k32w0/K32W0Config.cpp | 174 +- src/platform/nxp/k32w/k32w0/K32W0Config.h | 11 +- .../k32w/k32w0/KeyValueStoreManagerImpl.cpp | 18 +- .../nxp/k32w/k32w0/KeyValueStoreManagerImpl.h | 1 + src/platform/nxp/k32w/k32w0/Logging.cpp | 4 +- .../nxp/k32w/k32w0/OTAImageProcessorImpl.cpp | 16 +- .../nxp/k32w/k32w0/PlatformManagerImpl.cpp | 28 +- .../nxp/k32w/k32w0/PlatformManagerImpl.h | 12 + .../nxp/k32w/k32w0/SystemPlatformConfig.h | 2 +- .../nxp/k32w/k32w0/ThreadStackManagerImpl.cpp | 5 + third_party/nxp/k32w0_sdk/BUILD.gn | 13 +- third_party/nxp/k32w0_sdk/k32w0_sdk.gni | 235 ++- .../nxp/k32w0_sdk/sdk_fixes/patch_k32w_sdk.sh | 62 +- third_party/openthread/ot-nxp | 2 +- .../platforms/nxp/k32w/k32w0/BUILD.gn | 10 +- 42 files changed, 2224 insertions(+), 641 deletions(-) rename examples/platform/nxp/k32w/k32w0/app/ldscripts/{chip-k32w061-linker.ld => chip-k32w0x-linker.ld} (93%) rename examples/{lighting-app/nxp/k32w/k32w0 => platform/nxp/k32w/k32w0/scripts}/detokenizer.py (100%) create mode 100644 src/crypto/CHIPCryptoPALTinyCrypt.cpp diff --git a/.github/workflows/examples-k32w.yaml b/.github/workflows/examples-k32w.yaml index 9885e1e43788b6..38f86e5b6f7a6d 100644 --- a/.github/workflows/examples-k32w.yaml +++ b/.github/workflows/examples-k32w.yaml @@ -34,7 +34,7 @@ jobs: if: github.actor != 'restyled-io[bot]' container: - image: connectedhomeip/chip-build-k32w:0.5.84 + image: connectedhomeip/chip-build-k32w:0.5.87 volumes: - "/tmp/bloat_reports:/tmp/bloat_reports" steps: @@ -82,15 +82,15 @@ jobs: timeout-minutes: 5 run: | .environment/pigweed-venv/bin/python3 scripts/tools/memory/gh_sizes.py \ - k32w k32w061+release light \ - out/artifacts/k32w-light-release-no-ota/chip-k32w061-light-example \ + k32w k32w0+release light \ + out/artifacts/k32w-light-release-no-ota/chip-k32w0x-light-example \ /tmp/bloat_reports/ - name: Get lock size stats timeout-minutes: 5 run: | .environment/pigweed-venv/bin/python3 scripts/tools/memory/gh_sizes.py \ - k32w k32w061+release lock \ - out/artifacts/k32w-lock-low-power-release/chip-k32w061-lock-example \ + k32w k32w0+release lock \ + out/artifacts/k32w-lock-low-power-release/chip-k32w0x-lock-example \ /tmp/bloat_reports/ - name: Uploading Size Reports uses: actions/upload-artifact@v2 diff --git a/examples/lighting-app/nxp/k32w/k32w0/BUILD.gn b/examples/lighting-app/nxp/k32w/k32w0/BUILD.gn index 5e811f8900e0d8..c19ccbac46f23a 100644 --- a/examples/lighting-app/nxp/k32w/k32w0/BUILD.gn +++ b/examples/lighting-app/nxp/k32w/k32w0/BUILD.gn @@ -21,7 +21,6 @@ import("${k32w0_sdk_build_root}/k32w0_sdk.gni") import("${chip_root}/src/crypto/crypto.gni") import("${chip_root}/src/lib/core/core.gni") -import("${chip_root}/src/lib/core/core.gni") import("${chip_root}/src/platform/device.gni") if (chip_pw_tokenizer_logging) { @@ -66,7 +65,7 @@ k32w0_sdk("sdk") { } k32w0_executable("light_app") { - output_name = "chip-k32w061-light-example" + output_name = "chip-k32w0x-light-example" sources = [ "${k32w0_platform_dir}/util/LEDWidget.cpp", @@ -103,7 +102,7 @@ k32w0_executable("light_app") { cflags = [ "-Wconversion" ] - ldscript = "${k32w0_platform_dir}/app/ldscripts/chip-k32w061-linker.ld" + ldscript = "${k32w0_platform_dir}/app/ldscripts/chip-k32w0x-linker.ld" inputs = [ ldscript ] @@ -118,15 +117,24 @@ k32w0_executable("light_app") { ] } + if (chip_enable_ota_requestor) { + ldflags += [ + "-Wl,--defsym", + "-Wl,__app_load_address__=0x4000", + "-Wl,--defsym", + "-Wl,__app_stated_size__=0x99A00", + ] + } + output_dir = root_out_dir } if (chip_pw_tokenizer_logging) { pw_tokenizer_database("light_app.database") { - database = "$root_build_dir/chip-k32w061-light-example-database.bin" + database = "$root_build_dir/chip-k32w0x-light-example-database.bin" create = "binary" deps = [ ":light_app" ] - optional_paths = [ "$root_build_dir/chip-k32w061-light-example" ] + optional_paths = [ "$root_build_dir/chip-k32w0x-light-example" ] } } diff --git a/examples/lighting-app/nxp/k32w/k32w0/README.md b/examples/lighting-app/nxp/k32w/k32w0/README.md index 51385c7d0edba2..6b638d0660447a 100644 --- a/examples/lighting-app/nxp/k32w/k32w0/README.md +++ b/examples/lighting-app/nxp/k32w/k32w0/README.md @@ -174,24 +174,23 @@ will be initiated. In order to build the Project CHIP example, we recommend using a Linux distribution (the demo-application was compiled on Ubuntu 20.04). -- Download [K32W061 SDK 2.6.4 for Project CHIP](https://mcuxpresso.nxp.com/). +- Download [K32W0 SDK 2.6.6 for Project CHIP](https://mcuxpresso.nxp.com/). Creating an nxp.com account is required before being able to download the SDK. Once the account is created, login and follow the steps for downloading - SDK_2_6_4_K32W061DK6. The SDK Builder UI selection should be similar with - the one from the image below. + SDK_2_6_6_K32W061DK6 (required for K32W061 flavor). The SDK Builder UI + selection should be similar with the one from the image below. ![MCUXpresso SDK Download](../../../../platform/nxp/k32w/k32w0/doc/images/mcux-sdk-download.JPG) - Start building the application either with Secure Element or without - without Secure Element ``` -user@ubuntu:~/Desktop/git/connectedhomeip$ export NXP_K32W061_SDK_ROOT=/home/user/Desktop/SDK_2_6_4_K32W061DK6/ -user@ubuntu:~/Desktop/git/connectedhomeip$ ./third_party/nxp/k32w0_sdk/sdk_fixes/patch_k32w_sdk.sh +user@ubuntu:~/Desktop/git/connectedhomeip$ export NXP_K32W0_SDK_ROOT=/home/user/Desktop/SDK_2_6_6_K32W061DK6/ user@ubuntu:~/Desktop/git/connectedhomeip$ source ./scripts/activate.sh user@ubuntu:~/Desktop/git/connectedhomeip$ cd examples/lighting-app/nxp/k32w/k32w0 -user@ubuntu:~/Desktop/git/connectedhomeip/examples/lighting-app/nxp/k32w/k32w0$ gn gen out/debug --args="k32w0_sdk_root=\"${NXP_K32W061_SDK_ROOT}\" chip_with_OM15082=1 chip_with_ot_cli=0 is_debug=false chip_crypto=\"mbedtls\" chip_with_se05x=0 mbedtls_use_tinycrypt=true chip_pw_tokenizer_logging=true mbedtls_repo=\"//third_party/connectedhomeip/third_party/nxp/libs/mbedtls\"" +user@ubuntu:~/Desktop/git/connectedhomeip/examples/lighting-app/nxp/k32w/k32w0$ gn gen out/debug --args="k32w0_sdk_root=\"${NXP_K32W0_SDK_ROOT}\" chip_with_OM15082=1 chip_with_ot_cli=0 is_debug=false chip_crypto=\"tinycrypt\" chip_with_se05x=0 chip_pw_tokenizer_logging=true mbedtls_repo=\"//third_party/connectedhomeip/third_party/nxp/libs/mbedtls\"" user@ubuntu:~/Desktop/git/connectedhomeip/examples/lighting-app/nxp/k32w/k32w0$ ninja -C out/debug -user@ubuntu:~/Desktop/git/connectedhomeip/examples/lighting-app/nxp/k32w/k32w0$ $NXP_K32W061_SDK_ROOT/tools/imagetool/sign_images.sh out/debug/ +user@ubuntu:~/Desktop/git/connectedhomeip/examples/lighting-app/nxp/k32w/k32w0$ $NXP_K32W0_SDK_ROOT/tools/imagetool/sign_images.sh out/debug/ ``` - with Secure element @@ -201,8 +200,9 @@ user@ubuntu:~/Desktop/git/connectedhomeip/examples/lighting-app/nxp/k32w/k32w0$ Note that option chip_enable_ota_requestor=false are required for building with Secure Element. These can be changed if building without Secure Element -Note that "patch_k32w_sdk.sh" script must be run for patching the K32W061 SDK -2.6.4. + - for K32W041AM flavor: + Exactly the same steps as above but set build_for_k32w041am=1 in the gn command. + Also, select the K32W041AM SDK from the SDK Builder. Also, in case the OM15082 Expansion Board is not attached to the DK6 board, the build argument (chip_with_OM15082) inside the gn build instruction should be set @@ -225,7 +225,7 @@ pycrypto 2.6.1 pycryptodome 3.9.8 ``` -The resulting output file can be found in out/debug/chip-k32w061-light-example. +The resulting output file can be found in out/debug/chip-k32w0x-light-example. @@ -235,8 +235,8 @@ Program the firmware using the official [OpenThread Flash Instructions](https://github.com/openthread/ot-nxp/tree/main/src/k32w0/k32w061#flash-binaries). All you have to do is to replace the Openthread binaries from the above -documentation with _out/debug/chip-k32w061-light-example.bin_ if DK6Programmer -is used or with _out/debug/chip-k32w061-light-example_ if MCUXpresso is used. +documentation with _out/debug/chip-k32w0x-light-example.bin_ if DK6Programmer is +used or with _out/debug/chip-k32w0x-light-example_ if MCUXpresso is used. @@ -252,8 +252,10 @@ needed for parsing the hashed scripts. ### Detokenizer script The python3 script detokenizer.py is a script that decodes the tokenized logs -either from a file or from a serial port. The script can be used in the -following ways: +either from a file or from a serial port. It is located in the following path +`examples/platform/nxp/k32w/k32w0/scripts/detokenizer.py`. + +The script can be used in the following ways: ``` usage: detokenizer.py serial [-h] -i INPUT -d DATABASE [-o OUTPUT] @@ -268,7 +270,7 @@ the serial to decode from. The third parameter is _-d DATABASE_ and represents the path to the token database to be used for decoding. The default path is -_out/debug/chip-k32w061-light-example-database.bin_ after a successful build. +_out/debug/chip-k32w0x-light-example-database.bin_ after a successful build. The forth parameter is _-o OUTPUT_ and it represents the path to the output file where the decoded logs will be stored. This parameter is required for file usage @@ -284,7 +286,12 @@ argument _chip_pw_tokenizer_logging=true_ was used. The detokenizer script must be run inside the example's folder after a successful run of the _scripts/activate.sh_ script. The pw_tokenizer module used -by the script is loaded by the environment. +by the script is loaded by the environment. An example of running the +detokenizer script to see logs of a lighting app: + +``` +python3 ../../../../../examples/platform/nxp/k32w/k32w0/scripts/detokenizer.py serial -i /dev/ttyACM0 -d out/debug/chip-k32w0x-light-example-database.bin -o device.txt +``` @@ -318,11 +325,12 @@ Note: This solution is temporary. In order to use the tinycrypt ecc operations, use the following build arguments: - Build without Secure element (_chip_with_se05x=0_), with tinycrypt enabled - (_mbedtls_use_tinycrypt=true_) and with the `NXPmicro/mbedtls` library + (_chip_crypto=\"tinycrypt\"_) and with the `NXPmicro/mbedtls` library (_mbedtls_repo=`\"//third_party/connectedhomeip/third_party/nxp/libs/mbedtls\"`_). -To disable tinycrypt ecc operations, simply build without -_mbedtls_use_tinycrypt=true_ and without _mbedtls_repo_. +To disable tinycrypt ecc operations, simply build with _chip_crypto=\"mbedtls\"_ +and with or without _mbedtls_repo_. If used with _mbedtls_repo_ the mbedtls +implementation from `NXPmicro/mbedtls` library will be used. @@ -406,7 +414,7 @@ CD04 -> 0x4CD pages of 512-bytes (= 614,5kB) DK6Programmer can be used for flashing the application: ``` -DK6Programmer.exe -V2 -s -P 1000000 -Y -p FLASH@0x4000="chip-k32w061-light-example.bin" +DK6Programmer.exe -V2 -s -P 1000000 -Y -p FLASH@0x4000="chip-k32w0x-light-example.bin" ``` If debugging is needed, MCUXpresso can be used then for flashing the @@ -461,9 +469,9 @@ doru@computer1:~/connectedhomeip$ : ./scripts/examples/gn_build_example.sh examp Build OTA image and start the OTA Provider Application: ``` -doru@computer1:~/connectedhomeip$ : ./src/app/ota_image_tool.py create -v 0xDEAD -p 0xBEEF -vn 1 -vs "1.0" -da sha256 chip-k32w061-light-example.bin chip-k32w061-light-example.ota +doru@computer1:~/connectedhomeip$ : ./src/app/ota_image_tool.py create -v 0xDEAD -p 0xBEEF -vn 1 -vs "1.0" -da sha256 chip-k32w0x-light-example.bin chip-k32w0x-light-example.ota doru@computer1:~/connectedhomeip$ : rm -rf /tmp/chip_* -doru@computer1:~/connectedhomeip$ : ./out/ota-provider-app/chip-ota-provider-app -f chip-k32w061-light-example.ota +doru@computer1:~/connectedhomeip$ : ./out/ota-provider-app/chip-ota-provider-app -f chip-k32w0x-light-example.ota ``` Build Linux chip-tool: diff --git a/examples/lighting-app/nxp/k32w/k32w0/main/main.cpp b/examples/lighting-app/nxp/k32w/k32w0/main/main.cpp index f3c4096c4d5a8a..58091c8fba4dae 100644 --- a/examples/lighting-app/nxp/k32w/k32w0/main/main.cpp +++ b/examples/lighting-app/nxp/k32w/k32w0/main/main.cpp @@ -43,6 +43,8 @@ extern InitFunc __init_array_end; /* needed for FreeRtos Heap 4 */ uint8_t __attribute__((section(".heap"))) ucHeap[HEAP_SIZE]; +extern "C" void sched_enable(); + extern "C" void main_task(void const * argument) { CHIP_ERROR err = CHIP_NO_ERROR; @@ -85,6 +87,11 @@ extern "C" void main_task(void const * argument) goto exit; } + /* Enable the MAC scheduler after BLEManagerImpl::_Init() and V2MMAC_Enable(). + * This is needed to register properly the active protocols. + */ + sched_enable(); + err = ConnectivityMgr().SetThreadDeviceType(ConnectivityManager::kThreadDeviceType_MinimalEndDevice); if (err != CHIP_NO_ERROR) { diff --git a/examples/lock-app/nxp/k32w/k32w0/BUILD.gn b/examples/lock-app/nxp/k32w/k32w0/BUILD.gn index 744bbeb839e402..57d4498ce98ad0 100644 --- a/examples/lock-app/nxp/k32w/k32w0/BUILD.gn +++ b/examples/lock-app/nxp/k32w/k32w0/BUILD.gn @@ -22,6 +22,12 @@ import("${k32w0_sdk_build_root}/k32w0_executable.gni") import("${k32w0_sdk_build_root}/k32w0_sdk.gni") import("${chip_root}/src/crypto/crypto.gni") +import("${chip_root}/src/lib/core/core.gni") + +if (chip_pw_tokenizer_logging) { + import("//build_overrides/pigweed.gni") + import("$dir_pw_tokenizer/database.gni") +} assert(current_os == "freertos") @@ -59,7 +65,7 @@ k32w0_sdk("sdk") { } k32w0_executable("lock_app") { - output_name = "chip-k32w061-lock-example" + output_name = "chip-k32w0x-lock-example" sources = [ "${k32w0_platform_dir}/util/LEDWidget.cpp", @@ -100,15 +106,26 @@ k32w0_executable("lock_app") { output_dir = root_out_dir - ldscript = "${k32w0_platform_dir}/app/ldscripts/chip-k32w061-linker.ld" + ldscript = "${k32w0_platform_dir}/app/ldscripts/chip-k32w0x-linker.ld" inputs = [ ldscript ] ldflags = [ "-T" + rebase_path(ldscript, root_build_dir) ] } +if (chip_pw_tokenizer_logging) { + pw_tokenizer_database("lock_app.database") { + database = "$root_build_dir/chip-k32w0x-lock-example-database.bin" + create = "binary" + deps = [ ":lock_app" ] + optional_paths = [ "$root_build_dir/chip-k32w0x-lock-example" ] + } +} group("k32w0") { deps = [ ":lock_app" ] + if (chip_pw_tokenizer_logging) { + deps += [ ":lock_app.database" ] + } } group("default") { diff --git a/examples/lock-app/nxp/k32w/k32w0/README.md b/examples/lock-app/nxp/k32w/k32w0/README.md index 68be3c11ae03b9..9c1ef8ef3170f2 100644 --- a/examples/lock-app/nxp/k32w/k32w0/README.md +++ b/examples/lock-app/nxp/k32w/k32w0/README.md @@ -25,8 +25,15 @@ network. - [Flashing and debugging](#flashdebug) - [Known Issues](#knownissues) - [Testing the example](#testing-the-example) +- [Pigweed Tokenizer](#tokenizer) + - [Detokenizer script](#detokenizer) + - [Notes](#detokenizer-notes) + - [Known issues](#detokenizer-known-issues) +- [Tinycrypt ECC operations](#tinycrypt) -
+ - [Building steps](#tinycrypt-building-steps) + + @@ -165,10 +172,10 @@ will be initiated. In order to build the Project CHIP example, we recommend using a Linux distribution (the demo-application was compiled on Ubuntu 20.04). -- Download [K32W061 SDK 2.6.4 for Project CHIP](https://mcuxpresso.nxp.com/). +- Download [K32W061 SDK 2.6.6 for Project CHIP](https://mcuxpresso.nxp.com/). Creating an nxp.com account is required before being able to download the SDK. Once the account is created, login and follow the steps for downloading - SDK_2_6_4_K32W061DK6. The SDK Builder UI selection should be similar with + SDK_2_6_6_K32W061DK6. The SDK Builder UI selection should be similar with the one from the image below. ![MCUXpresso SDK Download](../../../../platform/nxp/k32w/k32w0/doc/images/mcux-sdk-download.JPG) @@ -177,25 +184,16 @@ distribution (the demo-application was compiled on Ubuntu 20.04). - without Secure Element ``` -user@ubuntu:~/Desktop/git/connectedhomeip$ export NXP_K32W061_SDK_ROOT=/home/user/Desktop/SDK_2_6_4_K32W061DK6/ -user@ubuntu:~/Desktop/git/connectedhomeip$ ./third_party/nxp/k32w0_sdk/sdk_fixes/patch_k32w_sdk.sh +user@ubuntu:~/Desktop/git/connectedhomeip$ export NXP_K32W0_SDK_ROOT=/home/user/Desktop/SDK_2_6_6_K32W061DK6/ user@ubuntu:~/Desktop/git/connectedhomeip$ source ./scripts/activate.sh user@ubuntu:~/Desktop/git/connectedhomeip$ cd examples/lock-app/nxp/k32w/k32w0/ -user@ubuntu:~/Desktop/git/connectedhomeip/examples/lock-app/nxp/k32w/k32w0$ gn gen out/debug --args="k32w0_sdk_root=\"${NXP_K32W061_SDK_ROOT}\" chip_with_OM15082=1 chip_with_ot_cli=0 is_debug=false chip_crypto=\"mbedtls\" chip_with_se05x=0" +user@ubuntu:~/Desktop/git/connectedhomeip/examples/lock-app/nxp/k32w/k32w0$ gn gen out/debug --args="k32w0_sdk_root=\"${NXP_K32W0_SDK_ROOT}\" chip_with_OM15082=1 chip_with_ot_cli=0 is_debug=false chip_crypto=\"tinycrypt\" chip_with_se05x=0 chip_pw_tokenizer_logging=true mbedtls_repo=\"//third_party/connectedhomeip/third_party/nxp/libs/mbedtls\"" user@ubuntu:~/Desktop/git/connectedhomeip/examples/lock-app/nxp/k32w/k32w0$ ninja -C out/debug -user@ubuntu:~/Desktop/git/connectedhomeip/examples/lock-app/nxp/k32w/k32w0$ $NXP_K32W061_SDK_ROOT/tools/imagetool/sign_images.sh out/debug/ +user@ubuntu:~/Desktop/git/connectedhomeip/examples/lock-app/nxp/k32w/k32w0$ $NXP_K32W0_SDK_ROOT/tools/imagetool/sign_images.sh out/debug/ ``` - with Secure element - Exactly the same steps as above but set chip_with_se05x=1 in the gn command - and add arguments chip_pw_tokenizer_logging=true chip_enable_ota_requestor=false - -Note that options chip_pw_tokenizer_logging=true and -chip_enable_ota_requestor=false are required for building with Secure Element. -These can be changed if building without Secure Element - -Note that "patch_k32w_sdk.sh" script must be run for patching the K32W061 SDK -2.6.4. + Exactly the same steps as above but set chip_with_se05x=1 in the gn command. Also, in case the OM15082 Expansion Board is not attached to the DK6 board, the build argument (chip_with_OM15082) inside the gn build instruction should be set @@ -218,7 +216,7 @@ pycrypto 2.6.1 pycryptodome 3.9.8 ``` -The resulting output file can be found in out/debug/chip-k32w061-lock-example. +The resulting output file can be found in out/debug/chip-k32w0x-lock-example. @@ -228,8 +226,8 @@ Program the firmware using the official [OpenThread Flash Instructions](https://github.com/openthread/ot-nxp/tree/main/src/k32w0/k32w061#flash-binaries). All you have to do is to replace the Openthread binaries from the above -documentation with _out/debug/chip-k32w061-lock-example.bin_ if DK6Programmer is -used or with _out/debug/chip-k32w061-lock-example_ if MCUXpresso is used. +documentation with _out/debug/chip-k32w0x-lock-example.bin_ if DK6Programmer is +used or with _out/debug/chip-k32w0x-lock-example_ if MCUXpresso is used. @@ -282,3 +280,97 @@ for step-by-step instructions. See [Unlocking the Future of Project CHIP Webinar](https://www.nxp.com/design/training/unlocking-the-future-of-project-chip:TIP-EEE-UNLOCKING-THE-FUTURE-OF-PROJECT-CHIP) for an in-depth analysis of NXP capabilities for Project CHIP. + + + +## Pigweed tokenizer + +The tokenizer is a pigweed module that allows hashing the strings. This greatly +reduces the flash needed for logs. The module can be enabled by building with +the gn argument _chip_pw_tokenizer_logging=true_. The detokenizer script is +needed for parsing the hashed scripts. + + + +### Detokenizer script + +The python3 script detokenizer.py is a script that decodes the tokenized logs +either from a file or from a serial port. It is located in the following path +`examples/platform/nxp/k32w/k32w0/scripts/detokenizer.py`. + +The script can be used in the following ways: + +``` +usage: detokenizer.py serial [-h] -i INPUT -d DATABASE [-o OUTPUT] +usage: detokenizer.py file [-h] -i INPUT -d DATABASE -o OUTPUT +``` + +The first parameter is either _serial_ or _file_ and it selects between decoding +from a file or from a serial port. + +The second parameter is _-i INPUT_ and it must se set to the path of the file or +the serial to decode from. + +The third parameter is _-d DATABASE_ and represents the path to the token +database to be used for decoding. The default path is +_out/debug/chip-k32w0x-lock-example-database.bin_ after a successful build. + +The forth parameter is _-o OUTPUT_ and it represents the path to the output file +where the decoded logs will be stored. This parameter is required for file usage +and optional for serial usage. If not provided when used with serial port, it +will show the decoded log only at the stdout and not save it to file. + + + +### Notes + +The token database is created automatically after building the binary if the +argument _chip_pw_tokenizer_logging=true_ was used. + +The detokenizer script must be run inside the example's folder after a +successful run of the _scripts/activate.sh_ script. The pw_tokenizer module used +by the script is loaded by the environment. An example of running the +detokenizer script to see logs of a lock app: + +``` +python3 ../../../../../examples/platform/nxp/k32w/k32w0/scripts/detokenizer.py serial -i /dev/ttyACM0 -d out/debug/chip-k32w0x-lock-example-database.bin -o device.txt +``` + + + +### Known issues + +The building process will not update the token database if it already exists. In +case that new strings are added and the database already exists in the output +folder, it must be deleted so that it will be recreated at the next build. + +Not all tokens will be decoded. This is due to a gcc/pw_tokenizer issue. The +pw_tokenizer creates special elf sections using attributes where the tokens and +strings will be stored. This sections will be used by the database creation +script. For template C++ functions, gcc ignores these attributes and places all +the strings by default in the .rodata section. As a result the database creation +script won't find them in the special-created sections. + +If run, closed and rerun with the serial option on the same serial port, the +detokenization script will get stuck and not show any logs. The solution is to +unplug and plug the board and then rerun the script. + + + +## Tinycrypt ECC operations + + + +### Building steps + +Note: This solution is temporary. + +In order to use the tinycrypt ecc operations, use the following build arguments: + +- Build without Secure element (_chip_with_se05x=0_), with tinycrypt enabled + (_chip_crypto=\"tinycrypt\"_) and with the `NXPmicro/mbedtls` library + (_mbedtls_repo=`\"//third_party/connectedhomeip/third_party/nxp/libs/mbedtls\"`_). + +To disable tinycrypt ecc operations, simply build with _chip_crypto=\"mbedtls\"_ +and with or without _mbedtls_repo_. If used with _mbedtls_repo_ the mbedtls +implementation from `NXPmicro/mbedtls` library will be used. diff --git a/examples/lock-app/nxp/k32w/k32w0/args.gni b/examples/lock-app/nxp/k32w/k32w0/args.gni index a1b757c6612439..2ace8356337891 100644 --- a/examples/lock-app/nxp/k32w/k32w0/args.gni +++ b/examples/lock-app/nxp/k32w/k32w0/args.gni @@ -20,5 +20,3 @@ k32w0_sdk_target = get_label_info(":sdk", "label_no_toolchain") chip_stack_lock_tracking = "fatal" chip_enable_ble = true - -chip_progress_logging = false diff --git a/examples/lock-app/nxp/k32w/k32w0/main/AppTask.cpp b/examples/lock-app/nxp/k32w/k32w0/main/AppTask.cpp index 015784f6d6e8dd..3a78c9c7f632c4 100644 --- a/examples/lock-app/nxp/k32w/k32w0/main/AppTask.cpp +++ b/examples/lock-app/nxp/k32w/k32w0/main/AppTask.cpp @@ -166,12 +166,14 @@ CHIP_ERROR AppTask::Init() void LockOpenThreadTask(void) { + PWR_DisallowDeviceToSleep(); chip::DeviceLayer::ThreadStackMgr().LockThreadStack(); } void UnlockOpenThreadTask(void) { chip::DeviceLayer::ThreadStackMgr().UnlockThreadStack(); + PWR_AllowDeviceToSleep(); } void AppTask::InitServer(intptr_t arg) @@ -728,9 +730,10 @@ void AppTask::DispatchEvent(AppEvent * aEvent) { aEvent->Handler(aEvent->param); } + else #endif - if (aEvent->Handler) + if (aEvent->Handler) { aEvent->Handler(aEvent); } diff --git a/examples/lock-app/nxp/k32w/k32w0/main/main.cpp b/examples/lock-app/nxp/k32w/k32w0/main/main.cpp index 216f98328503ee..a792030a7c78b0 100644 --- a/examples/lock-app/nxp/k32w/k32w0/main/main.cpp +++ b/examples/lock-app/nxp/k32w/k32w0/main/main.cpp @@ -36,8 +36,11 @@ using namespace ::chip::Inet; using namespace ::chip::DeviceLayer; using namespace ::chip::Logging; +#define ENABLE_LOW_POWER_LOGS 0 + #if defined(cPWR_UsePowerDownMode) && (cPWR_UsePowerDownMode) #include "Keyboard.h" +#include "OtaSupport.h" #include "PWR_Configuration.h" #include "PWR_Interface.h" #include "RNG_Interface.h" @@ -46,6 +49,8 @@ using namespace ::chip::Logging; #include "radio.h" #endif +#include "MacSched.h" + typedef void (*InitFunc)(void); extern InitFunc __init_array_start; extern InitFunc __init_array_end; @@ -55,6 +60,7 @@ extern InitFunc __init_array_end; extern "C" void vMMAC_IntHandlerBbc(); extern "C" void vMMAC_IntHandlerPhy(); extern "C" void BOARD_SetClockForPowerMode(void); +extern "C" void stopM2(); static void dm_switch_wakeupCallBack(void); static void dm_switch_preSleepCallBack(void); @@ -77,6 +83,8 @@ static sDualModeAppStates dualModeStates; #define THREAD_WARM_BOOT_INIT_DURATION_DEFAULT_VALUE 4000 #endif +extern "C" void sched_enable(); + /* needed for FreeRtos Heap 4 */ uint8_t __attribute__((section(".heap"))) ucHeap[HEAP_SIZE]; @@ -100,7 +108,9 @@ extern "C" void main_task(void const * argument) #if defined(cPWR_UsePowerDownMode) && (cPWR_UsePowerDownMode) PWR_Init(); - PWR_vAddRamRetention((uint32_t) &ucHeap[0], sizeof(ucHeap)); + /* Internal - MATTER-303: keep in retention the entire RAM1 for the moment */ + PWR_vAddRamRetention((uint32_t) 0x4020000, 0x10000); + PWR_RegisterLowPowerExitCallback(dm_switch_wakeupCallBack); PWR_RegisterLowPowerEnterCallback(dm_switch_preSleepCallBack); @@ -132,6 +142,11 @@ extern "C" void main_task(void const * argument) goto exit; } + /* Enable the MAC scheduler after BLEManagerImpl::_Init() and V2MMAC_Enable(). + * This is needed to register properly the active protocols. + */ + sched_enable(); + #if defined(cPWR_UsePowerDownMode) && (cPWR_UsePowerDownMode) dualModeStates.threadWarmBootInitTime = THREAD_WARM_BOOT_INIT_DURATION_DEFAULT_VALUE; dualModeStates.threadInitialized = TRUE; @@ -197,10 +212,15 @@ uint32_t dm_switch_get15_4InitWakeUpTime(void) extern "C" bleResult_t App_PostCallbackMessage(appCallbackHandler_t handler, appCallbackParam_t param) { AppEvent event; - event.Type = AppEvent::kEventType_Lp; + event.Type = AppEvent::kEventType_Lp; + event.Handler = handler; event.param = param; +#if ENABLE_LOW_POWER_LOGS + K32W_LOG("App_PostCallbackMessage %d", (uint32_t) param); +#endif + GetAppTask().PostEvent(&event); return gBleSuccess_c; @@ -210,6 +230,11 @@ static void dm_switch_wakeupCallBack(void) { BOARD_SetClockForWakeup(); +#if ENABLE_LOW_POWER_LOGS + K32W_LOG("dm_switch_wakeupCallBack"); + K32W_LOG("Warm up time actual value: %d", dualModeStates.threadWarmBootInitTime); +#endif + RNG_Init(); SecLib_Init(); @@ -218,25 +243,37 @@ static void dm_switch_wakeupCallBack(void) PWR_WakeupReason_t wakeReason = PWR_GetWakeupReason(); if (wakeReason.Bits.FromBLE_LLTimer == 1) { - SWITCH_DBG_LOG("woken up from LL"); +#if ENABLE_LOW_POWER_LOGS + K32W_LOG("woken up from LL"); +#endif } else if (wakeReason.Bits.FromKeyBoard == 1) { - SWITCH_DBG_LOG("woken up from FromKeyBoard"); +#if ENABLE_LOW_POWER_LOGS + K32W_LOG("woken up from FromKeyBoard"); +#endif } else if (wakeReason.Bits.FromTMR == 1) { - SWITCH_DBG_LOG("woken up from TMR"); +#if ENABLE_LOW_POWER_LOGS + K32W_LOG("woken up from TMR"); +#endif } dm_lp_wakeup(); } static void dm_switch_preSleepCallBack(void) { - SWITCH_DBG_LOG("sleeping"); +#if ENABLE_LOW_POWER_LOGS + K32W_LOG("dm_switch_preSleepCallBack"); +#endif if (dualModeStates.threadInitialized) { + /* stop the internal MAC Scheduler timer */ + stopM2(); + /* disable the MAC scheduler */ + sched_disable(); otPlatRadioDisable(NULL); dualModeStates.threadInitialized = FALSE; } @@ -251,6 +288,12 @@ static void dm_switch_preSleepCallBack(void) BOARD_SetClockForPowerMode(); } +extern "C" void vDynStopAll(void) +{ + vDynRequestState(E_DYN_SLAVE, E_DYN_STATE_OFF); + vDynRequestState(E_DYN_MASTER, E_DYN_STATE_OFF); +} + void dm_switch_init15_4AfterWakeUp(void) { uint32_t tick1 = 0; @@ -271,8 +314,13 @@ void dm_switch_init15_4AfterWakeUp(void) { tick2 = PWR_Get32kTimestamp(); dualModeStates.threadWarmBootInitTime = ((tick2 - tick1) * 15625u) >> 9; + /* Add a margin of 1 ms */ dualModeStates.threadWarmBootInitTime += 1000; + +#if ENABLE_LOW_POWER_LOGS + K32W_LOG("Calibration: %d", dualModeStates.threadWarmBootInitTime); +#endif } } @@ -287,6 +335,8 @@ static void ThreadExitSleep() /* Radio must be re-enabled after waking up from sleep. * The module is completely disabled in power down mode */ otPlatRadioEnable(NULL); + sched_enable(); + dualModeStates.threadInitialized = TRUE; /* wake up the Thread stack and check if any processing needs to be done */ diff --git a/examples/platform/nxp/k32w/k32w0/app/ldscripts/chip-k32w061-linker.ld b/examples/platform/nxp/k32w/k32w0/app/ldscripts/chip-k32w0x-linker.ld similarity index 93% rename from examples/platform/nxp/k32w/k32w0/app/ldscripts/chip-k32w061-linker.ld rename to examples/platform/nxp/k32w/k32w0/app/ldscripts/chip-k32w0x-linker.ld index 3bb028d183d9dd..359a9ef790336d 100644 --- a/examples/platform/nxp/k32w/k32w0/app/ldscripts/chip-k32w061-linker.ld +++ b/examples/platform/nxp/k32w/k32w0/app/ldscripts/chip-k32w0x-linker.ld @@ -28,7 +28,7 @@ /** * @file - * GCC linker script for K32W061. + * GCC linker script for K32W061/K32W041. */ OUTPUT_FORMAT ("elf32-littlearm", "elf32-bigarm", "elf32-littlearm") @@ -58,13 +58,15 @@ m_app_start = DEFINED(__app_load_address__) ? __app_load_address__ : m_app_meta_data = 0x400; /* 640K (Total Flash size) - 16K (SSBL + SSBL update region) - 8.5K (PSECT) - m_app_meta_data */ -m_app_size = DEFINED(__app_stated_size__) ? __app_stated_size__ : 0x9FC00; +m_app_size = DEFINED(__app_stated_size__) ? __app_stated_size__ : 0x9DE00; MEMORY { - Flash640 (rx) : ORIGIN = m_app_start, LENGTH = m_app_size - RAM0 (rwx) : ORIGIN = 0x4000400, LENGTH = 0x0015c00 /* 87K bytes (alias RAM) */ - RAM1 (rwx) : ORIGIN = 0x4020000, LENGTH = 0x10000 /* 64K bytes (alias RAM2) */ + Flash640 (rx) : ORIGIN = m_app_start, LENGTH = m_app_size + + SCRATCH_RAM(rwx) : ORIGIN = 0x4000000, LENGTH = 0x400 /* 1K bytes (alias SCRATCH_RAM) */ + RAM0 (rwx) : ORIGIN = 0x4000400, LENGTH = 0x0015c00 /* 87K bytes (alias RAM) */ + RAM1 (rwx) : ORIGIN = 0x4020000, LENGTH = 0x10000 /* 64K bytes (alias RAM2) */ } /* Define a symbol for the top of each memory region */ @@ -234,6 +236,13 @@ SECTIONS . = ALIGN(4); __interrupts_ram_end__ = .; /* Define a global symbol at data end */ } > RAM0 + .scratch_area (NOLOAD): ALIGN(4) + { + __scratch_area_start__ = .; + . = ALIGN(4) ; + . += 0x400; + __scratch_area_top__ = .; + } > SCRATCH_RAM /* MAIN DATA SECTION */ .uninit_RESERVED : ALIGN(4) @@ -340,6 +349,8 @@ SECTIONS PROVIDE(Chip_LOWPOWER_ChipSoftwareReset = 0x03003fa1); PROVIDE(_pvHeapStart = _heap); PROVIDE(_pvHeapLimit = _pvHeapStart + (HEAP_SIZE)); + PROVIDE(_scratch_buf_start = __scratch_area_start__); + PROVIDE(_scratch_buf_end = __scratch_area_top__); __StackLimit = _vStackTop - STACK_SIZE; } diff --git a/examples/platform/nxp/k32w/k32w0/app/project_include/OpenThreadConfig.h b/examples/platform/nxp/k32w/k32w0/app/project_include/OpenThreadConfig.h index 667574786bb91e..ef95988da9ab24 100644 --- a/examples/platform/nxp/k32w/k32w0/app/project_include/OpenThreadConfig.h +++ b/examples/platform/nxp/k32w/k32w0/app/project_include/OpenThreadConfig.h @@ -96,6 +96,8 @@ #undef OPENTHREAD_CONFIG_PLATFORM_CSL_UNCERT +#define UART_USE_SERIAL_MGR 1 + //#define OPENTHREAD_CONFIG_LOG_LEVEL OT_LOG_LEVEL_DEBG // Use the NXP-supplied default platform configuration for remainder diff --git a/examples/platform/nxp/k32w/k32w0/app/support/FreeRtosHooks.c b/examples/platform/nxp/k32w/k32w0/app/support/FreeRtosHooks.c index 5bdb70c6ee21fc..e6a445c1c086ff 100644 --- a/examples/platform/nxp/k32w/k32w0/app/support/FreeRtosHooks.c +++ b/examples/platform/nxp/k32w/k32w0/app/support/FreeRtosHooks.c @@ -236,7 +236,14 @@ extern void OTAIdleActivities(void); void vApplicationIdleHook(void) { + // Data queued by PDM will be written to external flash + // when PDM_vIdleTask is called. Interrupts are disabled + // to ensure there is no context switch during the actual + // writing, thus avoiding race conditions. + OSA_InterruptDisable(); PDM_vIdleTask(PDM_MAX_WRITES_INFINITE); + OSA_InterruptEnable(); + OTAIdleActivities(); BOARD_ActionOnIdle(); } diff --git a/examples/lighting-app/nxp/k32w/k32w0/detokenizer.py b/examples/platform/nxp/k32w/k32w0/scripts/detokenizer.py similarity index 100% rename from examples/lighting-app/nxp/k32w/k32w0/detokenizer.py rename to examples/platform/nxp/k32w/k32w0/scripts/detokenizer.py diff --git a/examples/shell/nxp/k32w/k32w0/BUILD.gn b/examples/shell/nxp/k32w/k32w0/BUILD.gn index 505373a42bf860..f6c4039783a5dd 100644 --- a/examples/shell/nxp/k32w/k32w0/BUILD.gn +++ b/examples/shell/nxp/k32w/k32w0/BUILD.gn @@ -57,7 +57,7 @@ k32w0_sdk("sdk") { } k32w0_executable("shell_app") { - output_name = "chip-k32w061-shell-example" + output_name = "chip-k32w0x-shell-example" sources = [ "${k32w0_platform_dir}/util/LEDWidget.cpp", @@ -79,7 +79,7 @@ k32w0_executable("shell_app") { output_dir = root_out_dir - ldscript = "${k32w0_platform_dir}/app/ldscripts/chip-k32w061-linker.ld" + ldscript = "${k32w0_platform_dir}/app/ldscripts/chip-k32w0x-linker.ld" inputs = [ ldscript ] diff --git a/gn_build.sh b/gn_build.sh index 86e2ff6889c6d3..0615a1833ef40d 100755 --- a/gn_build.sh +++ b/gn_build.sh @@ -154,14 +154,14 @@ fi # K32W SDK setup k32w_sdk_args="" -if [[ -d "$NXP_K32W061_SDK_ROOT" ]]; then - k32w_sdk_args+="k32w0_sdk_root=\"$NXP_K32W061_SDK_ROOT\"" +if [[ -d "$NXP_K32W0_SDK_ROOT" ]]; then + k32w_sdk_args+="k32w0_sdk_root=\"$NXP_K32W0_SDK_ROOT\"" extra_args+=" $k32w0_sdk_args enable_k32w_builds=true" fi echo -if [[ ! -d "$NXP_K32W061_SDK_ROOT" ]]; then - echo "Hint: Set \$NXP_K32W061_SDK_ROOT to enable building for K32W061" +if [[ ! -d "$NXP_K32W0_SDK_ROOT" ]]; then + echo "Hint: Set \$NXP_K32W0_SDK_ROOT to enable building for K32W061" else echo 'To build the K32W lock sample as a standalone project': echo "(cd $CHIP_ROOT/examples/lock-app/nxp/k32w/k32w0; gn gen out/debug --args='$k32w_sdk_args'; ninja -C out/debug)" diff --git a/scripts/build/build/targets.py b/scripts/build/build/targets.py index a4d3d859558bca..0ae6f05a9f328e 100755 --- a/scripts/build/build/targets.py +++ b/scripts/build/build/targets.py @@ -534,7 +534,7 @@ def K32WTargets(): target = Target('k32w', K32WBuilder) yield target.Extend('light-ota-se', app=K32WApp.LIGHT, release=True, disable_ble=True, se05x=True).GlobBlacklist("Only on demand build") - yield target.Extend('light-release-no-ota', app=K32WApp.LIGHT, tokenizer=True, disable_ota=True, release=True) + yield target.Extend('light-release-no-ota', app=K32WApp.LIGHT, tokenizer=True, disable_ota=True, release=True, tinycrypt=True) yield target.Extend('shell-release', app=K32WApp.SHELL, release=True) yield target.Extend('lock-release', app=K32WApp.LOCK, release=True) yield target.Extend('lock-low-power-release', app=K32WApp.LOCK, diff --git a/scripts/build/builders/k32w.py b/scripts/build/builders/k32w.py index ea446ec8a40e88..39828157e934eb 100644 --- a/scripts/build/builders/k32w.py +++ b/scripts/build/builders/k32w.py @@ -35,11 +35,13 @@ def ExampleName(self): def AppNamePrefix(self): if self == K32WApp.LIGHT: - return 'chip-k32w061-light-example' + return 'chip-k32w0x-light-example' elif self == K32WApp.LOCK: - return 'chip-k32w061-lock-example' + return 'chip-k32w0x-lock-example' elif self == K32WApp.SHELL: - return 'chip-k32w061-shell-example' + return 'chip-k32w0x-shell-example' + elif self == K32WApp.CONTACT: + return 'chip-k32w0x-contact-example' else: raise Exception('Unknown app type: %r' % self) @@ -58,7 +60,8 @@ def __init__(self, tokenizer: bool = False, disable_ble: bool = False, disable_ota: bool = False, - se05x: bool = False): + se05x: bool = False, + tinycrypt: bool = False): super(K32WBuilder, self).__init__( root=app.BuildRoot(root), runner=runner) @@ -70,10 +73,11 @@ def __init__(self, self.disable_ble = disable_ble self.disable_ota = disable_ota self.se05x = se05x + self.tinycrypt = tinycrypt def GnBuildArgs(self): args = [ - 'k32w0_sdk_root="%s"' % os.environ['NXP_K32W061_SDK_ROOT'], + 'k32w0_sdk_root="%s"' % os.environ['NXP_K32W0_SDK_ROOT'], ] if self.low_power: @@ -96,6 +100,9 @@ def GnBuildArgs(self): if self.se05x: args.append('chip_with_se05x=true') + if self.tinycrypt: + args.append('chip_crypto=\"tinycrypt\" mbedtls_repo=\"//third_party/connectedhomeip/third_party/nxp/libs/mbedtls\"') + return args def generate(self): diff --git a/scripts/build/test.py b/scripts/build/test.py index 5559847adf50d9..056d34166a40ef 100644 --- a/scripts/build/test.py +++ b/scripts/build/test.py @@ -44,7 +44,7 @@ def build_actual_output(root: str, out: str, args: List[str]) -> List[str]: 'TIZEN_SDK_SYSROOT': 'TEST_TIZEN_SDK_SYSROOT', 'TELINK_ZEPHYR_SDK_DIR': 'TELINK_ZEPHYR_SDK_DIR', 'SYSROOT_AARCH64': 'SYSROOT_AARCH64', - 'NXP_K32W061_SDK_ROOT': 'TEST_NXP_K32W061_SDK_ROOT', + 'NXP_K32W0_SDK_ROOT': 'TEST_NXP_K32W0_SDK_ROOT', 'IMX_SDK_ROOT': 'IMX_SDK_ROOT', 'TI_SYSCONFIG_ROOT': 'TEST_TI_SYSCONFIG_ROOT', }) diff --git a/scripts/build/testdata/build_all_except_host.txt b/scripts/build/testdata/build_all_except_host.txt index fa887aca49fb73..e365f295f08c20 100644 --- a/scripts/build/testdata/build_all_except_host.txt +++ b/scripts/build/testdata/build_all_except_host.txt @@ -858,27 +858,27 @@ gn gen --check --fail-on-unused-args --export-compile-commands --root={root}/exa {root}/third_party/nxp/k32w0_sdk/sdk_fixes/patch_k32w_sdk.sh # Generating k32w-light-ota-se -gn gen --check --fail-on-unused-args --export-compile-commands --root={root}/examples/lighting-app/nxp/k32w/k32w0 '--args=k32w0_sdk_root="TEST_NXP_K32W061_SDK_ROOT" chip_with_low_power=0 is_debug=false chip_enable_ble=false chip_with_se05x=true' {out}/k32w-light-ota-se +gn gen --check --fail-on-unused-args --export-compile-commands --root={root}/examples/lighting-app/nxp/k32w/k32w0 '--args=k32w0_sdk_root="TEST_NXP_K32W0_SDK_ROOT" chip_with_low_power=0 is_debug=false chip_enable_ble=false chip_with_se05x=true' {out}/k32w-light-ota-se {root}/third_party/nxp/k32w0_sdk/sdk_fixes/patch_k32w_sdk.sh # Generating k32w-light-release-no-ota -gn gen --check --fail-on-unused-args --export-compile-commands --root={root}/examples/lighting-app/nxp/k32w/k32w0 '--args=k32w0_sdk_root="TEST_NXP_K32W061_SDK_ROOT" chip_with_low_power=0 chip_pw_tokenizer_logging=true is_debug=false chip_enable_ota_requestor=false' {out}/k32w-light-release-no-ota +gn gen --check --fail-on-unused-args --export-compile-commands --root={root}/examples/lighting-app/nxp/k32w/k32w0 '--args=k32w0_sdk_root="TEST_NXP_K32W0_SDK_ROOT" chip_with_low_power=0 chip_pw_tokenizer_logging=true is_debug=false chip_enable_ota_requestor=false chip_crypto="tinycrypt" mbedtls_repo="//third_party/connectedhomeip/third_party/nxp/libs/mbedtls"' {out}/k32w-light-release-no-ota {root}/third_party/nxp/k32w0_sdk/sdk_fixes/patch_k32w_sdk.sh # Generating k32w-lock-low-power-release -gn gen --check --fail-on-unused-args --export-compile-commands --root={root}/examples/lock-app/nxp/k32w/k32w0 '--args=k32w0_sdk_root="TEST_NXP_K32W061_SDK_ROOT" chip_with_low_power=1 is_debug=false' {out}/k32w-lock-low-power-release +gn gen --check --fail-on-unused-args --export-compile-commands --root={root}/examples/lock-app/nxp/k32w/k32w0 '--args=k32w0_sdk_root="TEST_NXP_K32W0_SDK_ROOT" chip_with_low_power=1 is_debug=false' {out}/k32w-lock-low-power-release {root}/third_party/nxp/k32w0_sdk/sdk_fixes/patch_k32w_sdk.sh # Generating k32w-lock-release -gn gen --check --fail-on-unused-args --export-compile-commands --root={root}/examples/lock-app/nxp/k32w/k32w0 '--args=k32w0_sdk_root="TEST_NXP_K32W061_SDK_ROOT" chip_with_low_power=0 is_debug=false' {out}/k32w-lock-release +gn gen --check --fail-on-unused-args --export-compile-commands --root={root}/examples/lock-app/nxp/k32w/k32w0 '--args=k32w0_sdk_root="TEST_NXP_K32W0_SDK_ROOT" chip_with_low_power=0 is_debug=false' {out}/k32w-lock-release {root}/third_party/nxp/k32w0_sdk/sdk_fixes/patch_k32w_sdk.sh # Generating k32w-shell-release -gn gen --check --fail-on-unused-args --export-compile-commands --root={root}/examples/shell/nxp/k32w/k32w0 '--args=k32w0_sdk_root="TEST_NXP_K32W061_SDK_ROOT" chip_with_low_power=0 is_debug=false' {out}/k32w-shell-release +gn gen --check --fail-on-unused-args --export-compile-commands --root={root}/examples/shell/nxp/k32w/k32w0 '--args=k32w0_sdk_root="TEST_NXP_K32W0_SDK_ROOT" chip_with_low_power=0 is_debug=false' {out}/k32w-shell-release # Generating config mbed-CY8CPROTO_062_4343W-all-clusters-debug mbed-tools configure -t GCC_ARM -m CY8CPROTO_062_4343W -p {root}/examples/all-clusters-app/mbed -o {out}/mbed-CY8CPROTO_062_4343W-all-clusters-debug --mbed-os-path {root}/third_party/mbed-os/repo diff --git a/scripts/examples/k32w_se_example.sh b/scripts/examples/k32w_se_example.sh index 27c0b5a29fe48c..9815dc9f49a06c 100755 --- a/scripts/examples/k32w_se_example.sh +++ b/scripts/examples/k32w_se_example.sh @@ -27,5 +27,5 @@ env "$(dirname "$0")"/../../third_party/nxp/k32w0_sdk/sdk_fixes/patch_k32w_sdk.sh -gn gen --check --fail-on-unused-args --root="$1" "$2" --args="k32w0_sdk_root=\"$NXP_K32W061_SDK_ROOT\" is_debug=false chip_crypto=\"mbedtls\" chip_with_se05x=1" +gn gen --check --fail-on-unused-args --root="$1" "$2" --args="k32w0_sdk_root=\"$NXP_K32W0_SDK_ROOT\" is_debug=false chip_crypto=\"mbedtls\" chip_with_se05x=1" ninja -C "$2" diff --git a/src/crypto/BUILD.gn b/src/crypto/BUILD.gn index 359bb9d289cf0a..a5e176c3fe5212 100644 --- a/src/crypto/BUILD.gn +++ b/src/crypto/BUILD.gn @@ -57,6 +57,8 @@ if (chip_crypto == "openssl") { import("//build_overrides/boringssl.gni") } else if (chip_crypto == "mbedtls") { import("//build_overrides/mbedtls.gni") +} else if (chip_crypto == "tinycrypt") { + import("//build_overrides/mbedtls.gni") } static_library("crypto") { @@ -99,6 +101,9 @@ static_library("crypto") { # BoringSSL is close enough to OpenSSL that isd uses same PAL, with minor #ifdef differences sources += [ "CHIPCryptoPALOpenSSL.cpp" ] public_deps += [ "${boringssl_root}:boringssl" ] + } else if (chip_crypto == "tinycrypt") { + sources += [ "CHIPCryptoPALTinyCrypt.cpp" ] + public_deps += [ "${mbedtls_root}:mbedtls" ] } else { assert(false, "Invalid CHIP crypto") } diff --git a/src/crypto/CHIPCryptoPALTinyCrypt.cpp b/src/crypto/CHIPCryptoPALTinyCrypt.cpp new file mode 100644 index 00000000000000..2b86f418cb27d3 --- /dev/null +++ b/src/crypto/CHIPCryptoPALTinyCrypt.cpp @@ -0,0 +1,1500 @@ +/* + * + * Copyright (c) 2020-2022 Project CHIP Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/** + * @file + * mbedTLS based implementation of CHIP crypto primitives + */ + +#include "CHIPCryptoPAL.h" + +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#if defined(MBEDTLS_X509_CRT_PARSE_C) +#include +#endif // defined(MBEDTLS_X509_CRT_PARSE_C) +#include +#include +#include + +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +namespace chip { +namespace Crypto { + +#define MAX_ERROR_STR_LEN 128 +#define NUM_BYTES_IN_SHA256_HASH 32 + +// In mbedTLS 3.0.0 direct access to structure fields was replaced with using MBEDTLS_PRIVATE macro. +#if (MBEDTLS_VERSION_NUMBER >= 0x03000000) +#define CHIP_CRYPTO_PAL_PRIVATE(x) MBEDTLS_PRIVATE(x) +#else +#define CHIP_CRYPTO_PAL_PRIVATE(x) x +#endif + +#if (MBEDTLS_VERSION_NUMBER >= 0x03000000 && MBEDTLS_VERSION_NUMBER < 0x03010000) +#define CHIP_CRYPTO_PAL_PRIVATE_X509(x) MBEDTLS_PRIVATE(x) +#else +#define CHIP_CRYPTO_PAL_PRIVATE_X509(x) x +#endif + +typedef struct +{ + bool mInitialized; + bool mDRBGSeeded; + mbedtls_ctr_drbg_context mDRBGCtxt; + mbedtls_entropy_context mEntropy; +} EntropyContext; + +static EntropyContext gsEntropyContext; + +static void _log_mbedTLS_error(int error_code) +{ + if (error_code != 0 && error_code != UECC_SUCCESS) + { +#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; +} + +static bool _isValidKeyLength(size_t length) +{ + // 16 bytes key for AES-CCM-128, 32 for AES-CCM-256 + if (length == 16 || length == 32) + { + 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 uint8_t * key, size_t key_length, const uint8_t * nonce, size_t nonce_length, uint8_t * ciphertext, + uint8_t * tag, size_t tag_length) +{ + CHIP_ERROR error = CHIP_NO_ERROR; + int result = 1; + + mbedtls_ccm_context context; + mbedtls_ccm_init(&context); + + VerifyOrExit(plaintext != nullptr || plaintext_length == 0, error = CHIP_ERROR_INVALID_ARGUMENT); + VerifyOrExit(ciphertext != nullptr || plaintext_length == 0, error = CHIP_ERROR_INVALID_ARGUMENT); + VerifyOrExit(key != nullptr, error = CHIP_ERROR_INVALID_ARGUMENT); + VerifyOrExit(_isValidKeyLength(key_length), error = CHIP_ERROR_UNSUPPORTED_ENCRYPTION_TYPE); + 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 = key_length * number of bits in a byte (8) + // Cast is safe because we called _isValidKeyLength above. + result = + mbedtls_ccm_setkey(&context, MBEDTLS_CIPHER_ID_AES, Uint8::to_const_uchar(key), static_cast(key_length * 8)); + VerifyOrExit(result == 0, error = CHIP_ERROR_INTERNAL); + + // Encrypt + result = mbedtls_ccm_encrypt_and_tag(&context, plaintext_length, Uint8::to_const_uchar(nonce), nonce_length, + Uint8::to_const_uchar(aad), aad_length, Uint8::to_const_uchar(plaintext), + Uint8::to_uchar(ciphertext), Uint8::to_uchar(tag), tag_length); + _log_mbedTLS_error(result); + VerifyOrExit(result == 0, error = CHIP_ERROR_INTERNAL); + +exit: + mbedtls_ccm_free(&context); + return error; +} + +CHIP_ERROR AES_CCM_decrypt(const uint8_t * ciphertext, size_t ciphertext_len, const uint8_t * aad, size_t aad_len, + const uint8_t * tag, size_t tag_length, const uint8_t * key, size_t key_length, const uint8_t * nonce, + size_t nonce_length, uint8_t * plaintext) +{ + CHIP_ERROR error = CHIP_NO_ERROR; + int result = 1; + + mbedtls_ccm_context context; + mbedtls_ccm_init(&context); + + VerifyOrExit(plaintext != nullptr || ciphertext_len == 0, error = CHIP_ERROR_INVALID_ARGUMENT); + VerifyOrExit(ciphertext != nullptr || ciphertext_len == 0, error = CHIP_ERROR_INVALID_ARGUMENT); + VerifyOrExit(tag != nullptr, error = CHIP_ERROR_INVALID_ARGUMENT); + VerifyOrExit(_isValidTagLength(tag_length), error = CHIP_ERROR_INVALID_ARGUMENT); + VerifyOrExit(key != nullptr, error = CHIP_ERROR_INVALID_ARGUMENT); + VerifyOrExit(_isValidKeyLength(key_length), error = CHIP_ERROR_UNSUPPORTED_ENCRYPTION_TYPE); + 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 = key_length * number of bits in a byte (8) + // Cast is safe because we called _isValidKeyLength above. + result = + mbedtls_ccm_setkey(&context, MBEDTLS_CIPHER_ID_AES, Uint8::to_const_uchar(key), static_cast(key_length * 8)); + VerifyOrExit(result == 0, error = CHIP_ERROR_INTERNAL); + + // Decrypt + result = mbedtls_ccm_auth_decrypt(&context, ciphertext_len, Uint8::to_const_uchar(nonce), nonce_length, + Uint8::to_const_uchar(aad), aad_len, Uint8::to_const_uchar(ciphertext), + Uint8::to_uchar(plaintext), Uint8::to_const_uchar(tag), tag_length); + _log_mbedTLS_error(result); + VerifyOrExit(result == 0, error = CHIP_ERROR_INTERNAL); + +exit: + mbedtls_ccm_free(&context); + return error; +} + +CHIP_ERROR Hash_SHA256(const uint8_t * data, const size_t data_length, uint8_t * out_buffer) +{ + // zero data length hash is supported. + VerifyOrReturnError(data != nullptr, CHIP_ERROR_INVALID_ARGUMENT); + VerifyOrReturnError(out_buffer != nullptr, CHIP_ERROR_INVALID_ARGUMENT); + +#if (MBEDTLS_VERSION_NUMBER >= 0x03000000) + const int result = mbedtls_sha256(Uint8::to_const_uchar(data), data_length, Uint8::to_uchar(out_buffer), 0); +#else + const int result = mbedtls_sha256_ret(Uint8::to_const_uchar(data), data_length, Uint8::to_uchar(out_buffer), 0); +#endif + + VerifyOrReturnError(result == 0, CHIP_ERROR_INTERNAL); + + return CHIP_NO_ERROR; +} + +CHIP_ERROR Hash_SHA1(const uint8_t * data, const size_t data_length, uint8_t * out_buffer) +{ + // zero data length hash is supported. + VerifyOrReturnError(out_buffer != nullptr, CHIP_ERROR_INVALID_ARGUMENT); + +#if (MBEDTLS_VERSION_NUMBER >= 0x03000000) + const int result = mbedtls_sha1(Uint8::to_const_uchar(data), data_length, Uint8::to_uchar(out_buffer)); +#else + const int result = mbedtls_sha1_ret(Uint8::to_const_uchar(data), data_length, Uint8::to_uchar(out_buffer)); +#endif + + VerifyOrReturnError(result == 0, CHIP_ERROR_INTERNAL); + + return CHIP_NO_ERROR; +} + +static_assert(kMAX_Hash_SHA256_Context_Size >= sizeof(mbedtls_sha256_context), + "kMAX_Hash_SHA256_Context_Size is too small for the size of underlying mbedtls_sha256_context"); + +static inline mbedtls_sha256_context * to_inner_hash_sha256_context(HashSHA256OpaqueContext * context) +{ + return SafePointerCast(context); +} + +Hash_SHA256_stream::Hash_SHA256_stream(void) +{ + mbedtls_sha256_context * context = to_inner_hash_sha256_context(&mContext); + mbedtls_sha256_init(context); +} + +Hash_SHA256_stream::~Hash_SHA256_stream(void) +{ + mbedtls_sha256_context * context = to_inner_hash_sha256_context(&mContext); + mbedtls_sha256_free(context); + Clear(); +} + +CHIP_ERROR Hash_SHA256_stream::Begin(void) +{ + mbedtls_sha256_context * const context = to_inner_hash_sha256_context(&mContext); + +#if (MBEDTLS_VERSION_NUMBER >= 0x03000000) + const int result = mbedtls_sha256_starts(context, 0); +#else + const int result = mbedtls_sha256_starts_ret(context, 0); +#endif + + VerifyOrReturnError(result == 0, CHIP_ERROR_INTERNAL); + + return CHIP_NO_ERROR; +} + +CHIP_ERROR Hash_SHA256_stream::AddData(const ByteSpan data) +{ + mbedtls_sha256_context * const context = to_inner_hash_sha256_context(&mContext); + +#if (MBEDTLS_VERSION_NUMBER >= 0x03000000) + const int result = mbedtls_sha256_update(context, Uint8::to_const_uchar(data.data()), data.size()); +#else + const int result = mbedtls_sha256_update_ret(context, Uint8::to_const_uchar(data.data()), data.size()); +#endif + + VerifyOrReturnError(result == 0, CHIP_ERROR_INTERNAL); + + return CHIP_NO_ERROR; +} + +CHIP_ERROR Hash_SHA256_stream::GetDigest(MutableByteSpan & out_buffer) +{ + mbedtls_sha256_context * context = to_inner_hash_sha256_context(&mContext); + + // Back-up context as we are about to finalize the hash to extract digest. + mbedtls_sha256_context previous_ctx; + mbedtls_sha256_init(&previous_ctx); + mbedtls_sha256_clone(&previous_ctx, context); + + // Pad + compute digest, then finalize context. It is restored next line to continue. + CHIP_ERROR result = Finish(out_buffer); + + // Restore context prior to finalization. + mbedtls_sha256_clone(context, &previous_ctx); + mbedtls_sha256_free(&previous_ctx); + + return result; +} + +CHIP_ERROR Hash_SHA256_stream::Finish(MutableByteSpan & out_buffer) +{ + VerifyOrReturnError(out_buffer.size() >= kSHA256_Hash_Length, CHIP_ERROR_BUFFER_TOO_SMALL); + mbedtls_sha256_context * const context = to_inner_hash_sha256_context(&mContext); + +#if (MBEDTLS_VERSION_NUMBER >= 0x03000000) + const int result = mbedtls_sha256_finish(context, Uint8::to_uchar(out_buffer.data())); +#else + const int result = mbedtls_sha256_finish_ret(context, Uint8::to_uchar(out_buffer.data())); +#endif + + VerifyOrReturnError(result == 0, CHIP_ERROR_INTERNAL); + out_buffer = out_buffer.SubSpan(0, kSHA256_Hash_Length); + + return CHIP_NO_ERROR; +} + +void Hash_SHA256_stream::Clear(void) +{ + mbedtls_platform_zeroize(this, sizeof(*this)); +} + +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) +{ + 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_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) +{ + 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; +} + +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; + 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; +} + +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_uecc_keypair * to_keypair(P256KeypairContext * context) +{ + return SafePointerCast(context); +} + +static inline const mbedtls_uecc_keypair * to_const_keypair(const P256KeypairContext * context) +{ + return SafePointerCast(context); +} + +CHIP_ERROR P256Keypair::ECDSA_sign_msg(const uint8_t * msg, const size_t msg_length, P256ECDSASignature & out_signature) const +{ + VerifyOrReturnError(mInitialized, CHIP_ERROR_INCORRECT_STATE); + 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])); + + CHIP_ERROR error = CHIP_NO_ERROR; + int result = UECC_FAILURE; + + const mbedtls_uecc_keypair * keypair = to_const_keypair(&mKeypair); + + result = uECC_sign(keypair->private_key, digest, sizeof(digest), out_signature.Bytes()); + + VerifyOrExit(result == UECC_SUCCESS, error = CHIP_ERROR_INTERNAL); + VerifyOrExit(out_signature.SetLength(kP256_ECDSA_Signature_Length_Raw) == CHIP_NO_ERROR, error = CHIP_ERROR_INTERNAL); + + keypair = nullptr; + +exit: + return error; +} + +CHIP_ERROR P256PublicKey::ECDSA_validate_msg_signature(const uint8_t * msg, const size_t msg_length, + const P256ECDSASignature & signature) const +{ +#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(&digest[0], sizeof(digest), signature); +#else + return CHIP_ERROR_NOT_IMPLEMENTED; +#endif +} + +CHIP_ERROR P256PublicKey::ECDSA_validate_hash_signature(const uint8_t * hash, const size_t hash_length, + const P256ECDSASignature & signature) const +{ + 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 = UECC_FAILURE; + + const uint8_t * public_key = *this; + + // Fully padded raw uncompressed points expected, first byte is always 0x04 i.e uncompressed + result = uECC_verify(public_key + 1, hash, hash_length, Uint8::to_const_uchar(signature.ConstBytes())); + VerifyOrExit(result == UECC_SUCCESS, error = CHIP_ERROR_INVALID_SIGNATURE); + +exit: + return error; +} + +CHIP_ERROR P256Keypair::ECDH_derive_secret(const P256PublicKey & remote_public_key, P256ECDHDerivedSecret & out_secret) const +{ +#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(); + + const mbedtls_uecc_keypair * keypair = to_const_keypair(&mKeypair); + + VerifyOrExit(mInitialized, error = CHIP_ERROR_INCORRECT_STATE); + + // Fully padded raw uncompressed points expected, first byte is always 0x04 i.e uncompressed + result = uECC_shared_secret(remote_public_key.ConstBytes() + 1, keypair->private_key, Uint8::to_uchar(out_secret)); + VerifyOrExit(result == UECC_SUCCESS, error = CHIP_ERROR_INTERNAL); + + SuccessOrExit(out_secret.SetLength(secret_length)); + +exit: + keypair = nullptr; + _log_mbedTLS_error(result); + return error; +#else + return CHIP_ERROR_NOT_IMPLEMENTED; +#endif +} + +void ClearSecretData(uint8_t * buf, size_t len) +{ + mbedtls_platform_zeroize(buf, len); +} + +// 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; +} + +CHIP_ERROR P256Keypair::Initialize() +{ + CHIP_ERROR error = CHIP_NO_ERROR; + int result = UECC_FAILURE; + + Clear(); + + mbedtls_uecc_keypair * keypair = to_keypair(&mKeypair); + + result = uECC_make_key(keypair->public_key, keypair->private_key); + VerifyOrExit(result == UECC_SUCCESS, error = CHIP_ERROR_INTERNAL); + + // Fully padded raw uncompressed points expected, first byte is always 0x04 i.e uncompressed + Uint8::to_uchar(mPublicKey)[0] = 0x04; + memcpy(Uint8::to_uchar(mPublicKey) + 1, keypair->public_key, 2 * NUM_ECC_BYTES); + + keypair = nullptr; + mInitialized = true; + +exit: + _log_mbedTLS_error(result); + return error; +} + +CHIP_ERROR P256Keypair::Serialize(P256SerializedKeypair & output) const +{ + const mbedtls_uecc_keypair * keypair = to_const_keypair(&mKeypair); + size_t len = output.Length() == 0 ? output.Capacity() : output.Length(); + Encoding::BufferWriter bbuf(output, 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(sizeof(keypair->private_key) <= bbuf.Available(), error = CHIP_ERROR_INTERNAL); + + memcpy(privkey, keypair->private_key, sizeof(privkey)); + + bbuf.Put(privkey, sizeof(privkey)); + VerifyOrExit(bbuf.Fit(), error = CHIP_ERROR_BUFFER_TOO_SMALL); + + output.SetLength(bbuf.Needed()); + +exit: + memset(privkey, 0, sizeof(privkey)); + _log_mbedTLS_error(result); + return error; +} + +CHIP_ERROR P256Keypair::Deserialize(P256SerializedKeypair & input) +{ + int result = 0; + CHIP_ERROR error = CHIP_NO_ERROR; + Encoding::BufferWriter bbuf(mPublicKey, mPublicKey.Length()); + + Clear(); + + mbedtls_uecc_keypair * keypair = to_keypair(&mKeypair); + + // Fully padded raw uncompressed points expected, first byte is always 0x04 i.e uncompressed + memcpy(keypair->public_key, Uint8::to_uchar(input) + 1, 2 * NUM_ECC_BYTES); + memcpy(keypair->private_key, Uint8::to_uchar(input) + mPublicKey.Length(), NUM_ECC_BYTES); + + keypair = nullptr; + + VerifyOrExit(input.Length() == mPublicKey.Length() + kP256_PrivateKey_Length, error = CHIP_ERROR_INVALID_ARGUMENT); + bbuf.Put((const uint8_t *) input, mPublicKey.Length()); + VerifyOrExit(bbuf.Fit(), error = CHIP_ERROR_NO_MEMORY); + + mInitialized = true; + + _log_mbedTLS_error(result); + +exit: + return error; +} + +void P256Keypair::Clear() +{ + if (mInitialized) + { + mbedtls_uecc_keypair * keypair = to_keypair(&mKeypair); + memset(keypair, 0, sizeof(mbedtls_uecc_keypair)); + mInitialized = false; + } +} + +P256Keypair::~P256Keypair() +{ + Clear(); +} + +CHIP_ERROR P256Keypair::NewCertificateSigningRequest(uint8_t * out_csr, size_t & csr_length) const +{ + 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); + + VerifyOrExit(mInitialized, error = CHIP_ERROR_INCORRECT_STATE); + + 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; +} + +CHIP_ERROR VerifyCertificateSigningRequest(const uint8_t * csr_buf, size_t csr_length, P256PublicKey & pubkey) +{ +#if defined(MBEDTLS_X509_CSR_PARSE_C) + // 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 +{ + const mbedtls_md_info_t * md_info; + uECC_word_t M[2 * NUM_ECC_WORDS]; + uECC_word_t N[2 * NUM_ECC_WORDS]; + uECC_word_t X[2 * NUM_ECC_WORDS]; + uECC_word_t Y[2 * NUM_ECC_WORDS]; + uECC_word_t L[2 * NUM_ECC_WORDS]; + uECC_word_t Z[2 * NUM_ECC_WORDS]; + uECC_word_t V[2 * NUM_ECC_WORDS]; + + uECC_word_t w0[NUM_ECC_WORDS]; + uECC_word_t w1[NUM_ECC_WORDS]; + uECC_word_t xy[NUM_ECC_WORDS]; + uECC_word_t tempbn[NUM_ECC_WORDS]; +} 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)); + + M = context->M; + N = context->N; + X = context->X; + Y = context->Y; + L = context->L; + V = context->V; + Z = context->Z; + + w0 = context->w0; + w1 = context->w1; + xy = context->xy; + tempbn = context->tempbn; + + G = curve_G; + + 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); + memset(&context->M, 0, 2 * NUM_ECC_WORDS * sizeof(uECC_word_t)); + memset(&context->N, 0, 2 * NUM_ECC_WORDS * sizeof(uECC_word_t)); + memset(&context->X, 0, 2 * NUM_ECC_WORDS * sizeof(uECC_word_t)); + memset(&context->Y, 0, 2 * NUM_ECC_WORDS * sizeof(uECC_word_t)); + memset(&context->L, 0, 2 * NUM_ECC_WORDS * sizeof(uECC_word_t)); + memset(&context->Z, 0, 2 * NUM_ECC_WORDS * sizeof(uECC_word_t)); + memset(&context->V, 0, 2 * NUM_ECC_WORDS * sizeof(uECC_word_t)); + + memset(&context->w0, 0, NUM_ECC_WORDS * sizeof(uECC_word_t)); + memset(&context->w1, 0, NUM_ECC_WORDS * sizeof(uECC_word_t)); + memset(&context->xy, 0, NUM_ECC_WORDS * sizeof(uECC_word_t)); + memset(&context->tempbn, 0, NUM_ECC_WORDS * sizeof(uECC_word_t)); + + G = NULL; + 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; + + uECC_word_t tmp[2 * NUM_ECC_WORDS] = { 0 }; + uECC_vli_bytesToNative(tmp, in, NUM_ECC_BYTES); + + uECC_vli_mmod((uECC_word_t *) fe, tmp, curve_n); + +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) +{ + uECC_vli_nativeToBytes(out, NUM_ECC_BYTES, (const unsigned int *) fe); + + return CHIP_NO_ERROR; +} + +CHIP_ERROR Spake2p_P256_SHA256_HKDF_HMAC::FEGenerate(void * fe) +{ + CHIP_ERROR error = CHIP_NO_ERROR; + int result = 0; + + mbedtls_uecc_keypair keypair; + + result = UECC_FAILURE; + + result = uECC_make_key(keypair.public_key, keypair.private_key); + VerifyOrExit(result == UECC_SUCCESS, error = CHIP_ERROR_INTERNAL); + + uECC_vli_bytesToNative((uECC_word_t *) fe, keypair.private_key, NUM_ECC_BYTES); + +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; + + uECC_vli_modMult((uECC_word_t *) fer, (const uECC_word_t *) fe1, (const uECC_word_t *) fe2, (const uECC_word_t *) curve_n); + +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) +{ + uint8_t tmp[2 * NUM_ECC_BYTES]; + + // Fully padded raw uncompressed points expected, first byte is always 0x04 i.e uncompressed + memcpy(tmp, in + 1, 2 * NUM_ECC_BYTES); + + uECC_vli_bytesToNative((uECC_word_t *) R, tmp, NUM_ECC_BYTES); + uECC_vli_bytesToNative((uECC_word_t *) R + NUM_ECC_WORDS, tmp + NUM_ECC_BYTES, NUM_ECC_BYTES); + + 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); + + // Fully padded raw uncompressed points expected, first byte is always 0x04 i.e uncompressed + out[0] = 0x04; + uECC_vli_nativeToBytes(out + 1, NUM_ECC_BYTES, (uECC_word_t *) R); + uECC_vli_nativeToBytes(out + NUM_ECC_BYTES + 1, NUM_ECC_BYTES, (uECC_word_t *) R + NUM_ECC_WORDS); + + return CHIP_NO_ERROR; +} + +CHIP_ERROR Spake2p_P256_SHA256_HKDF_HMAC::PointMul(void * R, const void * P1, const void * fe1) +{ + + if (EccPoint_mult_safer((uECC_word_t *) R, (const uECC_word_t *) P1, (const uECC_word_t *) fe1) != UECC_SUCCESS) + { + 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) +{ + uECC_word_t R1[2 * NUM_ECC_WORDS]; + uECC_word_t R2[2 * NUM_ECC_WORDS]; + uECC_word_t z[NUM_ECC_WORDS]; + uint8_t ret = UECC_SUCCESS; + + if (EccPoint_mult_safer(R1, (const uECC_word_t *) P1, (const uECC_word_t *) fe1) != UECC_SUCCESS) + { + return CHIP_ERROR_INTERNAL; + } + + if (EccPoint_mult_safer(R2, (const uECC_word_t *) P2, (const uECC_word_t *) fe2) != UECC_SUCCESS) + { + return CHIP_ERROR_INTERNAL; + } + + uECC_vli_modSub(z, R2, R1, curve_p); + XYcZ_add(R1, R1 + NUM_ECC_WORDS, R2, R2 + NUM_ECC_WORDS); + uECC_vli_modInv(z, z, curve_p); + apply_z(R2, R2 + NUM_ECC_WORDS, z); + + memcpy((uECC_word_t *) R, R2, 2 * NUM_ECC_BYTES); + + return CHIP_NO_ERROR; +} + +CHIP_ERROR Spake2p_P256_SHA256_HKDF_HMAC::PointInvert(void * R) +{ + uECC_word_t tmp[NUM_ECC_WORDS] = { 0 }; + + uECC_vli_sub(tmp, curve_p, (uECC_word_t *) R + NUM_ECC_WORDS); + memcpy((uECC_word_t *) R + NUM_ECC_WORDS, tmp, NUM_ECC_BYTES); + + 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; + + result = UECC_SUCCESS; + uECC_word_t tmp[2 * NUM_ECC_WORDS]; + uECC_word_t w1_bn[NUM_ECC_WORDS]; + uECC_word_t L_tmp[2 * NUM_ECC_WORDS]; + + uECC_vli_bytesToNative(tmp, w1in, NUM_ECC_BYTES); + + uECC_vli_mmod(w1_bn, tmp, curve_n); + + result = EccPoint_mult_safer(L_tmp, curve_G, w1_bn); + VerifyOrExit(result == UECC_SUCCESS, error = CHIP_ERROR_INTERNAL); + + // Fully padded raw uncompressed points expected, first byte is always 0x04 i.e uncompressed + Lout[0] = 0x04; + uECC_vli_nativeToBytes(Lout + 1, NUM_ECC_BYTES, L_tmp); + uECC_vli_nativeToBytes(Lout + NUM_ECC_BYTES + 1, NUM_ECC_BYTES, L_tmp + NUM_ECC_WORDS); + +exit: + _log_mbedTLS_error(result); + + return error; +} + +CHIP_ERROR Spake2p_P256_SHA256_HKDF_HMAC::PointIsValid(void * R) +{ + if (uECC_valid_point((const uECC_word_t *) R) != 0) + { + return CHIP_ERROR_INTERNAL; + } + + return CHIP_NO_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; + + result = CertificateChainValidationResult::kInternalFrameworkError; + + VerifyOrReturnError(rootCertificate != nullptr && rootCertificateLen != 0, + (result = CertificateChainValidationResult::kRootArgumentInvalid, CHIP_ERROR_INVALID_ARGUMENT)); + VerifyOrReturnError(caCertificate != nullptr && caCertificateLen != 0, + (result = CertificateChainValidationResult::kICAArgumentInvalid, 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 */ + 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, NULL, NULL, &flags, NULL, NULL); + + switch (mbedResult) + { + case 0: + VerifyOrExit(flags == 0, (result = CertificateChainValidationResult::kInternalFrameworkError, error = CHIP_ERROR_INTERNAL)); + result = CertificateChainValidationResult::kSuccess; + break; + case MBEDTLS_ERR_X509_CERT_VERIFY_FAILED: + result = CertificateChainValidationResult::kChainInvalid; + error = CHIP_ERROR_CERT_NOT_TRUSTED; + break; + default: + SuccessOrExit((result = CertificateChainValidationResult::kInternalFrameworkError, error = CHIP_ERROR_INTERNAL)); + } + +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; +} + +inline 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 ByteSpan & referenceCertificate, const ByteSpan & toBeEvaluatedCertificate) +{ +#if defined(MBEDTLS_X509_CRT_PARSE_C) + CHIP_ERROR error = CHIP_NO_ERROR; + mbedtls_x509_crt mbedReferenceCertificate; + mbedtls_x509_crt mbedToBeEvaluatedCertificate; + mbedtls_x509_time refNotBeforeTime; + mbedtls_x509_time tbeNotBeforeTime; + mbedtls_x509_time tbeNotAfterTime; + int result; + + VerifyOrReturnError(!referenceCertificate.empty() && !toBeEvaluatedCertificate.empty(), CHIP_ERROR_INVALID_ARGUMENT); + + mbedtls_x509_crt_init(&mbedReferenceCertificate); + mbedtls_x509_crt_init(&mbedToBeEvaluatedCertificate); + + result = mbedtls_x509_crt_parse(&mbedReferenceCertificate, Uint8::to_const_uchar(referenceCertificate.data()), + referenceCertificate.size()); + VerifyOrExit(result == 0, error = CHIP_ERROR_INTERNAL); + + result = mbedtls_x509_crt_parse(&mbedToBeEvaluatedCertificate, Uint8::to_const_uchar(toBeEvaluatedCertificate.data()), + toBeEvaluatedCertificate.size()); + VerifyOrExit(result == 0, error = CHIP_ERROR_INTERNAL); + + refNotBeforeTime = mbedReferenceCertificate.CHIP_CRYPTO_PAL_PRIVATE_X509(valid_from); + tbeNotBeforeTime = mbedToBeEvaluatedCertificate.CHIP_CRYPTO_PAL_PRIVATE_X509(valid_from); + tbeNotAfterTime = mbedToBeEvaluatedCertificate.CHIP_CRYPTO_PAL_PRIVATE_X509(valid_to); + + // check if referenceCertificate is issued at or after tbeCertificate's notBefore timestamp + VerifyOrExit(IsTimeGreaterThanEqual(&refNotBeforeTime, &tbeNotBeforeTime), error = CHIP_ERROR_CERT_EXPIRED); + + // check if referenceCertificate is issued at or before tbeCertificate's notAfter timestamp + VerifyOrExit(IsTimeGreaterThanEqual(&tbeNotAfterTime, &refNotBeforeTime), error = CHIP_ERROR_CERT_EXPIRED); + +exit: + _log_mbedTLS_error(result); + mbedtls_x509_crt_free(&mbedReferenceCertificate); + mbedtls_x509_crt_free(&mbedToBeEvaluatedCertificate); + +#else + (void) referenceCertificate; + (void) toBeEvaluatedCertificate; + 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_NO_ERROR; + mbedtls_x509_crt mbed_cert; + unsigned char * p; + const unsigned char * end; + size_t len; + + constexpr uint8_t sOID_Extension_SubjectKeyIdentifier[] = { 0x55, 0x1D, 0x0E }; + constexpr uint8_t sOID_Extension_AuthorityKeyIdentifier[] = { 0x55, 0x1D, 0x23 }; + + 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); + + bool extractCurrentExtSKID = extractSKID && (sizeof(sOID_Extension_SubjectKeyIdentifier) == len) && + (memcmp(p, sOID_Extension_SubjectKeyIdentifier, len) == 0); + bool extractCurrentExtAKID = !extractSKID && (sizeof(sOID_Extension_AuthorityKeyIdentifier) == len) && + (memcmp(p, sOID_Extension_AuthorityKeyIdentifier, len) == 0); + 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); + } + 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) + 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 }; + + 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)) + { + size_t oid_len = dnIterator->CHIP_CRYPTO_PAL_PRIVATE_X509(oid).CHIP_CRYPTO_PAL_PRIVATE_X509(len); + uint8_t * oid_p = dnIterator->CHIP_CRYPTO_PAL_PRIVATE_X509(oid).CHIP_CRYPTO_PAL_PRIVATE_X509(p); + 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); + + if (oid_p != nullptr && val_p != nullptr) + { + DNAttrType attrType = DNAttrType::kUnspecified; + if ((oid_len == sizeof(sOID_AttributeType_CommonName)) && (memcmp(sOID_AttributeType_CommonName, oid_p, oid_len) == 0)) + { + attrType = DNAttrType::kCommonName; + } + else if ((oid_len == sizeof(sOID_AttributeType_MatterVendorId)) && + (memcmp(sOID_AttributeType_MatterVendorId, oid_p, oid_len) == 0)) + { + attrType = DNAttrType::kMatterVID; + } + else if ((oid_len == sizeof(sOID_AttributeType_MatterProductId)) && + (memcmp(sOID_AttributeType_MatterProductId, oid_p, oid_len) == 0)) + { + attrType = DNAttrType::kMatterPID; + } + + 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/crypto/CHIPCryptoPALmbedTLS.cpp b/src/crypto/CHIPCryptoPALmbedTLS.cpp index 5dbce1d3d62f8f..59b11d1e34a681 100644 --- a/src/crypto/CHIPCryptoPALmbedTLS.cpp +++ b/src/crypto/CHIPCryptoPALmbedTLS.cpp @@ -44,13 +44,6 @@ #include #include -#if defined(MBEDTLS_USE_TINYCRYPT) -#include -#include -#include -#include -#endif // defined(MBEDTLS_USE_TINYCRYPT) - #include #include #include @@ -93,11 +86,7 @@ static EntropyContext gsEntropyContext; static void _log_mbedTLS_error(int error_code) { -#if defined(MBEDTLS_USE_TINYCRYPT) - if (error_code != 0 && error_code != UECC_SUCCESS) -#else if (error_code != 0) -#endif { #if defined(MBEDTLS_ERROR_C) char error_str[MAX_ERROR_STR_LEN]; @@ -496,24 +485,6 @@ 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; } -#if defined(MBEDTLS_USE_TINYCRYPT) - -static int uecc_rng_wrapper(uint8_t * dest, unsigned int size) -{ - int ret; - - ret = CryptoRNG(NULL, dest, size); - - return (ret == 0) ? size : 0; -} - -static int uECC_is_rng_set(void) -{ - return (uecc_rng_wrapper == uECC_get_rng()) ? 1 : 0; -} - -#endif - mbedtls_ecp_group_id MapECPGroupId(SupportedECPKeyTypes keyType) { switch (keyType) @@ -525,20 +496,6 @@ mbedtls_ecp_group_id MapECPGroupId(SupportedECPKeyTypes keyType) } } -#if defined(MBEDTLS_USE_TINYCRYPT) - -static inline mbedtls_uecc_keypair * to_keypair(P256KeypairContext * context) -{ - return SafePointerCast(context); -} - -static inline const mbedtls_uecc_keypair * to_const_keypair(const P256KeypairContext * context) -{ - return SafePointerCast(context); -} - -#else - static inline mbedtls_ecp_keypair * to_keypair(P256KeypairContext * context) { return SafePointerCast(context); @@ -549,8 +506,6 @@ static inline const mbedtls_ecp_keypair * to_const_keypair(const P256KeypairCont return SafePointerCast(context); } -#endif - CHIP_ERROR P256Keypair::ECDSA_sign_msg(const uint8_t * msg, const size_t msg_length, P256ECDSASignature & out_signature) const { VerifyOrReturnError(mInitialized, CHIP_ERROR_INCORRECT_STATE); @@ -560,24 +515,9 @@ CHIP_ERROR P256Keypair::ECDSA_sign_msg(const uint8_t * msg, const size_t msg_len memset(&digest[0], 0, sizeof(digest)); ReturnErrorOnFailure(Hash_SHA256(msg, msg_length, &digest[0])); -#if defined(MBEDTLS_USE_TINYCRYPT) - CHIP_ERROR error = CHIP_NO_ERROR; - int result = UECC_FAILURE; - - const mbedtls_uecc_keypair * keypair = to_const_keypair(&mKeypair); - - result = uECC_sign(keypair->private_key, digest, sizeof(digest), out_signature.Bytes()); - - VerifyOrExit(result == UECC_SUCCESS, error = CHIP_ERROR_INTERNAL); - VerifyOrExit(out_signature.SetLength(kP256_ECDSA_Signature_Length_Raw) == CHIP_NO_ERROR, error = CHIP_ERROR_INTERNAL); - - keypair = nullptr; - -exit: - return error; -#elif defined(MBEDTLS_ECDSA_C) +#if defined(MBEDTLS_ECDSA_C) CHIP_ERROR error = CHIP_NO_ERROR; - int result = 0; + int result = 0; mbedtls_mpi r, s; mbedtls_mpi_init(&r); mbedtls_mpi_init(&s); @@ -638,29 +578,13 @@ CHIP_ERROR P256PublicKey::ECDSA_validate_msg_signature(const uint8_t * msg, cons CHIP_ERROR P256PublicKey::ECDSA_validate_hash_signature(const uint8_t * hash, const size_t hash_length, const P256ECDSASignature & signature) const { -#if defined(MBEDTLS_USE_TINYCRYPT) - 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 = UECC_FAILURE; - - const uint8_t * public_key = *this; - - // Fully padded raw uncompressed points expected, first byte is always 0x04 i.e uncompressed - result = uECC_verify(public_key + 1, hash, hash_length, Uint8::to_const_uchar(signature.ConstBytes())); - VerifyOrExit(result == UECC_SUCCESS, error = CHIP_ERROR_INVALID_SIGNATURE); - -exit: - return error; -#elif defined(MBEDTLS_ECDSA_C) +#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; + int result = 0; mbedtls_mpi r, s; mbedtls_mpi_init(&r); @@ -712,26 +636,6 @@ CHIP_ERROR P256Keypair::ECDH_derive_secret(const P256PublicKey & remote_public_k { #if defined(MBEDTLS_ECDH_C) -#if defined(MBEDTLS_USE_TINYCRYPT) - CHIP_ERROR error = CHIP_NO_ERROR; - int result = 0; - size_t secret_length = (out_secret.Length() == 0) ? out_secret.Capacity() : out_secret.Length(); - - const mbedtls_uecc_keypair * keypair = to_const_keypair(&mKeypair); - - VerifyOrExit(mInitialized, error = CHIP_ERROR_INCORRECT_STATE); - - // Fully padded raw uncompressed points expected, first byte is always 0x04 i.e uncompressed - result = uECC_shared_secret(remote_public_key.ConstBytes() + 1, keypair->private_key, Uint8::to_uchar(out_secret)); - VerifyOrExit(result == UECC_SUCCESS, error = CHIP_ERROR_INTERNAL); - - SuccessOrExit(out_secret.SetLength(secret_length)); - -exit: - keypair = nullptr; - _log_mbedTLS_error(result); - return error; -#else CHIP_ERROR error = CHIP_NO_ERROR; int result = 0; size_t secret_length = (out_secret.Length() == 0) ? out_secret.Capacity() : out_secret.Length(); @@ -771,7 +675,6 @@ CHIP_ERROR P256Keypair::ECDH_derive_secret(const P256PublicKey & remote_public_k mbedtls_ecp_point_free(&ecp_pubkey); _log_mbedTLS_error(result); return error; -#endif #else return CHIP_ERROR_NOT_IMPLEMENTED; @@ -811,34 +714,8 @@ bool IsBufferContentEqualConstantTime(const void * a, const void * b, size_t n) CHIP_ERROR P256Keypair::Initialize() { -#if defined(MBEDTLS_USE_TINYCRYPT) - CHIP_ERROR error = CHIP_NO_ERROR; - int result = UECC_FAILURE; - - Clear(); - - mbedtls_uecc_keypair * keypair = to_keypair(&mKeypair); - if (!uECC_is_rng_set()) - { - uECC_set_rng(&uecc_rng_wrapper); - } - - result = uECC_make_key(keypair->public_key, keypair->private_key); - VerifyOrExit(result == UECC_SUCCESS, error = CHIP_ERROR_INTERNAL); - - // Fully padded raw uncompressed points expected, first byte is always 0x04 i.e uncompressed - Uint8::to_uchar(mPublicKey)[0] = 0x04; - memcpy(Uint8::to_uchar(mPublicKey) + 1, keypair->public_key, 2 * NUM_ECC_BYTES); - - keypair = nullptr; - mInitialized = true; - -exit: - _log_mbedTLS_error(result); - return error; -#else CHIP_ERROR error = CHIP_NO_ERROR; - int result = 0; + int result = 0; size_t pubkey_size = 0; @@ -858,7 +735,7 @@ CHIP_ERROR P256Keypair::Initialize() VerifyOrExit(result == 0, error = CHIP_ERROR_INVALID_ARGUMENT); VerifyOrExit(pubkey_size == mPublicKey.Length(), error = CHIP_ERROR_INVALID_ARGUMENT); - keypair = nullptr; + keypair = nullptr; mInitialized = true; exit: @@ -870,42 +747,16 @@ CHIP_ERROR P256Keypair::Initialize() _log_mbedTLS_error(result); return error; -#endif } CHIP_ERROR P256Keypair::Serialize(P256SerializedKeypair & output) const { -#if defined(MBEDTLS_USE_TINYCRYPT) - const mbedtls_uecc_keypair * keypair = to_const_keypair(&mKeypair); - size_t len = output.Length() == 0 ? output.Capacity() : output.Length(); - Encoding::BufferWriter bbuf(output, 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(sizeof(keypair->private_key) <= bbuf.Available(), error = CHIP_ERROR_INTERNAL); - - memcpy(privkey, keypair->private_key, sizeof(privkey)); - - bbuf.Put(privkey, sizeof(privkey)); - VerifyOrExit(bbuf.Fit(), error = CHIP_ERROR_BUFFER_TOO_SMALL); - - output.SetLength(bbuf.Needed()); - -exit: - memset(privkey, 0, sizeof(privkey)); - _log_mbedTLS_error(result); - return error; -#else const mbedtls_ecp_keypair * keypair = to_const_keypair(&mKeypair); - size_t len = output.Length() == 0 ? output.Capacity() : output.Length(); + size_t len = output.Length() == 0 ? output.Capacity() : output.Length(); Encoding::BufferWriter bbuf(output, len); uint8_t privkey[kP256_PrivateKey_Length]; CHIP_ERROR error = CHIP_NO_ERROR; - int result = 0; + int result = 0; bbuf.Put(mPublicKey, mPublicKey.Length()); @@ -925,44 +776,13 @@ CHIP_ERROR P256Keypair::Serialize(P256SerializedKeypair & output) const ClearSecretData(privkey, sizeof(privkey)); _log_mbedTLS_error(result); return error; -#endif } CHIP_ERROR P256Keypair::Deserialize(P256SerializedKeypair & input) { -#if defined(MBEDTLS_USE_TINYCRYPT) - int result = 0; - CHIP_ERROR error = CHIP_NO_ERROR; - Encoding::BufferWriter bbuf(mPublicKey, mPublicKey.Length()); - - Clear(); - - mbedtls_uecc_keypair * keypair = to_keypair(&mKeypair); - if (!uECC_is_rng_set()) - { - uECC_set_rng(&uecc_rng_wrapper); - } - - // Fully padded raw uncompressed points expected, first byte is always 0x04 i.e uncompressed - memcpy(keypair->public_key, Uint8::to_uchar(input) + 1, 2 * NUM_ECC_BYTES); - memcpy(keypair->private_key, Uint8::to_uchar(input) + mPublicKey.Length(), NUM_ECC_BYTES); - - keypair = nullptr; - - VerifyOrExit(input.Length() == mPublicKey.Length() + kP256_PrivateKey_Length, error = CHIP_ERROR_INVALID_ARGUMENT); - bbuf.Put((const uint8_t *) input, mPublicKey.Length()); - VerifyOrExit(bbuf.Fit(), error = CHIP_ERROR_NO_MEMORY); - - mInitialized = true; - - _log_mbedTLS_error(result); - -exit: - return error; -#else Encoding::BufferWriter bbuf(mPublicKey, mPublicKey.Length()); - int result = 0; + int result = 0; CHIP_ERROR error = CHIP_NO_ERROR; Clear(); @@ -993,22 +813,15 @@ CHIP_ERROR P256Keypair::Deserialize(P256SerializedKeypair & input) exit: _log_mbedTLS_error(result); return error; -#endif } void P256Keypair::Clear() { if (mInitialized) { -#if defined(MBEDTLS_USE_TINYCRYPT) - mbedtls_uecc_keypair * keypair = to_keypair(&mKeypair); - memset(keypair, 0, sizeof(mbedtls_uecc_keypair)); - mInitialized = false; -#else mbedtls_ecp_keypair * keypair = to_keypair(&mKeypair); mbedtls_ecp_keypair_free(keypair); mInitialized = false; -#endif } } @@ -1134,21 +947,6 @@ CHIP_ERROR VerifyCertificateSigningRequest(const uint8_t * csr_buf, size_t csr_l typedef struct Spake2p_Context { -#if defined(MBEDTLS_USE_TINYCRYPT) - const mbedtls_md_info_t * md_info; - uECC_word_t M[2 * NUM_ECC_WORDS]; - uECC_word_t N[2 * NUM_ECC_WORDS]; - uECC_word_t X[2 * NUM_ECC_WORDS]; - uECC_word_t Y[2 * NUM_ECC_WORDS]; - uECC_word_t L[2 * NUM_ECC_WORDS]; - uECC_word_t Z[2 * NUM_ECC_WORDS]; - uECC_word_t V[2 * NUM_ECC_WORDS]; - - uECC_word_t w0[NUM_ECC_WORDS]; - uECC_word_t w1[NUM_ECC_WORDS]; - uECC_word_t xy[NUM_ECC_WORDS]; - uECC_word_t tempbn[NUM_ECC_WORDS]; -#else mbedtls_ecp_group curve; const mbedtls_md_info_t * md_info; mbedtls_ecp_point M; @@ -1163,7 +961,6 @@ typedef struct Spake2p_Context mbedtls_mpi w1; mbedtls_mpi xy; mbedtls_mpi tempbn; -#endif } Spake2p_Context; static inline Spake2p_Context * to_inner_spake2p_context(Spake2pOpaqueContext * context) @@ -1180,27 +977,6 @@ CHIP_ERROR Spake2p_P256_SHA256_HKDF_HMAC::InitInternal(void) memset(context, 0, sizeof(Spake2p_Context)); -#if defined(MBEDTLS_USE_TINYCRYPT) - M = context->M; - N = context->N; - X = context->X; - Y = context->Y; - L = context->L; - V = context->V; - Z = context->Z; - - w0 = context->w0; - w1 = context->w1; - xy = context->xy; - tempbn = context->tempbn; - - G = curve_G; - - if (!uECC_is_rng_set()) - { - uECC_set_rng(&uecc_rng_wrapper); - } -#else mbedtls_ecp_group_init(&context->curve); result = mbedtls_ecp_group_load(&context->curve, MBEDTLS_ECP_DP_SECP256R1); VerifyOrExit(result == 0, error = CHIP_ERROR_INTERNAL); @@ -1227,14 +1003,13 @@ CHIP_ERROR Spake2p_P256_SHA256_HKDF_HMAC::InitInternal(void) mbedtls_mpi_init(&context->w1); mbedtls_mpi_init(&context->xy); mbedtls_mpi_init(&context->tempbn); - w0 = &context->w0; - w1 = &context->w1; - xy = &context->xy; + w0 = &context->w0; + w1 = &context->w1; + xy = &context->xy; tempbn = &context->tempbn; - G = &context->curve.G; + G = &context->curve.G; order = &context->curve.N; -#endif return error; @@ -1249,22 +1024,6 @@ void Spake2p_P256_SHA256_HKDF_HMAC::Clear() VerifyOrReturn(state != CHIP_SPAKE2P_STATE::PREINIT); Spake2p_Context * context = to_inner_spake2p_context(&mSpake2pContext); -#if defined(MBEDTLS_USE_TINYCRYPT) - memset(&context->M, 0, 2 * NUM_ECC_WORDS * sizeof(uECC_word_t)); - memset(&context->N, 0, 2 * NUM_ECC_WORDS * sizeof(uECC_word_t)); - memset(&context->X, 0, 2 * NUM_ECC_WORDS * sizeof(uECC_word_t)); - memset(&context->Y, 0, 2 * NUM_ECC_WORDS * sizeof(uECC_word_t)); - memset(&context->L, 0, 2 * NUM_ECC_WORDS * sizeof(uECC_word_t)); - memset(&context->Z, 0, 2 * NUM_ECC_WORDS * sizeof(uECC_word_t)); - memset(&context->V, 0, 2 * NUM_ECC_WORDS * sizeof(uECC_word_t)); - - memset(&context->w0, 0, NUM_ECC_WORDS * sizeof(uECC_word_t)); - memset(&context->w1, 0, NUM_ECC_WORDS * sizeof(uECC_word_t)); - memset(&context->xy, 0, NUM_ECC_WORDS * sizeof(uECC_word_t)); - memset(&context->tempbn, 0, NUM_ECC_WORDS * sizeof(uECC_word_t)); - - G = NULL; -#else mbedtls_ecp_point_free(&context->M); mbedtls_ecp_point_free(&context->N); mbedtls_ecp_point_free(&context->X); @@ -1279,7 +1038,6 @@ void Spake2p_P256_SHA256_HKDF_HMAC::Clear() mbedtls_mpi_free(&context->tempbn); mbedtls_ecp_group_free(&context->curve); -#endif state = CHIP_SPAKE2P_STATE::PREINIT; } @@ -1318,18 +1076,11 @@ CHIP_ERROR Spake2p_P256_SHA256_HKDF_HMAC::FELoad(const uint8_t * in, size_t in_l CHIP_ERROR error = CHIP_NO_ERROR; int result = 0; -#if defined(MBEDTLS_USE_TINYCRYPT) - uECC_word_t tmp[2 * NUM_ECC_WORDS] = { 0 }; - uECC_vli_bytesToNative(tmp, in, NUM_ECC_BYTES); - - uECC_vli_mmod((uECC_word_t *) fe, tmp, curve_n); -#else 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); -#endif exit: _log_mbedTLS_error(result); @@ -1338,14 +1089,10 @@ CHIP_ERROR Spake2p_P256_SHA256_HKDF_HMAC::FELoad(const uint8_t * in, size_t in_l CHIP_ERROR Spake2p_P256_SHA256_HKDF_HMAC::FEWrite(const void * fe, uint8_t * out, size_t out_len) { -#if defined(MBEDTLS_USE_TINYCRYPT) - uECC_vli_nativeToBytes(out, NUM_ECC_BYTES, (const unsigned int *) fe); -#else if (mbedtls_mpi_write_binary((const mbedtls_mpi *) fe, Uint8::to_uchar(out), out_len) != 0) { return CHIP_ERROR_INTERNAL; } -#endif return CHIP_NO_ERROR; } @@ -1354,21 +1101,10 @@ CHIP_ERROR Spake2p_P256_SHA256_HKDF_HMAC::FEGenerate(void * fe) CHIP_ERROR error = CHIP_NO_ERROR; int result = 0; -#if defined(MBEDTLS_USE_TINYCRYPT) - mbedtls_uecc_keypair keypair; - - result = UECC_FAILURE; - - result = uECC_make_key(keypair.public_key, keypair.private_key); - VerifyOrExit(result == UECC_SUCCESS, error = CHIP_ERROR_INTERNAL); - - uECC_vli_bytesToNative((uECC_word_t *) fe, keypair.private_key, NUM_ECC_BYTES); -#else 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); -#endif exit: _log_mbedTLS_error(result); @@ -1380,15 +1116,11 @@ CHIP_ERROR Spake2p_P256_SHA256_HKDF_HMAC::FEMul(void * fer, const void * fe1, co CHIP_ERROR error = CHIP_NO_ERROR; int result = 0; -#if defined(MBEDTLS_USE_TINYCRYPT) - uECC_vli_modMult((uECC_word_t *) fer, (const uECC_word_t *) fe1, (const uECC_word_t *) fe2, (const uECC_word_t *) curve_n); -#else 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); -#endif exit: _log_mbedTLS_error(result); @@ -1397,22 +1129,12 @@ CHIP_ERROR Spake2p_P256_SHA256_HKDF_HMAC::FEMul(void * fer, const void * fe1, co CHIP_ERROR Spake2p_P256_SHA256_HKDF_HMAC::PointLoad(const uint8_t * in, size_t in_len, void * R) { -#if defined(MBEDTLS_USE_TINYCRYPT) - uint8_t tmp[2 * NUM_ECC_BYTES]; - - // Fully padded raw uncompressed points expected, first byte is always 0x04 i.e uncompressed - memcpy(tmp, in + 1, 2 * NUM_ECC_BYTES); - - uECC_vli_bytesToNative((uECC_word_t *) R, tmp, NUM_ECC_BYTES); - uECC_vli_bytesToNative((uECC_word_t *) R + NUM_ECC_WORDS, tmp + NUM_ECC_BYTES, NUM_ECC_BYTES); -#else 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; } -#endif return CHIP_NO_ERROR; } @@ -1421,12 +1143,6 @@ CHIP_ERROR Spake2p_P256_SHA256_HKDF_HMAC::PointWrite(const void * R, uint8_t * o { memset(out, 0, out_len); -#if defined(MBEDTLS_USE_TINYCRYPT) - // Fully padded raw uncompressed points expected, first byte is always 0x04 i.e uncompressed - out[0] = 0x04; - uECC_vli_nativeToBytes(out + 1, NUM_ECC_BYTES, (uECC_word_t *) R); - uECC_vli_nativeToBytes(out + NUM_ECC_BYTES + 1, NUM_ECC_BYTES, (uECC_word_t *) R + NUM_ECC_WORDS); -#else size_t mbedtls_out_len = out_len; Spake2p_Context * context = to_inner_spake2p_context(&mSpake2pContext); @@ -1436,22 +1152,16 @@ CHIP_ERROR Spake2p_P256_SHA256_HKDF_HMAC::PointWrite(const void * R, uint8_t * o { return CHIP_ERROR_INTERNAL; } -#endif return CHIP_NO_ERROR; } CHIP_ERROR Spake2p_P256_SHA256_HKDF_HMAC::PointMul(void * R, const void * P1, const void * fe1) { - -#if defined(MBEDTLS_USE_TINYCRYPT) - if (EccPoint_mult_safer((uECC_word_t *) R, (const uECC_word_t *) P1, (const uECC_word_t *) fe1) != UECC_SUCCESS) -#else 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) -#endif { return CHIP_ERROR_INTERNAL; } @@ -1462,29 +1172,6 @@ CHIP_ERROR Spake2p_P256_SHA256_HKDF_HMAC::PointMul(void * R, const void * P1, co CHIP_ERROR Spake2p_P256_SHA256_HKDF_HMAC::PointAddMul(void * R, const void * P1, const void * fe1, const void * P2, const void * fe2) { -#if defined(MBEDTLS_USE_TINYCRYPT) - uECC_word_t R1[2 * NUM_ECC_WORDS]; - uECC_word_t R2[2 * NUM_ECC_WORDS]; - uECC_word_t z[NUM_ECC_WORDS]; - uint8_t ret = UECC_SUCCESS; - - if (EccPoint_mult_safer(R1, (const uECC_word_t *) P1, (const uECC_word_t *) fe1) != UECC_SUCCESS) - { - return CHIP_ERROR_INTERNAL; - } - - if (EccPoint_mult_safer(R2, (const uECC_word_t *) P2, (const uECC_word_t *) fe2) != UECC_SUCCESS) - { - return CHIP_ERROR_INTERNAL; - } - - uECC_vli_modSub(z, R2, R1, curve_p); - XYcZ_add(R1, R1 + NUM_ECC_WORDS, R2, R2 + NUM_ECC_WORDS); - uECC_vli_modInv(z, z, curve_p); - apply_z(R2, R2 + NUM_ECC_WORDS, z); - - memcpy((uECC_word_t *) R, R2, 2 * NUM_ECC_BYTES); -#else 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, @@ -1492,27 +1179,19 @@ CHIP_ERROR Spake2p_P256_SHA256_HKDF_HMAC::PointAddMul(void * R, const void * P1, { return CHIP_ERROR_INTERNAL; } -#endif return CHIP_NO_ERROR; } CHIP_ERROR Spake2p_P256_SHA256_HKDF_HMAC::PointInvert(void * R) { -#if defined(MBEDTLS_USE_TINYCRYPT) - uECC_word_t tmp[NUM_ECC_WORDS] = { 0 }; - - uECC_vli_sub(tmp, curve_p, (uECC_word_t *) R + NUM_ECC_WORDS); - memcpy((uECC_word_t *) R + NUM_ECC_WORDS, tmp, NUM_ECC_BYTES); -#else - mbedtls_ecp_point * Rp = (mbedtls_ecp_point *) 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; } -#endif return CHIP_NO_ERROR; } @@ -1527,24 +1206,6 @@ CHIP_ERROR Spake2p_P256_SHA256_HKDF_HMAC::ComputeL(uint8_t * Lout, size_t * L_le CHIP_ERROR error = CHIP_NO_ERROR; int result = 0; -#if defined(MBEDTLS_USE_TINYCRYPT) - result = UECC_SUCCESS; - uECC_word_t tmp[2 * NUM_ECC_WORDS]; - uECC_word_t w1_bn[NUM_ECC_WORDS]; - uECC_word_t L_tmp[2 * NUM_ECC_WORDS]; - - uECC_vli_bytesToNative(tmp, w1in, NUM_ECC_BYTES); - - uECC_vli_mmod(w1_bn, tmp, curve_n); - - result = EccPoint_mult_safer(L_tmp, curve_G, w1_bn); - VerifyOrExit(result == UECC_SUCCESS, error = CHIP_ERROR_INTERNAL); - - // Fully padded raw uncompressed points expected, first byte is always 0x04 i.e uncompressed - Lout[0] = 0x04; - uECC_vli_nativeToBytes(Lout + 1, NUM_ECC_BYTES, L_tmp); - uECC_vli_nativeToBytes(Lout + NUM_ECC_BYTES + 1, NUM_ECC_BYTES, L_tmp + NUM_ECC_WORDS); -#else mbedtls_ecp_group curve; mbedtls_mpi w1_bn; mbedtls_ecp_point Ltemp; @@ -1569,28 +1230,21 @@ CHIP_ERROR Spake2p_P256_SHA256_HKDF_HMAC::ComputeL(uint8_t * Lout, size_t * L_le 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); -#endif exit: _log_mbedTLS_error(result); -#if !defined(MBEDTLS_USE_TINYCRYPT) mbedtls_ecp_point_free(&Ltemp); mbedtls_mpi_free(&w1_bn); mbedtls_ecp_group_free(&curve); -#endif return error; } CHIP_ERROR Spake2p_P256_SHA256_HKDF_HMAC::PointIsValid(void * R) { -#if defined(MBEDTLS_USE_TINYCRYPT) - if (uECC_valid_point((const uECC_word_t *) R) != 0) -#else Spake2p_Context * context = to_inner_spake2p_context(&mSpake2pContext); if (mbedtls_ecp_check_pubkey(&context->curve, (mbedtls_ecp_point *) R) != 0) -#endif { return CHIP_ERROR_INTERNAL; } diff --git a/src/crypto/crypto.gni b/src/crypto/crypto.gni index 80d94e042224c7..c77f91a4823083 100644 --- a/src/crypto/crypto.gni +++ b/src/crypto/crypto.gni @@ -30,5 +30,5 @@ if (chip_crypto == "") { assert( chip_crypto == "mbedtls" || chip_crypto == "openssl" || - chip_crypto == "boringssl", - "Please select a valid crypto implementation: mbedtls, openssl, boringssl") + chip_crypto == "tinycrypt" || chip_crypto == "boringssl", + "Please select a valid crypto implementation: mbedtls, openssl, tinycrypt, boringssl") diff --git a/src/lib/shell/streamer_k32w.cpp b/src/lib/shell/streamer_k32w.cpp index ee0887766a8fb2..68523e7a2c44ff 100644 --- a/src/lib/shell/streamer_k32w.cpp +++ b/src/lib/shell/streamer_k32w.cpp @@ -28,7 +28,7 @@ #include #include "SerialManager.h" -extern uint8_t mOtSerMgrIfLog; +extern uint8_t gShellSerMgrIf; namespace chip { namespace Shell { @@ -48,7 +48,7 @@ ssize_t streamer_k32w_read(streamer_t * streamer, char * buffer, size_t length) uint16_t bytesRead = 0; (void) streamer; - Serial_Read(mOtSerMgrIfLog, (uint8_t *) buffer, length, &bytesRead); + Serial_Read(gShellSerMgrIf, (uint8_t *) buffer, length, &bytesRead); return bytesRead; } diff --git a/src/platform/nxp/k32w/k32w0/BLEManagerImpl.cpp b/src/platform/nxp/k32w/k32w0/BLEManagerImpl.cpp index ce2c4a235cdaa8..f8e6518b2d466a 100644 --- a/src/platform/nxp/k32w/k32w0/BLEManagerImpl.cpp +++ b/src/platform/nxp/k32w/k32w0/BLEManagerImpl.cpp @@ -184,6 +184,7 @@ CHIP_ERROR BLEManagerImpl::_Init() VerifyOrExit(bleAppCreated == pdPASS, err = CHIP_ERROR_INCORRECT_STATE); /* BLE Radio Init */ + XCVR_TemperatureUpdate(BOARD_GetTemperature()); VerifyOrExit(XCVR_Init(BLE_MODE, DR_2MBPS) == gXcvrSuccess_c, err = CHIP_ERROR_INCORRECT_STATE); /* Create BLE Controller Task */ diff --git a/src/platform/nxp/k32w/k32w0/BUILD.gn b/src/platform/nxp/k32w/k32w0/BUILD.gn index dddeef7374b20a..e813d8253c48bd 100644 --- a/src/platform/nxp/k32w/k32w0/BUILD.gn +++ b/src/platform/nxp/k32w/k32w0/BUILD.gn @@ -47,8 +47,6 @@ static_library("k32w0") { "NFCManagerImpl.h", "PlatformManagerImpl.cpp", "PlatformManagerImpl.h", - "RamStorage.cpp", - "RamStorage.h", "ble_function_mux.c", ] diff --git a/src/platform/nxp/k32w/k32w0/K32W0Config.cpp b/src/platform/nxp/k32w/k32w0/K32W0Config.cpp index bab9d1eb2e618b..c22f4c5a862312 100644 --- a/src/platform/nxp/k32w/k32w0/K32W0Config.cpp +++ b/src/platform/nxp/k32w/k32w0/K32W0Config.cpp @@ -36,7 +36,8 @@ namespace chip { namespace DeviceLayer { namespace Internal { -static ramBufferDescriptor * ramDescr; +osaMutexId_t K32WConfig::pdmMutexHandle = NULL; +static ramBufferDescriptor * ramDescr = NULL; constexpr uint16_t kNvmIdChipConfigData = 0x5000; constexpr uint16_t kRamBufferInitialSize = 3072; @@ -47,6 +48,8 @@ CHIP_ERROR K32WConfig::Init() int pdmStatus; /* Initialise the Persistent Data Manager */ + pdmMutexHandle = OSA_MutexCreate(); + VerifyOrExit((NULL != pdmMutexHandle), err = CHIP_ERROR_NO_MEMORY); pdmStatus = PDM_Init(); SuccessOrExit(err = MapPdmInitStatus(pdmStatus)); @@ -57,9 +60,38 @@ CHIP_ERROR K32WConfig::Init() } exit: + if (err != CHIP_NO_ERROR) + { + if (pdmMutexHandle) + { + OSA_MutexDestroy(pdmMutexHandle); + } + if (ramDescr) + { + free(ramDescr); + } + } return err; } +void K32WConfig::MutexLock(osaMutexId_t mutexId, uint32_t millisec) +{ + osaStatus_t status = OSA_MutexLock(mutexId, millisec); + if (osaStatus_Success != status) + { + ChipLogProgress(DeviceLayer, "OSA mutex lock failed."); + } +} + +void K32WConfig::MutexUnlock(osaMutexId_t mutexId) +{ + osaStatus_t status = OSA_MutexUnlock(mutexId); + if (osaStatus_Success != status) + { + ChipLogProgress(DeviceLayer, "OSA mutex unlock failed."); + } +} + CHIP_ERROR K32WConfig::ReadConfigValue(Key key, bool & val) { CHIP_ERROR err; @@ -139,53 +171,119 @@ CHIP_ERROR K32WConfig::ReadConfigValueCounter(uint8_t counterIdx, uint32_t & val CHIP_ERROR K32WConfig::WriteConfigValue(Key key, bool val) { CHIP_ERROR err; - rsError status; PDM_teStatus pdmStatus; + rsError ramStatus = RS_ERROR_NONE; VerifyOrExit(ValidConfigKey(key), err = CHIP_DEVICE_ERROR_CONFIG_NOT_FOUND); // Verify key id. - status = ramStorageSet(&ramDescr, key, (uint8_t *) &val, sizeof(bool)); - SuccessOrExit(err = MapRamStorageStatus(status)); + MutexLock(pdmMutexHandle, osaWaitForever_c); + + /* first delete all occurrences of "key" */ + ramStorageDelete(ramDescr, key, -1); + + /* resize RAM Buffer if needed */ + ramStatus = ramStorageResize(&ramDescr, key, (uint8_t *) &val, sizeof(bool)); + SuccessOrExit(err = MapRamStorageStatus(ramStatus)); + + /* add to RAM buffer */ + ramStatus = ramStorageSet(ramDescr, key, (uint8_t *) &val, sizeof(bool)); + SuccessOrExit(err = MapRamStorageStatus(ramStatus)); + + /* schedule flash writing */ + pdmStatus = PDM_eSaveRecordDataInIdleTask(kNvmIdChipConfigData, ramDescr, ramDescr->ramBufferLen + kRamDescHeaderSize); + SuccessOrExit(err = MapPdmStatus(pdmStatus)); + +exit: + MutexUnlock(pdmMutexHandle); + return err; +} + +CHIP_ERROR K32WConfig::WriteConfigValueSync(Key key, bool val) +{ + CHIP_ERROR err; + PDM_teStatus pdmStatus; + rsError ramStatus = RS_ERROR_NONE; + + VerifyOrExit(ValidConfigKey(key), err = CHIP_DEVICE_ERROR_CONFIG_NOT_FOUND); // Verify key id. + MutexLock(pdmMutexHandle, osaWaitForever_c); + + /* first delete all occurrences of "key" */ + ramStorageDelete(ramDescr, key, -1); - pdmStatus = - PDM_eSaveRecordDataInIdleTask((uint16_t) kNvmIdChipConfigData, ramDescr, ramDescr->ramBufferLen + kRamDescHeaderSize); + /* resize RAM Buffer if needed */ + ramStatus = ramStorageResize(&ramDescr, key, (uint8_t *) &val, sizeof(bool)); + SuccessOrExit(err = MapRamStorageStatus(ramStatus)); + + /* add to RAM buffer */ + ramStatus = ramStorageSet(ramDescr, key, (uint8_t *) &val, sizeof(bool)); + SuccessOrExit(err = MapRamStorageStatus(ramStatus)); + + // Interrupts are disabled to ensure there is no context switch during the actual + // writing, thus avoiding race conditions. + OSA_InterruptDisable(); + pdmStatus = PDM_eSaveRecordData(kNvmIdChipConfigData, ramDescr, ramDescr->ramBufferLen + kRamDescHeaderSize); + OSA_InterruptEnable(); SuccessOrExit(err = MapPdmStatus(pdmStatus)); + exit: + MutexUnlock(pdmMutexHandle); return err; } CHIP_ERROR K32WConfig::WriteConfigValue(Key key, uint32_t val) { CHIP_ERROR err; - rsError status; PDM_teStatus pdmStatus; + rsError ramStatus = RS_ERROR_NONE; VerifyOrExit(ValidConfigKey(key), err = CHIP_DEVICE_ERROR_CONFIG_NOT_FOUND); // Verify key id. - status = ramStorageSet(&ramDescr, key, (uint8_t *) &val, sizeof(uint32_t)); - SuccessOrExit(err = MapRamStorageStatus(status)); + MutexLock(pdmMutexHandle, osaWaitForever_c); + + /* first delete all occurrences of "key" */ + ramStorageDelete(ramDescr, key, -1); - pdmStatus = - PDM_eSaveRecordDataInIdleTask((uint16_t) kNvmIdChipConfigData, ramDescr, ramDescr->ramBufferLen + kRamDescHeaderSize); + /* resize RAM Buffer if needed */ + ramStatus = ramStorageResize(&ramDescr, key, (uint8_t *) &val, sizeof(uint32_t)); + SuccessOrExit(err = MapRamStorageStatus(ramStatus)); + + /* add to RAM buffer */ + ramStatus = ramStorageSet(ramDescr, key, (uint8_t *) &val, sizeof(uint32_t)); + SuccessOrExit(err = MapRamStorageStatus(ramStatus)); + + /* schedule flash writing */ + pdmStatus = PDM_eSaveRecordDataInIdleTask(kNvmIdChipConfigData, ramDescr, ramDescr->ramBufferLen + kRamDescHeaderSize); SuccessOrExit(err = MapPdmStatus(pdmStatus)); exit: + MutexUnlock(pdmMutexHandle); return err; } CHIP_ERROR K32WConfig::WriteConfigValue(Key key, uint64_t val) { CHIP_ERROR err; - rsError status; PDM_teStatus pdmStatus; + rsError ramStatus = RS_ERROR_NONE; VerifyOrExit(ValidConfigKey(key), err = CHIP_DEVICE_ERROR_CONFIG_NOT_FOUND); // Verify key id. - status = ramStorageSet(&ramDescr, key, (uint8_t *) &val, sizeof(uint64_t)); - SuccessOrExit(err = MapRamStorageStatus(status)); + MutexLock(pdmMutexHandle, osaWaitForever_c); + + /* first delete all occurrences of "key" */ + ramStorageDelete(ramDescr, key, -1); + + /* resize RAM Buffer if needed */ + ramStatus = ramStorageResize(&ramDescr, key, (uint8_t *) &val, sizeof(uint64_t)); + SuccessOrExit(err = MapRamStorageStatus(ramStatus)); - pdmStatus = - PDM_eSaveRecordDataInIdleTask((uint16_t) kNvmIdChipConfigData, ramDescr, ramDescr->ramBufferLen + kRamDescHeaderSize); + /* add to RAM buffer */ + ramStatus = ramStorageSet(ramDescr, key, (uint8_t *) &val, sizeof(uint64_t)); + SuccessOrExit(err = MapRamStorageStatus(ramStatus)); + + /* schedule flash writing */ + pdmStatus = PDM_eSaveRecordDataInIdleTask(kNvmIdChipConfigData, ramDescr, ramDescr->ramBufferLen + kRamDescHeaderSize); SuccessOrExit(err = MapPdmStatus(pdmStatus)); exit: + MutexUnlock(pdmMutexHandle); return err; } @@ -198,26 +296,35 @@ CHIP_ERROR K32WConfig::WriteConfigValueStr(Key key, const char * str, size_t str { CHIP_ERROR err; PDM_teStatus pdmStatus; - rsError status; + rsError ramStatus = RS_ERROR_NONE; VerifyOrExit(ValidConfigKey(key), err = CHIP_DEVICE_ERROR_CONFIG_NOT_FOUND); // Verify key id. + MutexLock(pdmMutexHandle, osaWaitForever_c); - if (str != NULL) + if (!str) { - status = ramStorageSet(&ramDescr, key, (uint8_t *) str, strLen); - SuccessOrExit(err = MapRamStorageStatus(status)); - - pdmStatus = - PDM_eSaveRecordDataInIdleTask((uint16_t) kNvmIdChipConfigData, ramDescr, ramDescr->ramBufferLen + kRamDescHeaderSize); - SuccessOrExit(err = MapPdmStatus(pdmStatus)); + ramStatus = ramStorageDelete(ramDescr, key, -1); + SuccessOrExit(err = MapRamStorageStatus(ramStatus)); } else { - err = ClearConfigValue(key); - SuccessOrExit(err); + /* first delete all occurrences of "key" */ + ramStorageDelete(ramDescr, key, -1); + + /* resize RAM Buffer if needed */ + ramStatus = ramStorageResize(&ramDescr, key, (uint8_t *) str, strLen); + SuccessOrExit(err = MapRamStorageStatus(ramStatus)); + + /* add to RAM buffer */ + ramStatus = ramStorageSet(ramDescr, key, (uint8_t *) str, strLen); + SuccessOrExit(err = MapRamStorageStatus(ramStatus)); + + /* schedule flash writing */ + pdmStatus = PDM_eSaveRecordDataInIdleTask(kNvmIdChipConfigData, ramDescr, ramDescr->ramBufferLen + kRamDescHeaderSize); } exit: + MutexUnlock(pdmMutexHandle); return err; } @@ -239,14 +346,15 @@ CHIP_ERROR K32WConfig::ClearConfigValue(Key key) PDM_teStatus pdmStatus; VerifyOrExit(ValidConfigKey(key), err = CHIP_DEVICE_ERROR_CONFIG_NOT_FOUND); // Verify key id. - status = ramStorageDelete(ramDescr, key, 0); + MutexLock(pdmMutexHandle, osaWaitForever_c); + status = ramStorageDelete(ramDescr, key, -1); SuccessOrExit(err = MapRamStorageStatus(status)); - pdmStatus = - PDM_eSaveRecordDataInIdleTask((uint16_t) kNvmIdChipConfigData, ramDescr, ramDescr->ramBufferLen + kRamDescHeaderSize); + pdmStatus = PDM_eSaveRecordDataInIdleTask(kNvmIdChipConfigData, ramDescr, ramDescr->ramBufferLen + kRamDescHeaderSize); SuccessOrExit(err = MapPdmStatus(pdmStatus)); exit: + MutexUnlock(pdmMutexHandle); return err; } @@ -269,14 +377,18 @@ CHIP_ERROR K32WConfig::FactoryResetConfig(void) CHIP_ERROR err = CHIP_NO_ERROR; PDM_teStatus pdmStatus; + MutexLock(pdmMutexHandle, osaWaitForever_c); FactoryResetConfigInternal(kMinConfigKey_ChipConfig, kMaxConfigKey_ChipConfig); FactoryResetConfigInternal(kMinConfigKey_KVSKey, kMaxConfigKey_KVSKey); FactoryResetConfigInternal(kMinConfigKey_KVSValue, kMaxConfigKey_KVSValue); - pdmStatus = PDM_eSaveRecordData((uint16_t) kNvmIdChipConfigData, ramDescr, ramDescr->ramBufferLen + kRamDescHeaderSize); + pdmStatus = PDM_eSaveRecordData(kNvmIdChipConfigData, ramDescr, ramDescr->ramBufferLen + kRamDescHeaderSize); SuccessOrExit(err = MapPdmStatus(pdmStatus)); exit: + free((void *) ramDescr); + ramDescr = NULL; + MutexUnlock(pdmMutexHandle); return err; } @@ -284,7 +396,7 @@ void K32WConfig::FactoryResetConfigInternal(Key firstKey, Key lastKey) { for (Key key = firstKey; key <= lastKey; key++) { - ramStorageDelete(ramDescr, key, 0); + ramStorageDelete(ramDescr, key, -1); } } diff --git a/src/platform/nxp/k32w/k32w0/K32W0Config.h b/src/platform/nxp/k32w/k32w0/K32W0Config.h index 803149947a7a71..cc8919cf21ebb9 100644 --- a/src/platform/nxp/k32w/k32w0/K32W0Config.h +++ b/src/platform/nxp/k32w/k32w0/K32W0Config.h @@ -29,7 +29,9 @@ #include #include "PDM.h" -#include "RamStorage.h" +#include "fsl_os_abstraction.h" +#include "pdm_ram_storage_glue.h" +#include "ram_storage.h" namespace chip { namespace DeviceLayer { @@ -122,6 +124,7 @@ class K32WConfig static CHIP_ERROR ReadConfigValueBin(Key key, uint8_t * buf, size_t bufSize, size_t & outLen); static CHIP_ERROR ReadConfigValueCounter(uint8_t counterIdx, uint32_t & val); static CHIP_ERROR WriteConfigValue(Key key, bool val); + static CHIP_ERROR WriteConfigValueSync(Key key, bool val); static CHIP_ERROR WriteConfigValue(Key key, uint32_t val); static CHIP_ERROR WriteConfigValue(Key key, uint64_t val); static CHIP_ERROR WriteConfigValueStr(Key key, const char * str); @@ -135,6 +138,12 @@ class K32WConfig static void RunConfigUnitTest(void); + // Log error wrappers for OSA mutex lock/unlock. + static void MutexLock(osaMutexId_t mutexId, uint32_t millisec); + static void MutexUnlock(osaMutexId_t mutexId); + + static osaMutexId_t pdmMutexHandle; + protected: static constexpr uint8_t GetPDMId(uint32_t key); static constexpr uint8_t GetRecordKey(uint32_t key); diff --git a/src/platform/nxp/k32w/k32w0/KeyValueStoreManagerImpl.cpp b/src/platform/nxp/k32w/k32w0/KeyValueStoreManagerImpl.cpp index 8cd1914211f121..f2fbd071bc3654 100644 --- a/src/platform/nxp/k32w/k32w0/KeyValueStoreManagerImpl.cpp +++ b/src/platform/nxp/k32w/k32w0/KeyValueStoreManagerImpl.cpp @@ -93,10 +93,14 @@ CHIP_ERROR KeyValueStoreManagerImpl::_Get(const char * key, void * value, size_t { // This is the ID of the actual data pdmInternalId = chip::DeviceLayer::Internal::K32WConfigKey(pdmIdKvsValue, keyId); + ChipLogProgress(DeviceLayer, "KVS, get the value of Matter key [%s] with PDM id: %i", key, pdmInternalId); err = chip::DeviceLayer::Internal::K32WConfig::ReadConfigValueBin(pdmInternalId, (uint8_t *) value, value_size, read_bytes); *read_bytes_size = read_bytes; - - ChipLogProgress(DeviceLayer, "KVS, get Matter key [%s] with PDM id: %i", key, pdmInternalId); + } + else + { + ChipLogProgress(DeviceLayer, "KVS, error in getting the value of Matter key [%s]. Key not found in persistent storage.", + key); } exit: @@ -118,15 +122,9 @@ CHIP_ERROR KeyValueStoreManagerImpl::_Put(const char * key, const void * value, keyId = GetStringKeyId(key, &freeKeyId); - // Key already exists - if (keyId < kMaxNumberOfKeys) - { - // Update just the value in this case - putKey = false; - } - else + // Key does not exist. Write both key and value in persistent storage. + if (kMaxNumberOfKeys == keyId) { - // Need to write both the value and the string key putKey = true; keyId = freeKeyId; } diff --git a/src/platform/nxp/k32w/k32w0/KeyValueStoreManagerImpl.h b/src/platform/nxp/k32w/k32w0/KeyValueStoreManagerImpl.h index 0b0a09178ed44d..df942779fe4bc2 100644 --- a/src/platform/nxp/k32w/k32w0/KeyValueStoreManagerImpl.h +++ b/src/platform/nxp/k32w/k32w0/KeyValueStoreManagerImpl.h @@ -1,3 +1,4 @@ + /* * * Copyright (c) 2021 Project CHIP Authors diff --git a/src/platform/nxp/k32w/k32w0/Logging.cpp b/src/platform/nxp/k32w/k32w0/Logging.cpp index eca2baf51216c1..da545b6c7aff85 100644 --- a/src/platform/nxp/k32w/k32w0/Logging.cpp +++ b/src/platform/nxp/k32w/k32w0/Logging.cpp @@ -28,7 +28,6 @@ static constexpr uint8_t category_max_len_bytes = 3; #endif // CHIP_DEVICE_CONFIG_ENABLE_THREAD static bool isLogInitialized; -extern uint8_t gOtLogUartInstance; extern "C" uint32_t otPlatAlarmMilliGetNow(void); namespace chip { @@ -108,8 +107,7 @@ void ENFORCE_FORMAT(1, 0) GenericLog(const char * format, va_list arg, const cha if (!isLogInitialized) { - isLogInitialized = true; - gOtLogUartInstance = 0; + isLogInitialized = true; otPlatUartEnable(); } diff --git a/src/platform/nxp/k32w/k32w0/OTAImageProcessorImpl.cpp b/src/platform/nxp/k32w/k32w0/OTAImageProcessorImpl.cpp index 27deee3fece95f..a44d0cb1dfec6e 100644 --- a/src/platform/nxp/k32w/k32w0/OTAImageProcessorImpl.cpp +++ b/src/platform/nxp/k32w/k32w0/OTAImageProcessorImpl.cpp @@ -83,7 +83,11 @@ void OTAImageProcessorImpl::TriggerNewRequestForData() { if (mDownloader) { + // The chip lock needs to be taken here to avoid having race conditions + // when trying to read attributes during OTA transfer. See https://github.com/project-chip/connectedhomeip/issues/18327 + PlatformMgr().LockChipStack(); this->mDownloader->FetchNextData(); + PlatformMgr().UnlockChipStack(); } } @@ -209,7 +213,7 @@ bool OTAImageProcessorImpl::IsFirstImageRun() { bool firstRun = false; - if (CHIP_NO_ERROR == (K32WConfig::ReadConfigValue(K32WConfig::kConfigKey_FirstRunOfOTAImage, firstRun))) + if (CHIP_NO_ERROR == K32WConfig::ReadConfigValue(K32WConfig::kConfigKey_FirstRunOfOTAImage, firstRun)) { return firstRun; } @@ -276,9 +280,7 @@ void OTAImageProcessorImpl::HandleApply(intptr_t context) OTA_CommitImage(NULL); if (OTA_ImageAuthenticate() == gOtaImageAuthPass_c) { - - /* TODO internal: MATTER-126 */ - /*if (CHIP_NO_ERROR == K32WConfig::WriteConfigValue(K32WConfig::kConfigKey_FirstRunOfOTAImage, firstRun)) */ + if (CHIP_NO_ERROR == K32WConfig::WriteConfigValueSync(K32WConfig::kConfigKey_FirstRunOfOTAImage, firstRun)) { /* Set the necessary information to inform the SSBL that a new image is available */ DeviceLayer::ConfigurationMgr().StoreSoftwareVersion(imageProcessor->mSoftwareVersion); @@ -286,10 +288,14 @@ void OTAImageProcessorImpl::HandleApply(intptr_t context) ChipLogProgress(SoftwareUpdate, "OTA image authentication success. Device will reboot with the new image!"); ResetMCU(); } + else + { + ChipLogProgress(SoftwareUpdate, "Failed to write kConfigKey_FirstRunOfOTAImage key."); + } } else { - ChipLogError(SoftwareUpdate, "Image authentication error"); + ChipLogError(SoftwareUpdate, "Image authentication error."); } } diff --git a/src/platform/nxp/k32w/k32w0/PlatformManagerImpl.cpp b/src/platform/nxp/k32w/k32w0/PlatformManagerImpl.cpp index 911b2e9ad73d71..4e7240c1f32202 100644 --- a/src/platform/nxp/k32w/k32w0/PlatformManagerImpl.cpp +++ b/src/platform/nxp/k32w/k32w0/PlatformManagerImpl.cpp @@ -35,9 +35,12 @@ #include #endif +#if defined(MBEDTLS_USE_TINYCRYPT) +#include "ecc.h" +#endif + #include -#include "K32W061.h" #include "MemManager.h" #include "RNG_Interface.h" #include "TimersManager.h" @@ -49,6 +52,10 @@ namespace DeviceLayer { PlatformManagerImpl PlatformManagerImpl::sInstance; +#if defined(MBEDTLS_USE_TINYCRYPT) +osaMutexId_t PlatformManagerImpl::rngMutexHandle = NULL; +#endif + CHIP_ERROR PlatformManagerImpl::InitBoardFwk(void) { CHIP_ERROR err = CHIP_NO_ERROR; @@ -93,6 +100,18 @@ static int app_entropy_source(void * data, unsigned char * output, size_t len, s return 0; } +#if defined(MBEDTLS_USE_TINYCRYPT) +int PlatformManagerImpl::uECC_RNG_Function(uint8_t * dest, unsigned int size) +{ + int res; + OSA_MutexLock(rngMutexHandle, osaWaitForever_c); + res = (chip::Crypto::DRBG_get_bytes(dest, size) == CHIP_NO_ERROR) ? size : 0; + OSA_MutexUnlock(rngMutexHandle); + + return res; +} +#endif + CHIP_ERROR PlatformManagerImpl::_InitChipStack(void) { uint32_t chipType; @@ -123,6 +142,13 @@ CHIP_ERROR PlatformManagerImpl::_InitChipStack(void) err = chip::Crypto::add_entropy_source(app_entropy_source, NULL, 16); SuccessOrExit(err); +#if defined(MBEDTLS_USE_TINYCRYPT) + /* Set RNG function for tinycrypt operations. */ + rngMutexHandle = OSA_MutexCreate(); + VerifyOrExit((NULL != rngMutexHandle), err = CHIP_ERROR_NO_MEMORY); + uECC_set_rng(PlatformManagerImpl::uECC_RNG_Function); +#endif + // Call _InitChipStack() on the generic implementation base class // to finish the initialization process. err = Internal::GenericPlatformManagerImpl_FreeRTOS::_InitChipStack(); diff --git a/src/platform/nxp/k32w/k32w0/PlatformManagerImpl.h b/src/platform/nxp/k32w/k32w0/PlatformManagerImpl.h index 70ece1cdf11f3c..6e241c1dbd62b8 100644 --- a/src/platform/nxp/k32w/k32w0/PlatformManagerImpl.h +++ b/src/platform/nxp/k32w/k32w0/PlatformManagerImpl.h @@ -25,6 +25,7 @@ #pragma once +#include "fsl_os_abstraction.h" #include namespace chip { @@ -51,6 +52,17 @@ class PlatformManagerImpl final : public PlatformManager, public Internal::Gener System::Clock::Timestamp GetStartTime() { return mStartTime; } CHIP_ERROR InitBoardFwk(void); +#if defined(MBEDTLS_USE_TINYCRYPT) + // Since the RNG callback will be called from multiple threads, + // use this mutex to lock/unlock the call to Matter RNG API, which + // uses some global variables. + static osaMutexId_t rngMutexHandle; + // Callback used by tinycrypt to generate random numbers. + // It must be set before calling any sign operations, + // which are used in both Matter and OT threads. + static int uECC_RNG_Function(uint8_t * dest, unsigned int size); +#endif + private: // ===== Methods that implement the PlatformManager abstract interface. diff --git a/src/platform/nxp/k32w/k32w0/SystemPlatformConfig.h b/src/platform/nxp/k32w/k32w0/SystemPlatformConfig.h index a589a86223d16d..f7514dcb68bec9 100644 --- a/src/platform/nxp/k32w/k32w0/SystemPlatformConfig.h +++ b/src/platform/nxp/k32w/k32w0/SystemPlatformConfig.h @@ -37,7 +37,7 @@ struct ChipDeviceEvent; // ==================== Platform Adaptations ==================== #define CHIP_SYSTEM_CONFIG_PLATFORM_PROVIDES_TIME 1 #define CHIP_SYSTEM_CONFIG_EVENT_OBJECT_TYPE const struct ::chip::DeviceLayer::ChipDeviceEvent * -#define CHIP_SYSTEM_CONFIG_PACKETBUFFER_POOL_SIZE 11 +#define CHIP_SYSTEM_CONFIG_PACKETBUFFER_POOL_SIZE 7 // ========== Platform-specific Configuration Overrides ========= diff --git a/src/platform/nxp/k32w/k32w0/ThreadStackManagerImpl.cpp b/src/platform/nxp/k32w/k32w0/ThreadStackManagerImpl.cpp index 7f5d4961ba41e4..78ccc1b9b0abf3 100644 --- a/src/platform/nxp/k32w/k32w0/ThreadStackManagerImpl.cpp +++ b/src/platform/nxp/k32w/k32w0/ThreadStackManagerImpl.cpp @@ -107,3 +107,8 @@ extern "C" void otPlatFree(void * aPtr) { return CHIPPlatformMemoryFree(aPtr); } + +extern "C" void * otPlatRealloc(void * p, size_t aSize) +{ + return CHIPPlatformMemoryRealloc(p, aSize); +} diff --git a/third_party/nxp/k32w0_sdk/BUILD.gn b/third_party/nxp/k32w0_sdk/BUILD.gn index f2307bafa95ca4..79d2e2a6ee1a6a 100644 --- a/third_party/nxp/k32w0_sdk/BUILD.gn +++ b/third_party/nxp/k32w0_sdk/BUILD.gn @@ -29,6 +29,13 @@ group("k32w0_sdk") { public_deps = [ k32w0_sdk_target ] } +if (chip_crypto == "tinycrypt") { + assert( + mbedtls_repo == + "//third_party/connectedhomeip/third_party/nxp/libs/mbedtls", + "mbedtls_repo must be set to nxp mbedtls-tinycrypt library when chip_crypto == \"tinycrypt\"") +} + config("mbedtls_k32w0_config") { defines = [ "MBEDTLS_CONFIG_FILE=", @@ -53,7 +60,7 @@ config("mbedtls_k32w0_config") { ] } - if (mbedtls_use_tinycrypt) { + if (chip_crypto == "tinycrypt") { defines += [ "MBEDTLS_USE_TINYCRYPT", "MBEDTLS_OPTIMIZE_TINYCRYPT_ASM", @@ -62,7 +69,7 @@ config("mbedtls_k32w0_config") { include_dirs = [ chip_root ] - if (mbedtls_use_tinycrypt) { + if (chip_crypto == "tinycrypt") { include_dirs += [ "${mbedtls_repo}/repo/include/tinycrypt" ] } } @@ -73,7 +80,7 @@ mbedtls_target("mbedtls") { "${k32w0_sdk_root}/middleware/mbedtls/port/ksdk/ksdk_mbedtls.c", ] - if (mbedtls_use_tinycrypt) { + if (chip_crypto == "tinycrypt") { sources += [ "${mbedtls_repo}/repo/tinycrypt/ecc.c", "${mbedtls_repo}/repo/tinycrypt/ecc_dh.c", diff --git a/third_party/nxp/k32w0_sdk/k32w0_sdk.gni b/third_party/nxp/k32w0_sdk/k32w0_sdk.gni index a0aa55ada6b4be..d0aa619d6a6968 100644 --- a/third_party/nxp/k32w0_sdk/k32w0_sdk.gni +++ b/third_party/nxp/k32w0_sdk/k32w0_sdk.gni @@ -24,12 +24,19 @@ import("${chip_root}/src/platform/nxp/k32w/k32w0/args.gni") declare_args() { # Location of the k32w0 SDK. - k32w0_sdk_root = getenv("NXP_K32W061_SDK_ROOT") + k32w0_sdk_root = getenv("NXP_K32W0_SDK_ROOT") chip_with_DK6 = true chip_with_OM15082 = 0 chip_with_ot_cli = 0 chip_with_low_power = 0 - mbedtls_use_tinycrypt = false + build_for_k32w061 = 1 + build_for_k32w041am = 0 + build_for_k32w041a = 0 + build_for_k32w041 = 0 + device = "K32W061" + board = "k32w061dk6" + chip_with_ntag = 1 + chip_with_high_power = 0 } assert(k32w0_sdk_root != "", "k32w0_sdk_root must be specified") @@ -57,6 +64,54 @@ template("k32w0_sdk") { chip_with_ot_cli == 0 && chip_with_se05x == 0), "Please disable low power if expansion board, openthread CLI or SE is needed!") + if (build_for_k32w041am == 1 || build_for_k32w041a == 1 || + build_for_k32w041 == 1) { + build_for_k32w061 = 0 + } + + if (build_for_k32w061 == 1) { + assert(build_for_k32w061 == 1 && build_for_k32w041am == 0 && + build_for_k32w041a == 0 && build_for_k32w041 == 0, + "Please build for only one platform") + device = "K32W061" + board = "k32w061dk6" + chip_with_ntag = 1 + chip_with_high_power = 0 + } + if (build_for_k32w041am == 1) { + assert(build_for_k32w041am == 1 && build_for_k32w061 == 0 && + build_for_k32w041a == 0 && build_for_k32w041 == 0, + "Please build for only one platform") + device = "K32W041AM" + board = "k32w041amdk6" + chip_with_high_power = 1 + chip_with_ntag = 0 + } + if (build_for_k32w041a == 1) { + assert(build_for_k32w041a == 1 && build_for_k32w061 == 0 && + build_for_k32w041am == 0 && build_for_k32w041 == 0, + "Please build for only one platform") + device = "K32W041A" + board = "k32w041adk6" + chip_with_high_power = 1 + chip_with_ntag = 0 + } + if (build_for_k32w041 == 1) { + assert(build_for_k32w041 == 1 && build_for_k32w061 == 0 && + build_for_k32w041am == 0 && build_for_k32w041a == 0, + "Please build for only one platform") + device = "K32W041" + board = "k32w041dk6" + chip_with_ntag = 0 + chip_with_high_power = 0 + } + + print("device:", device) + print("board:", board) + print("ntag:", chip_with_ntag) + print("high power:", chip_with_high_power) + device_lowercase = string_replace(board, "dk6", "") + sdk_target_name = target_name config("${sdk_target_name}_config") { @@ -72,14 +127,23 @@ template("k32w0_sdk") { if (chip_with_DK6) { if (chip_with_low_power != 0) { - _sdk_include_dirs += [ "${k32w0_sdk_root}/boards/k32w061dk6/wireless_examples/openthread/lped/bm" ] + _sdk_include_dirs += [ "${k32w0_sdk_root}/boards/${board}/wireless_examples/openthread/lped/bm" ] } else { - _sdk_include_dirs += [ "${k32w0_sdk_root}/boards/k32w061dk6/wireless_examples/openthread/reed/bm" ] + _sdk_include_dirs += [ "${k32w0_sdk_root}/boards/${board}/wireless_examples/openthread/reed/bm" ] } } if (chip_with_low_power != 0) { - _sdk_include_dirs += [ "${k32w0_sdk_root}/boards/k32w061dk6/wireless_examples/hybrid/ble_ot/lped_ble_wuart/ble_802_15_4_common" ] + _sdk_include_dirs += [ "${k32w0_sdk_root}/boards/${board}/wireless_examples/hybrid/ble_ot/lped_ble_wuart/ble_802_15_4_common" ] + } + + if (chip_with_ntag != 0) { + _sdk_include_dirs += [ + "${k32w0_sdk_root}/middleware/ntag_i2c_plus/HAL_I2C/inc", + "${k32w0_sdk_root}/middleware/ntag_i2c_plus/HAL_NTAG/inc", + "${k32w0_sdk_root}/middleware/ntag_i2c_plus/inc", + "${k32w0_sdk_root}/middleware/ntag_i2c_plus/HAL_TMR/inc", + ] } _sdk_include_dirs += [ @@ -87,16 +151,12 @@ template("k32w0_sdk") { "${k32w0_sdk_root}/CMSIS/Include", "${k32w0_sdk_root}/components/serial_manager", "${k32w0_sdk_root}/components/uart", - "${k32w0_sdk_root}/devices/K32W061", - "${k32w0_sdk_root}/devices/K32W061/drivers", - "${k32w0_sdk_root}/devices/K32W061/utilities", - "${k32w0_sdk_root}/devices/K32W061/utilities/debug_console", - "${k32w0_sdk_root}/devices/K32W061/utilities/str", + "${k32w0_sdk_root}/devices/${device}", + "${k32w0_sdk_root}/devices/${device}/drivers", + "${k32w0_sdk_root}/devices/${device}/utilities", + "${k32w0_sdk_root}/devices/${device}/utilities/debug_console", + "${k32w0_sdk_root}/devices/${device}/utilities/str", "${k32w0_sdk_root}/middleware/mbedtls/port/ksdk", - "${k32w0_sdk_root}/middleware/ntag_i2c_plus/HAL_I2C/inc", - "${k32w0_sdk_root}/middleware/ntag_i2c_plus/HAL_NTAG/inc", - "${k32w0_sdk_root}/middleware/ntag_i2c_plus/inc", - "${k32w0_sdk_root}/middleware/ntag_i2c_plus/HAL_TMR/inc", "${k32w0_sdk_root}/middleware/wireless/ble_controller/interface", "${k32w0_sdk_root}/middleware/wireless/bluetooth/application/common", "${k32w0_sdk_root}/middleware/wireless/bluetooth/application/common/gatt_db", @@ -112,7 +172,7 @@ template("k32w0_sdk") { "${k32w0_sdk_root}/middleware/wireless/framework/Keyboard/Interface", "${k32w0_sdk_root}/middleware/wireless/framework/LED/Interface", "${k32w0_sdk_root}/middleware/wireless/framework/Lists", - "${k32w0_sdk_root}/middleware/wireless/framework/LowPower/Interface/k32w061dk6", + "${k32w0_sdk_root}/middleware/wireless/framework/LowPower/Interface/${board}", "${k32w0_sdk_root}/middleware/wireless/framework/MemManager/Interface", "${k32w0_sdk_root}/middleware/wireless/framework/Messaging/Interface", "${k32w0_sdk_root}/middleware/wireless/framework/ModuleInfo", @@ -137,9 +197,9 @@ template("k32w0_sdk") { ] libs = [ - "${k32w0_sdk_root}/middleware/wireless/ble_controller/lib/lib_ble_controller.a", - "${k32w0_sdk_root}//middleware/wireless/bluetooth/host/lib/lib_ble_5-0_host_peripheral_cm4_noFP.a", - "${k32w0_sdk_root}/middleware/wireless/ieee-802.15.4/lib/libMiniMac_Dynamic_MMAC.a", + "${k32w0_sdk_root}/middleware/wireless/ble_controller/lib/lib_ble_controller_peripheral_commissioning.a", + "${k32w0_sdk_root}//middleware/wireless/bluetooth/host/lib/lib_ble_5-0_host_matter_cm4_noFP.a", + "${k32w0_sdk_root}/middleware/wireless/ieee-802.15.4/lib/libMiniMac_Sched.a", "${k32w0_sdk_root}/middleware/wireless/framework/PDM/Library/libPDM_extFlash.a", "${k32w0_sdk_root}/middleware/wireless/framework/SecLib/lib_crypto_m4.a", "${k32w0_sdk_root}/middleware/wireless/framework/XCVR/lib/libRadio.a", @@ -148,18 +208,20 @@ template("k32w0_sdk") { defines = [ "gPWR_CpuClk_48MHz=1", "gMainThreadPriority_c=5", - "CPU_K32W061HN", "CPU_JN518X", "CPU_JN518X_REV=2", "JENNIC_CHIP_FAMILY_NAME=_JN518x", + "MAC_PROTO_TAG=1", + "JENNIC_CHIP_FAMILY_JN518x", "gPWR_LDOMEM_0_9V_PD=0", "SDK_DEBUGCONSOLE=DEBUGCONSOLE_REDIRECT_TO_SDK", + "PRINTF_ADVANCED_ENABLE", "NO_SYSCORECLK_UPD=0", "USE_RTOS=1", "USE_SDK_OSA=0", "gSerialManagerMaxInterfaces_c=2", "FSL_RTOS_FREE_RTOS=1", - "gTotalHeapSize_c=0xB000", + "gTotalHeapSize_c=0xC8BC", "gUartDebugConsole_d=1", "DEBUG_SERIAL_INTERFACE_INSTANCE=0", "APP_SERIAL_INTERFACE_INSTANCE=1", @@ -168,6 +230,7 @@ template("k32w0_sdk") { "gOtaEepromPostedOperations_d=1", "gOtaVerifyWrite_d=0", "gExternalFlashIsCiphered_d=1", + "PDM_USE_DYNAMIC_MEMORY=1", "gBootData_None_c=1", "PROGRAM_PAGE_SZ=256", "configFRTOS_MEMORY_SCHEME=4", @@ -220,6 +283,7 @@ template("k32w0_sdk") { "PDM_EXT_FLASH=1", "gEepromType_d=gEepromDevice_MX25R8035F_c", "gPdmNbSegments=63", + "gRadioUsePdm_d=1", ] if (chip_with_OM15082 != 0) { @@ -266,6 +330,34 @@ template("k32w0_sdk") { ] } + if (build_for_k32w061 == 1) { + defines += [ "CPU_K32W061HN" ] + } else if (build_for_k32w041am == 1) { + defines += [ "CPU_K32W041AMZ" ] + } else if (build_for_k32w041a == 1) { + defines += [ "CPU_K32W041AZ" ] + } else if (build_for_k32w041 == 1) { + defines += [ "CPU_K32W041HN" ] + } + + if (chip_with_high_power == 1) { + defines += [ + "K32WMCM_APP_BUILD", + "JENNIC_CHIP_FAMILY_JN518x", + ] + _sdk_include_dirs += [ + "${k32w0_sdk_root}/middleware/wireless/ieee-802.15.4/Include", + "${k32w0_sdk_root}/middleware/wireless/ieee-802.15.4/mMac/Include", + ] + } + + if (chip_with_ntag == 1) { + defines += [ + "CONFIG_CHIP_NFC_COMMISSIONING=1", + "CHIP_DEVICE_CONFIG_ENABLE_NFC=1", + ] + } + if (defined(invoker.defines)) { defines += invoker.defines } @@ -309,35 +401,31 @@ template("k32w0_sdk") { "${k32w0_sdk_root}/components/serial_manager/serial_manager.c", "${k32w0_sdk_root}/components/serial_manager/serial_port_uart.c", "${k32w0_sdk_root}/components/uart/usart_adapter.c", - "${k32w0_sdk_root}/devices/K32W061/drivers/fsl_adc.c", - "${k32w0_sdk_root}/devices/K32W061/drivers/fsl_aes.c", - "${k32w0_sdk_root}/devices/K32W061/drivers/fsl_clock.c", - "${k32w0_sdk_root}/devices/K32W061/drivers/fsl_common.c", - "${k32w0_sdk_root}/devices/K32W061/drivers/fsl_ctimer.c", - "${k32w0_sdk_root}/devices/K32W061/drivers/fsl_flash.c", - "${k32w0_sdk_root}/devices/K32W061/drivers/fsl_flexcomm.c", - "${k32w0_sdk_root}/devices/K32W061/drivers/fsl_fmeas.c", - "${k32w0_sdk_root}/devices/K32W061/drivers/fsl_gpio.c", - "${k32w0_sdk_root}/devices/K32W061/drivers/fsl_i2c.c", - "${k32w0_sdk_root}/devices/K32W061/drivers/fsl_i2c_freertos.c", - "${k32w0_sdk_root}/devices/K32W061/drivers/fsl_inputmux.c", - "${k32w0_sdk_root}/devices/K32W061/drivers/fsl_ntag.c", - "${k32w0_sdk_root}/devices/K32W061/drivers/fsl_pint.c", - "${k32w0_sdk_root}/devices/K32W061/drivers/fsl_power.c", - "${k32w0_sdk_root}/devices/K32W061/drivers/fsl_reset.c", - "${k32w0_sdk_root}/devices/K32W061/drivers/fsl_rng.c", - "${k32w0_sdk_root}/devices/K32W061/drivers/fsl_rtc.c", - "${k32w0_sdk_root}/devices/K32W061/drivers/fsl_sha.c", - "${k32w0_sdk_root}/devices/K32W061/drivers/fsl_spifi.c", - "${k32w0_sdk_root}/devices/K32W061/drivers/fsl_usart.c", - "${k32w0_sdk_root}/devices/K32W061/drivers/fsl_wtimer.c", - "${k32w0_sdk_root}/devices/K32W061/mcuxpresso/startup_k32w061.c", - "${k32w0_sdk_root}/devices/K32W061/system_K32W061.c", - "${k32w0_sdk_root}/devices/K32W061/utilities/debug_console/fsl_debug_console.c", - "${k32w0_sdk_root}/devices/K32W061/utilities/str/fsl_str.c", - "${k32w0_sdk_root}/middleware/ntag_i2c_plus/HAL_I2C/i2c_jn_fsl.c", - "${k32w0_sdk_root}/middleware/ntag_i2c_plus/HAL_NTAG/ntag_driver.c", - "${k32w0_sdk_root}/middleware/ntag_i2c_plus/HAL_TMR/timer_driver_jn.c", + "${k32w0_sdk_root}/devices/${device}/drivers/fsl_adc.c", + "${k32w0_sdk_root}/devices/${device}/drivers/fsl_aes.c", + "${k32w0_sdk_root}/devices/${device}/drivers/fsl_clock.c", + "${k32w0_sdk_root}/devices/${device}/drivers/fsl_common.c", + "${k32w0_sdk_root}/devices/${device}/drivers/fsl_ctimer.c", + "${k32w0_sdk_root}/devices/${device}/drivers/fsl_flash.c", + "${k32w0_sdk_root}/devices/${device}/drivers/fsl_flexcomm.c", + "${k32w0_sdk_root}/devices/${device}/drivers/fsl_fmeas.c", + "${k32w0_sdk_root}/devices/${device}/drivers/fsl_gpio.c", + "${k32w0_sdk_root}/devices/${device}/drivers/fsl_i2c.c", + "${k32w0_sdk_root}/devices/${device}/drivers/fsl_i2c_freertos.c", + "${k32w0_sdk_root}/devices/${device}/drivers/fsl_inputmux.c", + "${k32w0_sdk_root}/devices/${device}/drivers/fsl_pint.c", + "${k32w0_sdk_root}/devices/${device}/drivers/fsl_power.c", + "${k32w0_sdk_root}/devices/${device}/drivers/fsl_reset.c", + "${k32w0_sdk_root}/devices/${device}/drivers/fsl_rng.c", + "${k32w0_sdk_root}/devices/${device}/drivers/fsl_rtc.c", + "${k32w0_sdk_root}/devices/${device}/drivers/fsl_sha.c", + "${k32w0_sdk_root}/devices/${device}/drivers/fsl_spifi.c", + "${k32w0_sdk_root}/devices/${device}/drivers/fsl_usart.c", + "${k32w0_sdk_root}/devices/${device}/drivers/fsl_wtimer.c", + "${k32w0_sdk_root}/devices/${device}/mcuxpresso/startup_${device_lowercase}.c", + "${k32w0_sdk_root}/devices/${device}/system_${device}.c", + "${k32w0_sdk_root}/devices/${device}/utilities/debug_console/fsl_debug_console.c", + "${k32w0_sdk_root}/devices/${device}/utilities/str/fsl_str.c", "${k32w0_sdk_root}/middleware/wireless/ble_controller/config/controller_config.c", "${k32w0_sdk_root}/middleware/wireless/bluetooth/application/common/ble_conn_manager.c", "${k32w0_sdk_root}/middleware/wireless/bluetooth/application/common/ble_host_tasks.c", @@ -351,9 +439,9 @@ template("k32w0_sdk") { "${k32w0_sdk_root}/middleware/wireless/framework/LED/Source/LED.c", "${k32w0_sdk_root}/middleware/wireless/framework/Lists/GenericList.c", "${k32w0_sdk_root}/middleware/wireless/framework/Logging/Source/dbg_logging.c", - "${k32w0_sdk_root}/middleware/wireless/framework/LowPower/Source/k32w061dk6/PWR.c", - "${k32w0_sdk_root}/middleware/wireless/framework/LowPower/Source/k32w061dk6/PWRLib.c", - "${k32w0_sdk_root}/middleware/wireless/framework/LowPower/Source/k32w061dk6/PWR_setjmp.S", + "${k32w0_sdk_root}/middleware/wireless/framework/LowPower/Source/${board}/PWR.c", + "${k32w0_sdk_root}/middleware/wireless/framework/LowPower/Source/${board}/PWRLib.c", + "${k32w0_sdk_root}/middleware/wireless/framework/LowPower/Source/${board}/PWR_setjmp.S", "${k32w0_sdk_root}/middleware/wireless/framework/MemManager/Source/MemManager.c", "${k32w0_sdk_root}/middleware/wireless/framework/Messaging/Source/Messaging.c", "${k32w0_sdk_root}/middleware/wireless/framework/OSAbstraction/Source/fsl_os_abstraction_free_rtos.c", @@ -379,37 +467,36 @@ template("k32w0_sdk") { ] if (chip_with_DK6) { - if (chip_with_low_power != 0) { + sources += [ + "${k32w0_sdk_root}/boards/${board}/wireless_examples/openthread/reed/bm/board.c", + "${k32w0_sdk_root}/boards/${board}/wireless_examples/openthread/reed/bm/board_utility.c", + "${k32w0_sdk_root}/boards/${board}/wireless_examples/openthread/reed/bm/hardware_init.c", + ] + + if (chip_with_se05x != 0) { sources += [ - "${k32w0_sdk_root}/boards/k32w061dk6/wireless_examples/openthread/lped/bm/board.c", - "${k32w0_sdk_root}/boards/k32w061dk6/wireless_examples/openthread/lped/bm/board_utility.c", - "${k32w0_sdk_root}/boards/k32w061dk6/wireless_examples/openthread/lped/bm/clock_config.c", - "${k32w0_sdk_root}/boards/k32w061dk6/wireless_examples/openthread/lped/bm/hardware_init.c", - "${k32w0_sdk_root}/boards/k32w061dk6/wireless_examples/openthread/lped/bm/pin_mux.c", + "${chip_root}/third_party/simw-top-mini/repo/demos/ksdk/common/boards/DK6/wireless_examples/chip/clock_config.c", + "${chip_root}/third_party/simw-top-mini/repo/demos/ksdk/common/boards/DK6/wireless_examples/chip/pin_mux.c", ] } else { sources += [ - "${k32w0_sdk_root}/boards/k32w061dk6/wireless_examples/openthread/reed/bm/board.c", - "${k32w0_sdk_root}/boards/k32w061dk6/wireless_examples/openthread/reed/bm/board_utility.c", - "${k32w0_sdk_root}/boards/k32w061dk6/wireless_examples/openthread/reed/bm/hardware_init.c", + "${k32w0_sdk_root}/boards/${board}/wireless_examples/openthread/reed/bm/clock_config.c", + "${k32w0_sdk_root}/boards/${board}/wireless_examples/openthread/reed/bm/pin_mux.c", ] - - if (chip_with_se05x != 0) { - sources += [ - "${chip_root}/third_party/simw-top-mini/repo/demos/ksdk/common/boards/DK6/wireless_examples/chip/clock_config.c", - "${chip_root}/third_party/simw-top-mini/repo/demos/ksdk/common/boards/DK6/wireless_examples/chip/pin_mux.c", - ] - } else { - sources += [ - "${k32w0_sdk_root}/boards/k32w061dk6/wireless_examples/openthread/reed/bm/clock_config.c", - "${k32w0_sdk_root}/boards/k32w061dk6/wireless_examples/openthread/reed/bm/pin_mux.c", - ] - } } } if (chip_with_low_power != 0) { - sources += [ "${k32w0_sdk_root}/boards/k32w061dk6/wireless_examples/hybrid/ble_ot/lped_ble_wuart/ble_802_15_4_common/app_dual_mode_low_power.c" ] + sources += [ "${k32w0_sdk_root}/boards/${board}/wireless_examples/hybrid/ble_ot/lped_ble_wuart/ble_802_15_4_common/app_dual_mode_low_power.c" ] + } + + if (chip_with_ntag != 0) { + sources += [ + "${k32w0_sdk_root}/devices/${device}/drivers/fsl_ntag.c", + "${k32w0_sdk_root}/middleware/ntag_i2c_plus/HAL_I2C/i2c_jn_fsl.c", + "${k32w0_sdk_root}/middleware/ntag_i2c_plus/HAL_NTAG/ntag_driver.c", + "${k32w0_sdk_root}/middleware/ntag_i2c_plus/HAL_TMR/timer_driver_jn.c", + ] } if (!defined(public_deps)) { diff --git a/third_party/nxp/k32w0_sdk/sdk_fixes/patch_k32w_sdk.sh b/third_party/nxp/k32w0_sdk/sdk_fixes/patch_k32w_sdk.sh index 417731e01f5216..1ae747ee5dcf23 100755 --- a/third_party/nxp/k32w0_sdk/sdk_fixes/patch_k32w_sdk.sh +++ b/third_party/nxp/k32w0_sdk/sdk_fixes/patch_k32w_sdk.sh @@ -1,10 +1,12 @@ #!/bin/bash -if [[ ! -d $NXP_K32W061_SDK_ROOT ]]; then - echo "NXP_K32W061_SDK_ROOT is not set" +if [[ ! -d $NXP_K32W0_SDK_ROOT ]]; then + echo "NXP_K32W0_SDK_ROOT is not set" exit 1 fi +board=$(ls "$NXP_K32W0_SDK_ROOT"/boards) + convert_to_dos() { [[ $(file -b - <$1) != *"CRLF"* ]] && sed -i 's/$/\r/' "$1" @@ -13,59 +15,5 @@ convert_to_dos() { SOURCE=${BASH_SOURCE[0]} SOURCE_DIR=$(cd "$(dirname "$SOURCE")" >/dev/null 2>&1 && pwd) -convert_to_dos "$NXP_K32W061_SDK_ROOT"/boards/k32w061dk6/wireless_examples/openthread/reed/bm/gpio_pins.h -patch -N --binary -d "$NXP_K32W061_SDK_ROOT"/boards/k32w061dk6/wireless_examples/openthread/reed/bm -p1 <"$SOURCE_DIR/gpio_pins_h.patch" - -convert_to_dos "$NXP_K32W061_SDK_ROOT"/boards/k32w061dk6/wireless_examples/hybrid/ble_ot/lped_ble_wuart/ble_802_15_4_common/app_dual_mode_low_power.h -patch -N --binary -d "$NXP_K32W061_SDK_ROOT"/boards/k32w061dk6/wireless_examples/hybrid/ble_ot/lped_ble_wuart/ble_802_15_4_common -p1 <"$SOURCE_DIR/app_dual_mode_low_power_h.patch" - -convert_to_dos "$NXP_K32W061_SDK_ROOT"/boards/k32w061dk6/wireless_examples/hybrid/ble_ot/lped_ble_wuart/ble_802_15_4_common/app_dual_mode_switch.h -patch -N --binary -d "$NXP_K32W061_SDK_ROOT"/boards/k32w061dk6/wireless_examples/hybrid/ble_ot/lped_ble_wuart/ble_802_15_4_common -p1 <"$SOURCE_DIR/app_dual_mode_switch_h.patch" - -convert_to_dos "$NXP_K32W061_SDK_ROOT"/middleware/wireless/framework/SecLib/SecLib.h -patch -N --binary -d "$NXP_K32W061_SDK_ROOT"/middleware/wireless/framework/SecLib -p1 <"$SOURCE_DIR/SecLib_h.patch" - -convert_to_dos "$NXP_K32W061_SDK_ROOT"/middleware/wireless/framework/OtaSupport/Source/OtaUtils.c -patch -N --binary -d "$NXP_K32W061_SDK_ROOT"/middleware/wireless/framework/OtaSupport/Source -p1 <"$SOURCE_DIR/OtaUtils_c.patch" - -convert_to_dos "$NXP_K32W061_SDK_ROOT"/middleware/wireless/framework/OtaSupport/Source/OtaSupport.c -patch -N --binary -d "$NXP_K32W061_SDK_ROOT"/middleware/wireless/framework/OtaSupport/Source -p1 <"$SOURCE_DIR/OtaSupport_c.patch" - -convert_to_dos "$NXP_K32W061_SDK_ROOT"/middleware/wireless/bluetooth/host/interface/ble_utils.h -patch -N --binary -d "$NXP_K32W061_SDK_ROOT"/middleware/wireless/bluetooth/host/interface -p1 <"$SOURCE_DIR/ble_utils_h.patch" - -convert_to_dos "$NXP_K32W061_SDK_ROOT"/middleware/wireless/framework/Flash/External/Source/Eeprom_MX25R8035F.c -patch -N --binary -d "$NXP_K32W061_SDK_ROOT"/middleware/wireless/framework/Flash/External/Source -p1 <"$SOURCE_DIR/Eeprom_MX25R8035F_c.patch" - -convert_to_dos "$NXP_K32W061_SDK_ROOT"/middleware/wireless/framework/MemManager/Interface/MemManager.h -patch -N --binary -d "$NXP_K32W061_SDK_ROOT"/middleware/wireless/framework/MemManager/Interface -p1 <"$SOURCE_DIR/MemManager_h.patch" - -#internal: THREADIP-3660 -patch -N --binary -d ./third_party/openthread/ot-nxp/src/k32w0/platform -p1 <"$SOURCE_DIR/settings_k32w_c.patch" - -SIGN_FILE_PATH="$NXP_K32W061_SDK_ROOT"/tools/imagetool/sign_images.sh -convert_to_dos "$SIGN_FILE_PATH" -patch -N --binary -d "$NXP_K32W061_SDK_ROOT"/tools/imagetool/ -p1 <"$SOURCE_DIR/sign_images_sh.patch" -sed -i 's/\r$//' "$SIGN_FILE_PATH" - -echo "Downloading PDM and BLE libraries from NXP server..." - -rm -rf patch_for_K32W061_SDK_2_6_4.zip patch_for_K32W061_SDK_2_6_4 -wget https://www.nxp.com/downloads/en/libraries/patch_for_K32W061_SDK_2_6_4.zip -exitCode=$? -if [ "$exitCode" -ne 0 ]; then - echo "Download error" - exit -fi - -unzip patch_for_K32W061_SDK_2_6_4.zip -cp patch_for_K32W061_SDK_2_6_4/controller_config.c "$NXP_K32W061_SDK_ROOT"/middleware/wireless/ble_controller/config/ -cp patch_for_K32W061_SDK_2_6_4/controller_interface.h "$NXP_K32W061_SDK_ROOT"/middleware/wireless/ble_controller/interface/ -cp patch_for_K32W061_SDK_2_6_4/lib_ble_controller.a "$NXP_K32W061_SDK_ROOT"/middleware/wireless/ble_controller/lib/ -cp patch_for_K32W061_SDK_2_6_4/libPDM_extFlash.a "$NXP_K32W061_SDK_ROOT"/middleware/wireless/framework/PDM/Library/ - -rm -rf patch_for_K32W061_SDK_2_6_4.zip -rm -rf patch_for_K32W061_SDK_2_6_4 - -echo "K32W SDK MR3 QP1 was patched!" +echo "SDK 2.6.6 doesn't need any patching!" exit 0 diff --git a/third_party/openthread/ot-nxp b/third_party/openthread/ot-nxp index 7a55fa48f51188..611561714fed15 160000 --- a/third_party/openthread/ot-nxp +++ b/third_party/openthread/ot-nxp @@ -1 +1 @@ -Subproject commit 7a55fa48f51188f24135b9e57834ae57acf2e0ff +Subproject commit 611561714fed15d8046c30933f3d3b84b6a9908c diff --git a/third_party/openthread/platforms/nxp/k32w/k32w0/BUILD.gn b/third_party/openthread/platforms/nxp/k32w/k32w0/BUILD.gn index b942608b82ac9b..c6946d3d1d06ab 100644 --- a/third_party/openthread/platforms/nxp/k32w/k32w0/BUILD.gn +++ b/third_party/openthread/platforms/nxp/k32w/k32w0/BUILD.gn @@ -23,7 +23,11 @@ import("${chip_root}/third_party/nxp/k32w0_sdk/k32w0_sdk.gni") openthread_nxp_root = "${chip_root}/third_party/openthread/ot-nxp" config("openthread_k32w0_config") { - include_dirs = [ "${openthread_nxp_root}/src/k32w0/k32w061" ] + include_dirs = [ + "${openthread_nxp_root}/src/k32w0/k32w061", + "${openthread_nxp_root}/src/k32w0/platform", + "${openthread_nxp_root}/src/common", + ] include_dirs += [ "${chip_root}/examples/platform/nxp/k32w/k32w0" ] if (is_clang) { @@ -52,14 +56,16 @@ source_set("openthread_mbedtls_config_k32w0") { source_set("libopenthread-k32w0") { sources = [ + "${openthread_nxp_root}/src/common/ram_storage.c", "${openthread_nxp_root}/src/k32w0/platform/alarm.c", "${openthread_nxp_root}/src/k32w0/platform/diag.c", "${openthread_nxp_root}/src/k32w0/platform/entropy.c", "${openthread_nxp_root}/src/k32w0/platform/flash.c", + "${openthread_nxp_root}/src/k32w0/platform/flash_pdm.c", "${openthread_nxp_root}/src/k32w0/platform/logging.c", "${openthread_nxp_root}/src/k32w0/platform/misc.c", + "${openthread_nxp_root}/src/k32w0/platform/pdm_ram_storage_glue.c", "${openthread_nxp_root}/src/k32w0/platform/radio.c", - "${openthread_nxp_root}/src/k32w0/platform/settings_k32w.c", "${openthread_nxp_root}/src/k32w0/platform/system.c", "${openthread_nxp_root}/src/k32w0/platform/uart.c", ]