diff --git a/.github/.wordlist.txt b/.github/.wordlist.txt index f7d6f3995dc039..6e8ed5fbe4a714 100644 --- a/.github/.wordlist.txt +++ b/.github/.wordlist.txt @@ -1384,6 +1384,7 @@ ug ui uint ULA +Ultrafast UNBLUR uncommissioned Unencrypted diff --git a/.github/workflows/examples-k32w.yaml b/.github/workflows/examples-k32w.yaml index 43d72b2f26cef7..7a90b9ebe36942 100644 --- a/.github/workflows/examples-k32w.yaml +++ b/.github/workflows/examples-k32w.yaml @@ -28,7 +28,7 @@ env: jobs: k32w: name: K32W - timeout-minutes: 60 + timeout-minutes: 90 env: BUILD_TYPE: gn_k32w @@ -37,7 +37,7 @@ jobs: if: github.actor != 'restyled-io[bot]' container: - image: connectedhomeip/chip-build-k32w:0.6.35 + image: connectedhomeip/chip-build-k32w:0.6.36 volumes: - "/tmp/bloat_reports:/tmp/bloat_reports" steps: @@ -75,10 +75,12 @@ jobs: scripts/run_in_build_env.sh "\ ./scripts/build/build_examples.py \ --target k32w-light-no-ble-se05x \ - --target k32w-light-no-ota \ - --target k32w-lock-low-power-nologs \ - --target k32w-contact-low-power-nologs \ - --target k32w-shell \ + --target k32w-light-crypto-platform-tokenizer \ + --target k32w-lock-crypto-platform-tokenizer \ + --target k32w-lock-crypto-platform-low-power-nologs \ + --target k32w-contact-crypto-platform-tokenizer \ + --target k32w-contact-crypto-platform-low-power-nologs \ + --target k32w-shell-crypto-platform \ build \ --copy-artifacts-to out/artifacts \ " @@ -87,21 +89,21 @@ jobs: run: | .environment/pigweed-venv/bin/python3 scripts/tools/memory/gh_sizes.py \ k32w k32w0+release light \ - out/artifacts/k32w-light-no-ota/chip-k32w0x-light-example \ + out/artifacts/k32w-light-crypto-platform-tokenizer/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 k32w0+release lock \ - out/artifacts/k32w-lock-low-power-nologs/chip-k32w0x-lock-example \ + out/artifacts/k32w-lock-crypto-platform-tokenizer/chip-k32w0x-lock-example \ /tmp/bloat_reports/ - name: Get contact size stats timeout-minutes: 5 run: | .environment/pigweed-venv/bin/python3 scripts/tools/memory/gh_sizes.py \ k32w k32w0+release contact \ - out/artifacts/k32w-contact-low-power-nologs/chip-k32w0x-contact-example \ + out/artifacts/k32w-contact-crypto-platform-tokenizer/chip-k32w0x-contact-example \ /tmp/bloat_reports/ - name: Uploading Size Reports uses: actions/upload-artifact@v3 diff --git a/.gitmodules b/.gitmodules index a1b9865c8b3a17..b10429140c7edc 100644 --- a/.gitmodules +++ b/.gitmodules @@ -234,11 +234,6 @@ path = third_party/nxp/mw320_sdk/repo url = https://github.com/nxptest/mw320_sdk platforms = mw320 -[submodule "third_party/nxp/libs/mbedtls/repo"] - path = third_party/nxp/libs/mbedtls/repo - url = https://github.com/NXPmicro/mbedtls.git - branch = tinycrypt-mbedtls-2.28 - platforms = k32w0 [submodule "third_party/silabs/matter_support"] path = third_party/silabs/matter_support url = https://github.com/SiliconLabs/sdk_support.git diff --git a/examples/contact-sensor-app/nxp/k32w/k32w0/BUILD.gn b/examples/contact-sensor-app/nxp/k32w/k32w0/BUILD.gn index 8a0ace589d009a..bfc232e963525a 100644 --- a/examples/contact-sensor-app/nxp/k32w/k32w0/BUILD.gn +++ b/examples/contact-sensor-app/nxp/k32w/k32w0/BUILD.gn @@ -23,6 +23,10 @@ import("${chip_root}/src/crypto/crypto.gni") import("${chip_root}/src/lib/core/core.gni") import("${chip_root}/src/platform/device.gni") +declare_args() { + chip_software_version = 0 +} + if (chip_pw_tokenizer_logging) { import("//build_overrides/pigweed.gni") import("$dir_pw_tokenizer/database.gni") @@ -50,6 +54,7 @@ k32w0_sdk("sdk") { "${k32w0_platform_dir}/app/project_include", "${k32w0_platform_dir}/app/support", "${k32w0_platform_dir}/util/include", + "${k32w0_platform_dir}/common", ] if (chip_with_se05x == 1) { @@ -62,6 +67,12 @@ k32w0_sdk("sdk") { } else { defines += [ "BUILD_RELEASE=1" ] } + + if (chip_software_version != 0) { + defines += [ + "CHIP_DEVICE_CONFIG_DEVICE_SOFTWARE_VERSION=${chip_software_version}", + ] + } } k32w0_executable("contact_sensor_app") { @@ -79,6 +90,18 @@ k32w0_executable("contact_sensor_app") { "main/main.cpp", ] + if (chip_with_factory_data == 1 && use_custom_factory_provider == 1) { + sources += [ + "${k32w0_platform_dir}/common/CustomFactoryDataProvider.cpp", + "${k32w0_platform_dir}/common/CustomFactoryDataProvider.h", + ] + + defines = [ + "CHIP_DEVICE_CONFIG_USE_CUSTOM_PROVIDER=1", + "CHIP_DEVICE_CONFIG_CUSTOM_PROVIDER_NUMBER_IDS=3", + ] + } + deps = [ ":sdk", "${chip_root}/examples/common/QRCode", @@ -109,16 +132,27 @@ k32w0_executable("contact_sensor_app") { inputs = [ ldscript ] - ldflags = [ "-T" + rebase_path(ldscript, root_build_dir) ] + ldflags = [ + "-T" + rebase_path(ldscript, root_build_dir), + "-Wl,-print-memory-usage", + ] if (chip_enable_ota_requestor) { - ldflags += [ - "-Wl,--defsym", - "-Wl,__app_load_address__=0x4000", - "-Wl,--defsym", - "-Wl,__app_stated_size__=0x99200", - "-Wl,-print-memory-usage", - ] + if (chip_reduce_ssbl_size) { + ldflags += [ + "-Wl,--defsym", + "-Wl,__app_load_address__=0x2000", + "-Wl,--defsym", + "-Wl,__app_stated_size__=0x9B200", + ] + } else { + ldflags += [ + "-Wl,--defsym", + "-Wl,__app_load_address__=0x4000", + "-Wl,--defsym", + "-Wl,__app_stated_size__=0x99200", + ] + } } } diff --git a/examples/contact-sensor-app/nxp/k32w/k32w0/README.md b/examples/contact-sensor-app/nxp/k32w/k32w0/README.md index 14e23161deac9f..3b2e2612f0126b 100644 --- a/examples/contact-sensor-app/nxp/k32w/k32w0/README.md +++ b/examples/contact-sensor-app/nxp/k32w/k32w0/README.md @@ -27,8 +27,10 @@ network. - [Detokenizer script](#detokenizer-script) - [Notes](#notes) - [Known issues](#known-issues-1) -- [Tinycrypt ECC operations](#tinycrypt-ecc-operations) +- [NXP Ultrafast P256 ECC Library](#nxp-ultrafast-p256-ecc-library) - [Building steps](#building-steps) +- [Tinycrypt ECC library](#tinycrypt-ecc-library) + - [Building steps](#building-steps-1) - [OTA](#ota) - [Writing the SSBL](#writing-the-ssbl) - [Writing the PSECT](#writing-the-psect) @@ -39,6 +41,8 @@ network. - [Known issues](#known-issues-3) +- [Removing SSBL Upgrade region](#removing-ssbl-upgrade-region) + ## Introduction @@ -133,10 +137,8 @@ states are depicted: * _Solid On_ — The device is fully provisioned and has full network and service connectivity. -**LED D3** shows the state of the simulated lock bolt. When the LED is lit the -bolt is extended (i.e. door locked); when not lit, the bolt is retracted (door -unlocked). The LED will flash whenever the simulated bolt is in motion from one -position to another. +**LED D3** shows the state of the simulated contact sensor. when the LED is lit, +the sensor is contacted, when not lit, the sensor is non-contacted. **Button SW2** can be used to reset the device to a default state. A short Press Button SW2 initiates a factory reset. After an initial period of 3 seconds, LED2 @@ -145,13 +147,10 @@ cause the device to reset its persistent configuration and initiate a reboot. The reset action can be cancelled by press SW2 button at any point before the 6 second limit. -**Button SW3** can be used to change the state of the simulated bolt. This can -be used to mimic a user manually operating the lock. The button behaves as a -toggle, swapping the state every time it is pressed. +**Button SW3** can be used to change the state of the simulated contact sensor. +The button behaves as a toggle, swapping the state every time it is pressed. -**Button SW4** can be used for joining a predefined Thread network advertised by -a Border Router. Default parameters for a Thread network are hard-coded and are -being used if this button is pressed. +**Button SW4** can be used for initiating the OTA software update process. The remaining two LEDs (D1/D4) and button (SW1) are unused. @@ -169,24 +168,27 @@ DS3, which can be found on the DK6 board. Also, by long pressing the **USERINTERFACE** button, the factory reset action will be initiated. +When low power is enabled, the **ISP button** on DK6 board is used to change +contact status. + ## Building In order to build the Project CHIP example, we recommend using a Linux distribution (the demo-application was compiled on Ubuntu 20.04). - Download - [K32W0 SDK 2.6.7](https://cache.nxp.com/lgfiles/bsps/SDK_2_6_7_K32W061DK6.zip). + [K32W061DK6 SDK 2.6.9](https://cache.nxp.com/lgfiles/bsps/SDK_2_6_9_K32W061DK6.zip). - Start building the application either with Secure Element or without - without Secure Element ``` - user@ubuntu:~/Desktop/git/connectedhomeip$ export NXP_K32W0_SDK_ROOT=/home/user/Desktop/SDK_2_6_7_K32W061DK6/ + user@ubuntu:~/Desktop/git/connectedhomeip$ export NXP_K32W0_SDK_ROOT=/home/user/Desktop/SDK_2_6_9_K32W061DK6/ user@ubuntu:~/Desktop/git/connectedhomeip$ ./third_party/nxp/k32w0_sdk/sdk_fixes/patch_k32w_sdk.sh user@ubuntu:~/Desktop/git/connectedhomeip$ source ./scripts/activate.sh user@ubuntu:~/Desktop/git/connectedhomeip$ cd examples/contact-sensor-app/nxp/k32w/k32w0 - user@ubuntu:~/Desktop/git/connectedhomeip/examples/contact-sensor-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/contact-sensor-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=\"platform\" chip_with_se05x=0 chip_pw_tokenizer_logging=true" user@ubuntu:~/Desktop/git/connectedhomeip/examples/contact-sensor-app/nxp/k32w/k32w0$ ninja -C out/debug user@ubuntu:~/Desktop/git/connectedhomeip/examples/contact-sensor-app/nxp/k32w/k32w0$ $NXP_K32W0_SDK_ROOT/tools/imagetool/sign_images.sh out/debug/ ``` @@ -198,9 +200,11 @@ distribution (the demo-application was compiled on Ubuntu 20.04). Note that option chip_enable_ota_requestor=false are required for building with Secure Element. These can be changed if building without Secure Element - - 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. +- K32W041AM flavor + + Exactly the same steps as above but set argument build_for_k32w041am=1 in + the gn command and use + [K32W041AMDK6 SDK 2.6.9](https://cache.nxp.com/lgfiles/bsps/SDK_2_6_9_K32W041AMDK6.zip). 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 @@ -209,6 +213,10 @@ to zero. The argument chip_with_OM15082 is set to zero by default. In case that Openthread CLI is needed, chip_with_ot_cli build argument must be set to 1. +In case the board doesn't have 32KHz crystal fitted, one can use the 32KHz free +running oscillator as a clock source. In this case one must set the use_fro_32k +argument to 1. + In case signing errors are encountered when running the "sign_images.sh" script install the recommanded packages (python version > 3, pip3, pycrypto, pycryptodome): @@ -235,6 +243,30 @@ The resulting output file can be found in out/debug/chip-k32w0x-contact-example. See [Guide for writing manufacturing data on NXP devices](../../../../platform/nxp/doc/manufacturing_flow.md). +There are factory data generated binaries available in +examples/platform/nxp/k32w/k32w0/scripts/demo_generated_factory_data folder. +These are based on the DAC, PAI and PAA certificates found in +scripts/tools/nxp/demo_generated_certs folder. The demo_factory_data_dut1.bin +uses the DAC certificate and private key found in +examples/platform/nxp/k32w/k32w0/scripts/demo_generated_factory_data/dac/dut1 +folder. The demo_factory_data_dut2.bin uses the DAC certificate and private key +found in +examples/platform/nxp/k32w/k32w0/scripts/demo_generated_factory_data/dac/dut2 +folder. These two factory data binaries can be used for testing topologies with +2 DUTS. They contain the corresponding DACs/PAIs generated using +generate_nxp_chip_factory_bin.py script. The discriminator is 14014 and the +passcode is 1000. These demo certificates are working with the CDs installed in +CHIPProjectConfig.h. + +Regarding factory data provider, there are two options: + +- use the default factory data provider: `K32W0FactoryDataProvider` by setting + `chip_with_factory_data=1` in the gn build command. +- use a custom factory data provider: please see + [Guide for implementing a custom factory data provider](../../../../platform/nxp/k32w/k32w0/common/README.md). + This can be enabled when `chip_with_factory_data=1` by setting + `use_custom_factory_provider=1` in the gn build command. + ## Flashing and debugging Program the firmware using the official @@ -310,21 +342,28 @@ 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 +## NXP Ultrafast P256 ECC Library ### Building steps -Note: This solution is temporary. +By default, the application builds with NXP Ultrafast P256 ECC Library. To build +with this library, use the following arguments: + +- Build without Secure element (_chip_with_se05x=0_) and with crypto platform + (_chip_crypto=\"platform\"_). -In order to use the tinycrypt ecc operations, use the following build arguments: +To stop using Ultrafast P256 ECC Library, simply build with +_chip_crypto=\"mbedtls\"_ or with Tinycrypt. -- 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\"`_). +## Tinycrypt ECC library -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. +### Building steps + +In order to use the Tinycrypt ECC library, use the following build arguments: + +- Build without Secure element (_chip_with_se05x=0_), with crypto platform + (_chip_crypto=\"platform\"_) and with tinycrypt selected + (_chip_crypto_flavor=\"tinycrypt\"_). ## OTA @@ -400,7 +439,7 @@ CD04 -> 0x4C9 pages of 512-bytes (= 612,5kB) DK6Programmer can be used for flashing the application: ``` -DK6Programmer.exe -V2 -s -P 1000000 -Y -p FLASH@0x4000="chip-k32w0x-light-example.bin" +DK6Programmer.exe -V2 -s -P 1000000 -Y -p FLASH@0x4000="chip-k32w0x-contact-example.bin" ``` If debugging is needed, MCUXpresso can be used then for flashing the @@ -458,6 +497,13 @@ user@computer1:~/connectedhomeip$ : rm -rf /tmp/chip_* user@computer1:~/connectedhomeip$ : ./out/ota-provider-app/chip-ota-provider-app -f chip-k32w0x-light-example.ota ``` +A note regarding OTA image header version (`-vn` option). An application binary +has its own software version (given by +`CHIP_DEVICE_CONFIG_DEVICE_SOFTWARE_VERSION`, which can be overwritten). For +having a correct OTA process, the OTA header version should be the same as the +binary embedded software version. A user can set a custom software version in +the gn build args by setting `chip_software_version` to the wanted version. + Build Linux chip-tool: ``` @@ -524,9 +570,10 @@ The example also offers the possibility to run in low power mode. This means that the board will go in a deep power down mode most of the time and the power consumption will be very low. -In order build with low power support, the _chip_with_low_power=1_ must be +In order to build with low power support, the _chip_with_low_power=1_ must be provided to the build system. In this case, please note that the GN build -arguments chip*with_OM15082 and \_chip_with_ot_cli* must be set to 0. +arguments _chip_with_OM15082_ and _chip_with_ot_cli_ must be set to 0 and +_chip_logging_ must be set to false to disable logging. In order to maintain a low power consumption, the LEDs showing the state of the elock and the internal state are disabled. Console logs can be used instead. @@ -552,3 +599,34 @@ professional tools must be used if exact power consumption needs to be known. - Power Measurement Tool may not work correctly in MCUXpresso versions greater that 11.0.1. + +## Removing SSBL Upgrade Region + +The example also offers the possibility to remove SSBL upgrade region, for +reserving more space for application level. + +A new flag `chip_reduce_ssbl_size` is introduced. In order to remove the SSBL +upgrade region, `chip_reduce_ssbl_size=true` must be provided to the build +system + +The programming method will change: + +- writing image directory 1 should change to + + ``` + DK6Programmer.exe -V5 -s -P 1000000 -w image_dir_1=00200000D9040101 + ``` + + Here is the interpretation of the fields: + + ``` + 00200000 -> start address 0x00002000 + D904 -> 0x4D9 pages of 512-bytes (= 620.5kB) + 01 -> bootable flag + 01 -> image type for the application + ``` + +- Matter application offset address should change to + ``` + DK6Programmer.exe -V2 -s -P 1000000 -Y -p FLASH@0x2000="chip-k32w0x-contact-example.bin" + ``` diff --git a/examples/contact-sensor-app/nxp/k32w/k32w0/include/CHIPProjectConfig.h b/examples/contact-sensor-app/nxp/k32w/k32w0/include/CHIPProjectConfig.h index 5b8a75a6347454..62262725f397f2 100644 --- a/examples/contact-sensor-app/nxp/k32w/k32w0/include/CHIPProjectConfig.h +++ b/examples/contact-sensor-app/nxp/k32w/k32w0/include/CHIPProjectConfig.h @@ -43,13 +43,22 @@ #if CONFIG_CHIP_K32W0_REAL_FACTORY_DATA +// Enable usage of custom factory data provider +#ifndef CHIP_DEVICE_CONFIG_USE_CUSTOM_PROVIDER +#define CHIP_DEVICE_CONFIG_USE_CUSTOM_PROVIDER 0 +#endif + +#if CHIP_DEVICE_CONFIG_USE_CUSTOM_PROVIDER +#ifndef CHIP_DEVICE_CONFIG_CUSTOM_PROVIDER_NUMBER_IDS +// Set to 3: default number of custom Ids from CustomFactoryDataProvider example +#define CHIP_DEVICE_CONFIG_CUSTOM_PROVIDER_NUMBER_IDS 3 +#endif +#endif + // VID/PID for product => will be used by Basic Information Cluster #define CHIP_DEVICE_CONFIG_DEVICE_VENDOR_ID 0x1037 #define CHIP_DEVICE_CONFIG_DEVICE_PRODUCT_ID 0xA220 -// set it to 0 for the moment -#define CHIP_DEVICE_CONFIG_ENABLE_DEVICE_INSTANCE_INFO_PROVIDER 0 - #ifndef CHIP_DEVICE_CONFIG_CERTIFICATION_DECLARATION //-> format_version = 1 //-> vendor_id = 0x1037 diff --git a/examples/contact-sensor-app/nxp/k32w/k32w0/main/AppTask.cpp b/examples/contact-sensor-app/nxp/k32w/k32w0/main/AppTask.cpp index 504513e643e107..91c8a240169627 100644 --- a/examples/contact-sensor-app/nxp/k32w/k32w0/main/AppTask.cpp +++ b/examples/contact-sensor-app/nxp/k32w/k32w0/main/AppTask.cpp @@ -18,6 +18,7 @@ */ #include "AppTask.h" #include "AppEvent.h" +#include #include #include @@ -69,9 +70,8 @@ static LEDWidget sStatusLED; static LEDWidget sContactSensorLED; #endif -static bool sIsThreadProvisioned = false; -static bool sHaveBLEConnections = false; -static bool sIsDnssdPlatformInitialized = false; +static bool sIsThreadProvisioned = false; +static bool sHaveBLEConnections = false; static uint32_t eventMask = 0; @@ -132,12 +132,10 @@ CHIP_ERROR AppTask::Init() // Initialize device attestation config #if CONFIG_CHIP_K32W0_REAL_FACTORY_DATA // Initialize factory data provider - ReturnErrorOnFailure(K32W0FactoryDataProvider::GetDefaultInstance().Init()); -#if CHIP_DEVICE_CONFIG_ENABLE_DEVICE_INSTANCE_INFO_PROVIDER - SetDeviceInstanceInfoProvider(&K32W0FactoryDataProvider::GetDefaultInstance()); -#endif - SetDeviceAttestationCredentialsProvider(&K32W0FactoryDataProvider::GetDefaultInstance()); - SetCommissionableDataProvider(&K32W0FactoryDataProvider::GetDefaultInstance()); + ReturnErrorOnFailure(AppTask::FactoryDataProvider::GetDefaultInstance().Init()); + SetDeviceInstanceInfoProvider(&AppTask::FactoryDataProvider::GetDefaultInstance()); + SetDeviceAttestationCredentialsProvider(&AppTask::FactoryDataProvider::GetDefaultInstance()); + SetCommissionableDataProvider(&AppTask::FactoryDataProvider::GetDefaultInstance()); #else #ifdef ENABLE_HSM_DEVICE_ATTESTATION SetDeviceAttestationCredentialsProvider(Examples::GetExampleSe05xDACProvider()); @@ -146,7 +144,7 @@ CHIP_ERROR AppTask::Init() #endif // QR code will be used with CHIP Tool - PrintOnboardingCodes(chip::RendezvousInformationFlags(chip::RendezvousInformationFlag::kBLE)); + AppTask::PrintOnboardingInfo(); #endif /* HW init leds */ @@ -188,23 +186,11 @@ CHIP_ERROR AppTask::Init() K32W_LOG("Get version error"); assert(err == CHIP_NO_ERROR); } + uint32_t currentVersion; + err = ConfigurationMgr().GetSoftwareVersion(currentVersion); - K32W_LOG("Current Software Version: %s", currentSoftwareVer); + K32W_LOG("Current Software Version: %s, %" PRIu32, currentSoftwareVer, currentVersion); -#if CHIP_DEVICE_CONFIG_ENABLE_OTA_REQUESTOR - if (gImageProcessor.IsFirstImageRun()) - { - // If DNS-SD initialization was captured by MatterEventHandler, then - // OTA initialization will be started as soon as possible. Otherwise, - // a periodic timer is started until the DNS-SD initialization event - // is received. Configurable delay: CHIP_DEVICE_CONFIG_INIT_OTA_DELAY - AppTask::OnScheduleInitOTA(nullptr, nullptr); - } - else - { - PlatformMgr().ScheduleWork(AppTask::InitOTA, 0); - } -#endif return err; } @@ -238,6 +224,18 @@ void AppTask::InitServer(intptr_t arg) VerifyOrDie((chip::Server::GetInstance().Init(initParams)) == CHIP_NO_ERROR); } +void AppTask::PrintOnboardingInfo() +{ + chip::PayloadContents payload; + CHIP_ERROR err = GetPayloadContents(payload, chip::RendezvousInformationFlags(chip::RendezvousInformationFlag::kBLE)); + if (err != CHIP_NO_ERROR) + { + ChipLogError(AppServer, "GetPayloadContents() failed: %" CHIP_ERROR_FORMAT, err.Format()); + } + payload.commissioningFlow = chip::CommissioningFlow::kUserActionRequired; + PrintOnboardingCodes(payload); +} + #if CHIP_DEVICE_CONFIG_ENABLE_OTA_REQUESTOR void AppTask::InitOTA(intptr_t arg) { @@ -565,32 +563,6 @@ void AppTask::StartOTAQuery(intptr_t arg) { GetRequestorInstance()->TriggerImmediateQuery(); } - -void AppTask::PostOTAResume() -{ - AppEvent event; - event.Type = AppEvent::kOTAResume; - event.Handler = OTAResumeEventHandler; - sAppTask.PostEvent(&event); -} - -void AppTask::OnScheduleInitOTA(chip::System::Layer * systemLayer, void * appState) -{ - if (sIsDnssdPlatformInitialized) - { - PlatformMgr().ScheduleWork(AppTask::InitOTA, 0); - } - else - { - CHIP_ERROR error = chip::DeviceLayer::SystemLayer().StartTimer( - chip::System::Clock::Milliseconds32(CHIP_DEVICE_CONFIG_INIT_OTA_DELAY), AppTask::OnScheduleInitOTA, nullptr); - - if (error != CHIP_NO_ERROR) - { - K32W_LOG("Failed to schedule OTA initialization timer."); - } - } -} #endif void AppTask::BleHandler(void * aGenericEvent) @@ -651,15 +623,10 @@ void AppTask::MatterEventHandler(const ChipDeviceEvent * event, intptr_t) } #if CHIP_DEVICE_CONFIG_ENABLE_OTA_REQUESTOR - if (event->Type == DeviceEventType::kOtaStateChanged && event->OtaStateChanged.newState == kOtaSpaceAvailable) - { - sAppTask.PostOTAResume(); - } - if (event->Type == DeviceEventType::kDnssdPlatformInitialized) { K32W_LOG("Dnssd platform initialized."); - sIsDnssdPlatformInitialized = true; + PlatformMgr().ScheduleWork(AppTask::InitOTA, 0); } #endif @@ -785,20 +752,6 @@ void AppTask::PostContactActionRequest(ContactSensorManager::Action aAction) PostEvent(&event); } -void AppTask::OTAResumeEventHandler(void * aGenericEvent) -{ - AppEvent * aEvent = (AppEvent *) aGenericEvent; - if (aEvent->Type == AppEvent::kOTAResume) - { -#if CHIP_DEVICE_CONFIG_ENABLE_OTA_REQUESTOR - if (gDownloader.GetState() == OTADownloader::State::kInProgress) - { - gImageProcessor.TriggerNewRequestForData(); - } -#endif - } -} - void AppTask::PostEvent(const AppEvent * aEvent) { portBASE_TYPE taskToWake = pdFALSE; diff --git a/examples/contact-sensor-app/nxp/k32w/k32w0/main/include/AppTask.h b/examples/contact-sensor-app/nxp/k32w/k32w0/main/include/AppTask.h index 029e0205cdf937..d8845b61ae45db 100644 --- a/examples/contact-sensor-app/nxp/k32w/k32w0/main/include/AppTask.h +++ b/examples/contact-sensor-app/nxp/k32w/k32w0/main/include/AppTask.h @@ -23,7 +23,15 @@ #include "AppEvent.h" #include "ContactSensorManager.h" + +#include "CHIPProjectConfig.h" + +#if CONFIG_CHIP_K32W0_REAL_FACTORY_DATA #include "K32W0FactoryDataProvider.h" +#if CHIP_DEVICE_CONFIG_USE_CUSTOM_PROVIDER +#include "CustomFactoryDataProvider.h" +#endif +#endif #include #include @@ -41,6 +49,15 @@ class AppTask { +public: +#if CONFIG_CHIP_K32W0_REAL_FACTORY_DATA +#if CHIP_DEVICE_CONFIG_USE_CUSTOM_PROVIDER + using FactoryDataProvider = chip::DeviceLayer::CustomFactoryDataProvider; +#else + using FactoryDataProvider = chip::DeviceLayer::K32W0FactoryDataProvider; +#endif +#endif + public: CHIP_ERROR StartAppTask(); static void AppTaskMain(void * pvParameter); @@ -75,7 +92,6 @@ class AppTask static void BleHandler(void * aGenericEvent); static void BleStartAdvertising(intptr_t arg); static void ContactActionEventHandler(void * aGenericEvent); - static void OTAResumeEventHandler(void * aGenericEvent); static void ResetActionEventHandler(void * aGenericEvent); static void InstallEventHandler(void * aGenericEvent); @@ -88,18 +104,16 @@ class AppTask #if CHIP_DEVICE_CONFIG_ENABLE_OTA_REQUESTOR static void InitOTA(intptr_t arg); static void StartOTAQuery(intptr_t arg); - static void PostOTAResume(); - static void OnScheduleInitOTA(chip::System::Layer * systemLayer, void * appState); #endif static void UpdateClusterStateInternal(intptr_t arg); static void UpdateDeviceStateInternal(intptr_t arg); static void InitServer(intptr_t arg); + static void PrintOnboardingInfo(); enum class Function : uint8_t { - kNoneSelected = 0, - kSoftwareUpdate = 0, + kNoneSelected = 0, kFactoryReset, kContact, kIdentify, @@ -111,8 +125,6 @@ class AppTask bool mSyncClusterToButtonAction = false; static AppTask sAppTask; - - chip::DeviceLayer::K32W0FactoryDataProvider mK32W0FactoryDataProvider; }; inline AppTask & GetAppTask(void) diff --git a/examples/contact-sensor-app/nxp/k32w/k32w0/main/include/app_config.h b/examples/contact-sensor-app/nxp/k32w/k32w0/main/include/app_config.h index 2e32f6475c4f46..5343e1e56a3af9 100644 --- a/examples/contact-sensor-app/nxp/k32w/k32w0/main/include/app_config.h +++ b/examples/contact-sensor-app/nxp/k32w/k32w0/main/include/app_config.h @@ -34,8 +34,8 @@ #define APP_BUTTON_PUSH 1 -#define CONTACT_SENSOR_STATE_LED LED1 -#define SYSTEM_STATE_LED LED2 +#define CONTACT_SENSOR_STATE_LED LED2 +#define SYSTEM_STATE_LED LED1 // ---- Contact Example SWU Config ---- #define SWU_INTERVAl_WINDOW_MIN_MS (23 * 60 * 60 * 1000) // 23 hours diff --git a/examples/contact-sensor-app/nxp/k32w/k32w0/main/main.cpp b/examples/contact-sensor-app/nxp/k32w/k32w0/main/main.cpp index fcba2385479876..b00f65d0d5578d 100644 --- a/examples/contact-sensor-app/nxp/k32w/k32w0/main/main.cpp +++ b/examples/contact-sensor-app/nxp/k32w/k32w0/main/main.cpp @@ -31,6 +31,16 @@ #include "FreeRtosHooks.h" #include "app_config.h" +#if PDM_SAVE_IDLE +#include +#endif + +#if defined(cPWR_UsePowerDownMode) && (cPWR_UsePowerDownMode) +#include "fsl_gpio.h" +#include "fsl_iocon.h" +#include "gpio_pins.h" +#endif + using namespace ::chip; using namespace ::chip::Inet; using namespace ::chip::DeviceLayer; @@ -119,6 +129,12 @@ extern "C" void main_task(void const * argument) APP_SetHighTxPowerMode(); #endif +#if PDM_SAVE_IDLE + /* OT Settings needs to be initialized + * early as XCVR is making use of it */ + otPlatSettingsInit(NULL, NULL, 0); +#endif + err = PlatformMgr().InitChipStack(); if (err != CHIP_NO_ERROR) { @@ -199,3 +215,29 @@ extern "C" void otSysEventSignalPending(void) portYIELD_FROM_ISR(yieldRequired); } } + +#if defined(cPWR_UsePowerDownMode) && (cPWR_UsePowerDownMode) +extern "C" void vOptimizeConsumption(void) +{ + /* BUTTON2 change contact, BUTTON4 start adv/factoryreset */ + uint32_t u32SkipIO = (1 << IOCON_USER_BUTTON1_PIN) | (1 << IOCON_USER_BUTTON2_PIN); + + /* Pins are set to GPIO mode (IOCON FUNC0), pulldown and analog mode */ + uint32_t u32PIOvalue = (IOCON_FUNC0 | IOCON_MODE_PULLDOWN | IOCON_ANALOG_EN); + + const gpio_pin_config_t pin_config = { .pinDirection = kGPIO_DigitalInput, .outputLogic = 1U }; + + if (u32PIOvalue != 0) + { + for (int i = 0; i < 22; i++) + { + if (((u32SkipIO >> i) & 0x1) != 1) + { + /* configure GPIOs to Input mode */ + GPIO_PinInit(GPIO, 0, i, &pin_config); + IOCON_PinMuxSet(IOCON, 0, i, u32PIOvalue); + } + } + } +} +#endif diff --git a/examples/lighting-app/nxp/k32w/k32w0/BUILD.gn b/examples/lighting-app/nxp/k32w/k32w0/BUILD.gn index ff271fc042ffa4..5daf13dfc7110c 100644 --- a/examples/lighting-app/nxp/k32w/k32w0/BUILD.gn +++ b/examples/lighting-app/nxp/k32w/k32w0/BUILD.gn @@ -23,6 +23,10 @@ import("${chip_root}/src/crypto/crypto.gni") import("${chip_root}/src/lib/core/core.gni") import("${chip_root}/src/platform/device.gni") +declare_args() { + chip_software_version = 0 +} + if (chip_pw_tokenizer_logging) { import("//build_overrides/pigweed.gni") import("$dir_pw_tokenizer/database.gni") @@ -50,6 +54,7 @@ k32w0_sdk("sdk") { "${k32w0_platform_dir}/app/project_include", "${k32w0_platform_dir}/app/support", "${k32w0_platform_dir}/util/include", + "${k32w0_platform_dir}/common", ] if (chip_with_se05x == 1) { @@ -62,6 +67,12 @@ k32w0_sdk("sdk") { } else { defines += [ "BUILD_RELEASE=1" ] } + + if (chip_software_version != 0) { + defines += [ + "CHIP_DEVICE_CONFIG_DEVICE_SOFTWARE_VERSION=${chip_software_version}", + ] + } } k32w0_executable("light_app") { @@ -81,6 +92,18 @@ k32w0_executable("light_app") { public = [ "${chip_root}/src/platform/nxp/k32w/k32w0/DefaultTestEventTriggerDelegate.h" ] + if (chip_with_factory_data == 1 && use_custom_factory_provider == 1) { + sources += [ + "${k32w0_platform_dir}/common/CustomFactoryDataProvider.cpp", + "${k32w0_platform_dir}/common/CustomFactoryDataProvider.h", + ] + + defines = [ + "CHIP_DEVICE_CONFIG_USE_CUSTOM_PROVIDER=1", + "CHIP_DEVICE_CONFIG_CUSTOM_PROVIDER_NUMBER_IDS=3", + ] + } + deps = [ ":sdk", "${chip_root}/examples/common/QRCode", @@ -109,7 +132,10 @@ k32w0_executable("light_app") { inputs = [ ldscript ] - ldflags = [ "-T" + rebase_path(ldscript, root_build_dir) ] + ldflags = [ + "-T" + rebase_path(ldscript, root_build_dir), + "-Wl,-print-memory-usage", + ] if (chip_enable_ota_requestor) { ldflags += [ diff --git a/examples/lighting-app/nxp/k32w/k32w0/README.md b/examples/lighting-app/nxp/k32w/k32w0/README.md index 9550f64354bbd6..61bc38f96fa920 100644 --- a/examples/lighting-app/nxp/k32w/k32w0/README.md +++ b/examples/lighting-app/nxp/k32w/k32w0/README.md @@ -29,8 +29,10 @@ network. - [Detokenizer script](#detokenizer-script) - [Notes](#notes) - [Known issues](#known-issues-1) -- [Tinycrypt ECC operations](#tinycrypt-ecc-operations) +- [NXP Ultrafast P256 ECC Library](#nxp-ultrafast-p256-ecc-library) - [Building steps](#building-steps) +- [Tinycrypt ECC library](#tinycrypt-ecc-library) + - [Building steps](#building-steps-1) - [OTA](#ota) - [Writing the SSBL](#writing-the-ssbl) - [Writing the PSECT](#writing-the-psect) @@ -190,17 +192,16 @@ In order to build the Project CHIP example, we recommend using a Linux distribution (the demo-application was compiled on Ubuntu 20.04). - Download - [K32W0 SDK 2.6.7](https://cache.nxp.com/lgfiles/bsps/SDK_2_6_7_K32W061DK6.zip). + [K32W061DK6 SDK 2.6.9](https://cache.nxp.com/lgfiles/bsps/SDK_2_6_9_K32W061DK6.zip). - Start building the application either with Secure Element or without - without Secure Element ``` -user@ubuntu:~/Desktop/git/connectedhomeip$ export NXP_K32W0_SDK_ROOT=/home/user/Desktop/SDK_2_6_7_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_9_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_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$ 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=\"platform\" chip_with_se05x=0 chip_pw_tokenizer_logging=true" 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_K32W0_SDK_ROOT/tools/imagetool/sign_images.sh out/debug/ ``` @@ -212,9 +213,11 @@ 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 - - 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. +- K32W041AM flavor + + Exactly the same steps as above but set argument build_for_k32w041am=1 in + the gn command and use + [K32W041AMDK6 SDK 2.6.9](https://cache.nxp.com/lgfiles/bsps/SDK_2_6_9_K32W041AMDK6.zip). 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 @@ -223,6 +226,10 @@ to zero. The argument chip_with_OM15082 is set to zero by default. In case that Openthread CLI is needed, chip_with_ot_cli build argument must be set to 1. +In case the board doesn't have 32KHz crystal fitted, one can use the 32KHz free +running oscillator as a clock source. In this case one must set the use_fro_32k +argument to 1. + In case signing errors are encountered when running the "sign_images.sh" script install the recommanded packages (python version > 3, pip3, pycrypto, pycryptodome): @@ -249,6 +256,30 @@ The resulting output file can be found in out/debug/chip-k32w0x-light-example. See [Guide for writing manufacturing data on NXP devices](../../../../platform/nxp/doc/manufacturing_flow.md). +There are factory data generated binaries available in +examples/platform/nxp/k32w/k32w0/scripts/demo_generated_factory_data folder. +These are based on the DAC, PAI and PAA certificates found in +scripts/tools/nxp/demo_generated_certs folder. The demo_factory_data_dut1.bin +uses the DAC certificate and private key found in +examples/platform/nxp/k32w/k32w0/scripts/demo_generated_factory_data/dac/dut1 +folder. The demo_factory_data_dut2.bin uses the DAC certificate and private key +found in +examples/platform/nxp/k32w/k32w0/scripts/demo_generated_factory_data/dac/dut2 +folder. These two factory data binaries can be used for testing topologies with +2 DUTS. They contain the corresponding DACs/PAIs generated using +generate_nxp_chip_factory_bin.py script. The discriminator is 14014 and the +passcode is 1000. These demo certificates are working with the CDs installed in +CHIPProjectConfig.h. + +Regarding factory data provider, there are two options: + +- use the default factory data provider: `K32W0FactoryDataProvider` by setting + `chip_with_factory_data=1` in the gn build command. +- use a custom factory data provider: please see + [Guide for implementing a custom factory data provider](../../../../platform/nxp/k32w/k32w0/common/README.md). + This can be enabled when `chip_with_factory_data=1` by setting + `use_custom_factory_provider=1` in the gn build command. + ## Flashing and debugging Program the firmware using the official @@ -324,21 +355,28 @@ 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 +## NXP Ultrafast P256 ECC Library ### Building steps -Note: This solution is temporary. +By default, the application builds with NXP Ultrafast P256 ECC Library. To build +with this library, use the following arguments: + +- Build without Secure element (_chip_with_se05x=0_) and with crypto platform + (_chip_crypto=\"platform\"_). -In order to use the tinycrypt ecc operations, use the following build arguments: +To stop using Ultrafast P256 ECC Library, simply build with +_chip_crypto=\"mbedtls\"_ or with Tinycrypt. -- 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\"`_). +## Tinycrypt ECC library -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. +### Building steps + +In order to use the Tinycrypt ECC library, use the following build arguments: + +- Build without Secure element (_chip_with_se05x=0_), with crypto platform + (_chip_crypto=\"platform\"_) and with tinycrypt selected + (_chip_crypto_flavor=\"tinycrypt\"_). ## OTA @@ -472,6 +510,13 @@ user@computer1:~/connectedhomeip$ : rm -rf /tmp/chip_* user@computer1:~/connectedhomeip$ : ./out/ota-provider-app/chip-ota-provider-app -f chip-k32w0x-light-example.ota ``` +A note regarding OTA image header version (`-vn` option). An application binary +has its own software version (given by +`CHIP_DEVICE_CONFIG_DEVICE_SOFTWARE_VERSION`, which can be overwritten). For +having a correct OTA process, the OTA header version should be the same as the +binary embedded software version. A user can set a custom software version in +the gn build args by setting `chip_software_version` to the wanted version. + Build Linux chip-tool: ``` diff --git a/examples/lighting-app/nxp/k32w/k32w0/include/CHIPProjectConfig.h b/examples/lighting-app/nxp/k32w/k32w0/include/CHIPProjectConfig.h index 11b539c5a67aff..c994886a68215a 100644 --- a/examples/lighting-app/nxp/k32w/k32w0/include/CHIPProjectConfig.h +++ b/examples/lighting-app/nxp/k32w/k32w0/include/CHIPProjectConfig.h @@ -43,13 +43,22 @@ #if CONFIG_CHIP_K32W0_REAL_FACTORY_DATA +// Enable usage of custom factory data provider +#ifndef CHIP_DEVICE_CONFIG_USE_CUSTOM_PROVIDER +#define CHIP_DEVICE_CONFIG_USE_CUSTOM_PROVIDER 0 +#endif + +#if CHIP_DEVICE_CONFIG_USE_CUSTOM_PROVIDER +#ifndef CHIP_DEVICE_CONFIG_CUSTOM_PROVIDER_NUMBER_IDS +// Set to 3: default number of custom Ids from CustomFactoryDataProvider example +#define CHIP_DEVICE_CONFIG_CUSTOM_PROVIDER_NUMBER_IDS 3 +#endif +#endif + // VID/PID for product => will be used by Basic Information Cluster #define CHIP_DEVICE_CONFIG_DEVICE_VENDOR_ID 0x1037 #define CHIP_DEVICE_CONFIG_DEVICE_PRODUCT_ID 0xA220 -// set it to 0 for the moment -#define CHIP_DEVICE_CONFIG_ENABLE_DEVICE_INSTANCE_INFO_PROVIDER 0 - #ifndef CHIP_DEVICE_CONFIG_CERTIFICATION_DECLARATION //-> format_version = 1 //-> vendor_id = 0x1037 diff --git a/examples/lighting-app/nxp/k32w/k32w0/main/AppTask.cpp b/examples/lighting-app/nxp/k32w/k32w0/main/AppTask.cpp index 18b9896475115b..9a66623836036b 100644 --- a/examples/lighting-app/nxp/k32w/k32w0/main/AppTask.cpp +++ b/examples/lighting-app/nxp/k32w/k32w0/main/AppTask.cpp @@ -18,6 +18,7 @@ */ #include "AppTask.h" #include "AppEvent.h" +#include #include #include @@ -57,7 +58,6 @@ #ifdef ENABLE_HSM_DEVICE_ATTESTATION #include "DeviceAttestationSe05xCredsExample.h" #endif -#include "CHIPProjectConfig.h" #define FACTORY_RESET_TRIGGER_TIMEOUT 6000 #define FACTORY_RESET_CANCEL_WINDOW_TIMEOUT 3000 @@ -72,9 +72,8 @@ static QueueHandle_t sAppEventQueue; static LEDWidget sStatusLED; static LEDWidget sLightLED; -static bool sIsThreadProvisioned = false; -static bool sHaveBLEConnections = false; -static bool sIsDnssdPlatformInitialized = false; +static bool sIsThreadProvisioned = false; +static bool sHaveBLEConnections = false; static uint32_t eventMask = 0; @@ -138,12 +137,10 @@ CHIP_ERROR AppTask::Init() // Initialize device attestation config #if CONFIG_CHIP_K32W0_REAL_FACTORY_DATA // Initialize factory data provider - ReturnErrorOnFailure(K32W0FactoryDataProvider::GetDefaultInstance().Init()); -#if CHIP_DEVICE_CONFIG_ENABLE_DEVICE_INSTANCE_INFO_PROVIDER - SetDeviceInstanceInfoProvider(&mK32W0FactoryDataProvider); -#endif - SetDeviceAttestationCredentialsProvider(&K32W0FactoryDataProvider::GetDefaultInstance()); - SetCommissionableDataProvider(&K32W0FactoryDataProvider::GetDefaultInstance()); + ReturnErrorOnFailure(AppTask::FactoryDataProvider::GetDefaultInstance().Init()); + SetDeviceInstanceInfoProvider(&AppTask::FactoryDataProvider::GetDefaultInstance()); + SetDeviceAttestationCredentialsProvider(&AppTask::FactoryDataProvider::GetDefaultInstance()); + SetCommissionableDataProvider(&AppTask::FactoryDataProvider::GetDefaultInstance()); #else #ifdef ENABLE_HSM_DEVICE_ATTESTATION SetDeviceAttestationCredentialsProvider(Examples::GetExampleSe05xDACProvider()); @@ -152,7 +149,7 @@ CHIP_ERROR AppTask::Init() #endif // QR code will be used with CHIP Tool - PrintOnboardingCodes(chip::RendezvousInformationFlags(chip::RendezvousInformationFlag::kBLE)); + AppTask::PrintOnboardingInfo(); #endif /* HW init leds */ @@ -198,23 +195,11 @@ CHIP_ERROR AppTask::Init() K32W_LOG("Get version error"); assert(err == CHIP_NO_ERROR); } + uint32_t currentVersion; + err = ConfigurationMgr().GetSoftwareVersion(currentVersion); - K32W_LOG("Current Software Version: %s", currentSoftwareVer); + K32W_LOG("Current Software Version: %s, %" PRIu32, currentSoftwareVer, currentVersion); -#if CHIP_DEVICE_CONFIG_ENABLE_OTA_REQUESTOR - if (gImageProcessor.IsFirstImageRun()) - { - // If DNS-SD initialization was captured by MatterEventHandler, then - // OTA initialization will be started as soon as possible. Otherwise, - // a periodic timer is started until the DNS-SD initialization event - // is received. Configurable delay: CHIP_DEVICE_CONFIG_INIT_OTA_DELAY - AppTask::OnScheduleInitOTA(nullptr, nullptr); - } - else - { - PlatformMgr().ScheduleWork(AppTask::InitOTA, 0); - } -#endif return err; } @@ -248,6 +233,18 @@ void AppTask::InitServer(intptr_t arg) VerifyOrDie((chip::Server::GetInstance().Init(initParams)) == CHIP_NO_ERROR); } +void AppTask::PrintOnboardingInfo() +{ + chip::PayloadContents payload; + CHIP_ERROR err = GetPayloadContents(payload, chip::RendezvousInformationFlags(chip::RendezvousInformationFlag::kBLE)); + if (err != CHIP_NO_ERROR) + { + ChipLogError(AppServer, "GetPayloadContents() failed: %" CHIP_ERROR_FORMAT, err.Format()); + } + payload.commissioningFlow = chip::CommissioningFlow::kUserActionRequired; + PrintOnboardingCodes(payload); +} + #if CHIP_DEVICE_CONFIG_ENABLE_OTA_REQUESTOR void AppTask::InitOTA(intptr_t arg) { @@ -552,32 +549,6 @@ void AppTask::StartOTAQuery(intptr_t arg) { GetRequestorInstance()->TriggerImmediateQuery(); } - -void AppTask::PostOTAResume() -{ - AppEvent event; - event.Type = AppEvent::kEventType_OTAResume; - event.Handler = OTAResumeEventHandler; - sAppTask.PostEvent(&event); -} - -void AppTask::OnScheduleInitOTA(chip::System::Layer * systemLayer, void * appState) -{ - if (sIsDnssdPlatformInitialized) - { - PlatformMgr().ScheduleWork(AppTask::InitOTA, 0); - } - else - { - CHIP_ERROR error = chip::DeviceLayer::SystemLayer().StartTimer( - chip::System::Clock::Milliseconds32(CHIP_DEVICE_CONFIG_INIT_OTA_DELAY), AppTask::OnScheduleInitOTA, nullptr); - - if (error != CHIP_NO_ERROR) - { - K32W_LOG("Failed to schedule OTA initialization timer."); - } - } -} #endif void AppTask::BleHandler(AppEvent * aEvent) @@ -630,15 +601,10 @@ void AppTask::MatterEventHandler(const ChipDeviceEvent * event, intptr_t) } #if CHIP_DEVICE_CONFIG_ENABLE_OTA_REQUESTOR - if (event->Type == DeviceEventType::kOtaStateChanged && event->OtaStateChanged.newState == kOtaSpaceAvailable) - { - sAppTask.PostOTAResume(); - } - if (event->Type == DeviceEventType::kDnssdPlatformInitialized) { K32W_LOG("Dnssd platform initialized."); - sIsDnssdPlatformInitialized = true; + PlatformMgr().ScheduleWork(AppTask::InitOTA, 0); } #endif @@ -875,19 +841,6 @@ void AppTask::PostTurnOnActionRequest(int32_t aActor, LightingManager::Action_t PostEvent(&event); } -void AppTask::OTAResumeEventHandler(AppEvent * aEvent) -{ - if (aEvent->Type == AppEvent::kEventType_OTAResume) - { -#if CHIP_DEVICE_CONFIG_ENABLE_OTA_REQUESTOR - if (gDownloader.GetState() == OTADownloader::State::kInProgress) - { - gImageProcessor.TriggerNewRequestForData(); - } -#endif - } -} - void AppTask::PostEvent(const AppEvent * aEvent) { if (sAppEventQueue != NULL) diff --git a/examples/lighting-app/nxp/k32w/k32w0/main/include/AppTask.h b/examples/lighting-app/nxp/k32w/k32w0/main/include/AppTask.h index e47c217bae169e..e91e3c5a303167 100644 --- a/examples/lighting-app/nxp/k32w/k32w0/main/include/AppTask.h +++ b/examples/lighting-app/nxp/k32w/k32w0/main/include/AppTask.h @@ -22,9 +22,17 @@ #include #include "AppEvent.h" -#include "K32W0FactoryDataProvider.h" #include "LightingManager.h" +#include "CHIPProjectConfig.h" + +#if CONFIG_CHIP_K32W0_REAL_FACTORY_DATA +#include "K32W0FactoryDataProvider.h" +#if CHIP_DEVICE_CONFIG_USE_CUSTOM_PROVIDER +#include "CustomFactoryDataProvider.h" +#endif +#endif + #include #include @@ -41,6 +49,15 @@ class AppTask { +public: +#if CONFIG_CHIP_K32W0_REAL_FACTORY_DATA +#if CHIP_DEVICE_CONFIG_USE_CUSTOM_PROVIDER + using FactoryDataProvider = chip::DeviceLayer::CustomFactoryDataProvider; +#else + using FactoryDataProvider = chip::DeviceLayer::K32W0FactoryDataProvider; +#endif +#endif + public: CHIP_ERROR StartAppTask(); static void AppTaskMain(void * pvParameter); @@ -76,7 +93,6 @@ class AppTask static void BleHandler(AppEvent * aEvent); static void BleStartAdvertising(intptr_t arg); static void LightActionEventHandler(AppEvent * aEvent); - static void OTAResumeEventHandler(AppEvent * aEvent); static void ResetActionEventHandler(AppEvent * aEvent); static void InstallEventHandler(AppEvent * aEvent); @@ -91,18 +107,16 @@ class AppTask #if CHIP_DEVICE_CONFIG_ENABLE_OTA_REQUESTOR static void InitOTA(intptr_t arg); static void StartOTAQuery(intptr_t arg); - static void PostOTAResume(); - static void OnScheduleInitOTA(chip::System::Layer * systemLayer, void * appState); #endif static void UpdateClusterStateInternal(intptr_t arg); static void UpdateDeviceStateInternal(intptr_t arg); static void InitServer(intptr_t arg); + static void PrintOnboardingInfo(); enum Function_t { - kFunction_NoneSelected = 0, - kFunction_SoftwareUpdate = 0, + kFunction_NoneSelected = 0, kFunction_FactoryReset, kFunctionTurnOnTurnOff, kFunction_Identify, diff --git a/examples/lighting-app/nxp/k32w/k32w0/main/main.cpp b/examples/lighting-app/nxp/k32w/k32w0/main/main.cpp index 4c2ce040d2b786..a8963a17c09096 100644 --- a/examples/lighting-app/nxp/k32w/k32w0/main/main.cpp +++ b/examples/lighting-app/nxp/k32w/k32w0/main/main.cpp @@ -31,6 +31,10 @@ #include "FreeRtosHooks.h" #include "app_config.h" +#if PDM_SAVE_IDLE +#include +#endif + #ifdef K32WMCM_APP_BUILD #define string string_shadow #include "AppApi.h" @@ -110,6 +114,12 @@ extern "C" void main_task(void const * argument) APP_SetHighTxPowerMode(); #endif +#if PDM_SAVE_IDLE + /* OT Settings needs to be initialized + * early as XCVR is making use of it */ + otPlatSettingsInit(NULL, NULL, 0); +#endif + err = PlatformMgr().InitChipStack(); 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 95f1a8c02a7848..2260f4cf1b58fd 100644 --- a/examples/lock-app/nxp/k32w/k32w0/BUILD.gn +++ b/examples/lock-app/nxp/k32w/k32w0/BUILD.gn @@ -24,6 +24,10 @@ import("${k32w0_sdk_build_root}/k32w0_sdk.gni") import("${chip_root}/src/crypto/crypto.gni") import("${chip_root}/src/lib/core/core.gni") +declare_args() { + chip_software_version = 0 +} + if (chip_pw_tokenizer_logging) { import("//build_overrides/pigweed.gni") import("$dir_pw_tokenizer/database.gni") @@ -50,6 +54,7 @@ k32w0_sdk("sdk") { "include", "${k32w0_platform_dir}/app/support", "${k32w0_platform_dir}/util/include", + "${k32w0_platform_dir}/common", ] if (chip_with_se05x == 1) { @@ -62,6 +67,12 @@ k32w0_sdk("sdk") { } else { defines += [ "BUILD_RELEASE=1" ] } + + if (chip_software_version != 0) { + defines += [ + "CHIP_DEVICE_CONFIG_DEVICE_SOFTWARE_VERSION=${chip_software_version}", + ] + } } k32w0_executable("lock_app") { @@ -79,10 +90,22 @@ k32w0_executable("lock_app") { "main/main.cpp", ] + if (chip_with_factory_data == 1 && use_custom_factory_provider == 1) { + sources += [ + "${k32w0_platform_dir}/common/CustomFactoryDataProvider.cpp", + "${k32w0_platform_dir}/common/CustomFactoryDataProvider.h", + ] + + defines = [ + "CHIP_DEVICE_CONFIG_USE_CUSTOM_PROVIDER=1", + "CHIP_DEVICE_CONFIG_CUSTOM_PROVIDER_NUMBER_IDS=3", + ] + } + deps = [ ":sdk", "${chip_root}/examples/common/QRCode", - "${chip_root}/examples/lock-app/lock-common", + "${chip_root}/examples/lock-app/nxp/zap/", "${chip_root}/examples/providers:device_info_provider", "${chip_root}/src/crypto", "${chip_root}/src/lib", @@ -111,7 +134,10 @@ k32w0_executable("lock_app") { inputs = [ ldscript ] - ldflags = [ "-T" + rebase_path(ldscript, root_build_dir) ] + ldflags = [ + "-T" + rebase_path(ldscript, root_build_dir), + "-Wl,-print-memory-usage", + ] } if (chip_pw_tokenizer_logging) { diff --git a/examples/lock-app/nxp/k32w/k32w0/README.md b/examples/lock-app/nxp/k32w/k32w0/README.md index c797127b5dbd3b..85a99f8e4e8554 100644 --- a/examples/lock-app/nxp/k32w/k32w0/README.md +++ b/examples/lock-app/nxp/k32w/k32w0/README.md @@ -29,8 +29,10 @@ network. - [Detokenizer script](#detokenizer-script) - [Notes](#notes) - [Known issues](#known-issues-1) -- [Tinycrypt ECC operations](#tinycrypt-ecc-operations) +- [NXP Ultrafast P256 ECC Library](#nxp-ultrafast-p256-ecc-library) - [Building steps](#building-steps) +- [Tinycrypt ECC library](#tinycrypt-ecc-library) + - [Building steps](#building-steps-1) - [Low power](#low-power) - [Known issues](#known-issues-2) @@ -171,18 +173,18 @@ In order to build the Project CHIP example, we recommend using a Linux distribution (the demo-application was compiled on Ubuntu 20.04). - Download - [K32W0 SDK 2.6.7](https://cache.nxp.com/lgfiles/bsps/SDK_2_6_7_K32W061DK6.zip). + [K32W061DK6 SDK 2.6.9](https://cache.nxp.com/lgfiles/bsps/SDK_2_6_9_K32W061DK6.zip). - Start building the application either with Secure Element or without - without Secure Element ``` -user@ubuntu:~/Desktop/git/connectedhomeip$ export NXP_K32W0_SDK_ROOT=/home/user/Desktop/SDK_2_6_7_K32W061DK6/ +user@ubuntu:~/Desktop/git/connectedhomeip$ export NXP_K32W0_SDK_ROOT=/home/user/Desktop/SDK_2_6_9_K32W061DK6/ user@ubuntu:~/Desktop/git/connectedhomeip$ ./third_party/nxp/k32w0_sdk/sdk_fixes/patch_k32w_sdk.sh 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_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$ 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=\"platform\" chip_with_se05x=0 chip_pw_tokenizer_logging=true" 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_K32W0_SDK_ROOT/tools/imagetool/sign_images.sh out/debug/ ``` @@ -197,6 +199,10 @@ to zero. The argument chip_with_OM15082 is set to zero by default. In case that Openthread CLI is needed, chip_with_ot_cli build argument must be set to 1. +In case the board doesn't have 32KHz crystal fitted, one can use the 32KHz free +running oscillator as a clock source. In this case one must set the use_fro_32k +argument to 1. + In case signing errors are encountered when running the "sign_images.sh" script install the recommanded packages (python version > 3, pip3, pycrypto, pycryptodome): @@ -223,6 +229,30 @@ The resulting output file can be found in out/debug/chip-k32w0x-lock-example. See [Guide for writing manufacturing data on NXP devices](../../../../platform/nxp/doc/manufacturing_flow.md). +There are factory data generated binaries available in +examples/platform/nxp/k32w/k32w0/scripts/demo_generated_factory_data folder. +These are based on the DAC, PAI and PAA certificates found in +scripts/tools/nxp/demo_generated_certs folder. The demo_factory_data_dut1.bin +uses the DAC certificate and private key found in +examples/platform/nxp/k32w/k32w0/scripts/demo_generated_factory_data/dac/dut1 +folder. The demo_factory_data_dut2.bin uses the DAC certificate and private key +found in +examples/platform/nxp/k32w/k32w0/scripts/demo_generated_factory_data/dac/dut2 +folder. These two factory data binaries can be used for testing topologies with +2 DUTS. They contain the corresponding DACs/PAIs generated using +generate_nxp_chip_factory_bin.py script. The discriminator is 14014 and the +passcode is 1000. These demo certificates are working with the CDs installed in +CHIPProjectConfig.h. + +Regarding factory data provider, there are two options: + +- use the default factory data provider: `K32W0FactoryDataProvider` by setting + `chip_with_factory_data=1` in the gn build command. +- use a custom factory data provider: please see + [Guide for implementing a custom factory data provider](../../../../platform/nxp/k32w/k32w0/common/README.md). + This can be enabled when `chip_with_factory_data=1` by setting + `use_custom_factory_provider=1` in the gn build command. + ## Flashing and debugging Program the firmware using the official @@ -298,21 +328,28 @@ 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 +## NXP Ultrafast P256 ECC Library ### Building steps -Note: This solution is temporary. +By default, the application builds with NXP Ultrafast P256 ECC Library. To build +with this library, use the following arguments: + +- Build without Secure element (_chip_with_se05x=0_) and with crypto platform + (_chip_crypto=\"platform\"_). -In order to use the tinycrypt ecc operations, use the following build arguments: +To stop using Ultrafast P256 ECC Library, simply build with +_chip_crypto=\"mbedtls\"_ or with Tinycrypt. + +## Tinycrypt ECC library + +### Building steps -- 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\"`_). +In order to use the Tinycrypt ECC library, use the following build arguments: -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. +- Build without Secure element (_chip_with_se05x=0_), with crypto platform + (_chip_crypto=\"platform\"_) and with tinycrypt selected + (_chip_crypto_flavor=\"tinycrypt\"_). ## Low power diff --git a/examples/lock-app/nxp/k32w/k32w0/include/CHIPProjectConfig.h b/examples/lock-app/nxp/k32w/k32w0/include/CHIPProjectConfig.h index d5c00c46cb1868..0ce39a8e498993 100644 --- a/examples/lock-app/nxp/k32w/k32w0/include/CHIPProjectConfig.h +++ b/examples/lock-app/nxp/k32w/k32w0/include/CHIPProjectConfig.h @@ -43,13 +43,22 @@ #if CONFIG_CHIP_K32W0_REAL_FACTORY_DATA +// Enable usage of custom factory data provider +#ifndef CHIP_DEVICE_CONFIG_USE_CUSTOM_PROVIDER +#define CHIP_DEVICE_CONFIG_USE_CUSTOM_PROVIDER 0 +#endif + +#if CHIP_DEVICE_CONFIG_USE_CUSTOM_PROVIDER +#ifndef CHIP_DEVICE_CONFIG_CUSTOM_PROVIDER_NUMBER_IDS +// Set to 3: default number of custom Ids from CustomFactoryDataProvider example +#define CHIP_DEVICE_CONFIG_CUSTOM_PROVIDER_NUMBER_IDS 3 +#endif +#endif + // VID/PID for product => will be used by Basic Information Cluster #define CHIP_DEVICE_CONFIG_DEVICE_VENDOR_ID 0x1037 #define CHIP_DEVICE_CONFIG_DEVICE_PRODUCT_ID 0xA220 -// set it to 0 for the moment -#define CHIP_DEVICE_CONFIG_ENABLE_DEVICE_INSTANCE_INFO_PROVIDER 0 - #ifndef CHIP_DEVICE_CONFIG_CERTIFICATION_DECLARATION //-> format_version = 1 //-> vendor_id = 0x1037 diff --git a/examples/lock-app/nxp/k32w/k32w0/include/FreeRTOSConfig.h b/examples/lock-app/nxp/k32w/k32w0/include/FreeRTOSConfig.h index 22d311ad15326c..2b82b290a9b2cb 100644 --- a/examples/lock-app/nxp/k32w/k32w0/include/FreeRTOSConfig.h +++ b/examples/lock-app/nxp/k32w/k32w0/include/FreeRTOSConfig.h @@ -54,7 +54,7 @@ #if defined(cPWR_UsePowerDownMode) && (cPWR_UsePowerDownMode) #define configMINIMAL_STACK_SIZE ((unsigned short) 250) #else -#define configMINIMAL_STACK_SIZE ((unsigned short) 90) +#define configMINIMAL_STACK_SIZE ((unsigned short) 450) #endif #define configMAX_TASK_NAME_LEN 20 @@ -87,13 +87,7 @@ #define configTOTAL_HEAP_SIZE ((size_t)(gTotalHeapSize_c)) #define configAPPLICATION_ALLOCATED_HEAP 1 -/* Hook function related definitions. */ -#if defined(cPWR_UsePowerDownMode) && (cPWR_UsePowerDownMode) #define configUSE_IDLE_HOOK 1 -#else -#define configUSE_IDLE_HOOK 0 -#endif - #define configUSE_TICK_HOOK 0 #define configCHECK_FOR_STACK_OVERFLOW 0 #ifndef configUSE_MALLOC_FAILED_HOOK diff --git a/examples/lock-app/nxp/k32w/k32w0/main/AppTask.cpp b/examples/lock-app/nxp/k32w/k32w0/main/AppTask.cpp index 5971c4ea7c28e0..51f3f500521d0a 100644 --- a/examples/lock-app/nxp/k32w/k32w0/main/AppTask.cpp +++ b/examples/lock-app/nxp/k32w/k32w0/main/AppTask.cpp @@ -18,6 +18,7 @@ */ #include "AppTask.h" #include "AppEvent.h" +#include #include #include @@ -97,12 +98,10 @@ CHIP_ERROR AppTask::Init() // Initialize device attestation config #if CONFIG_CHIP_K32W0_REAL_FACTORY_DATA // Initialize factory data provider - ReturnErrorOnFailure(K32W0FactoryDataProvider::GetDefaultInstance().Init()); -#if CHIP_DEVICE_CONFIG_ENABLE_DEVICE_INSTANCE_INFO_PROVIDER - SetDeviceInstanceInfoProvider(&K32W0FactoryDataProvider::GetDefaultInstance()); -#endif - SetDeviceAttestationCredentialsProvider(&K32W0FactoryDataProvider::GetDefaultInstance()); - SetCommissionableDataProvider(&K32W0FactoryDataProvider::GetDefaultInstance()); + ReturnErrorOnFailure(AppTask::FactoryDataProvider::GetDefaultInstance().Init()); + SetDeviceInstanceInfoProvider(&AppTask::FactoryDataProvider::GetDefaultInstance()); + SetDeviceAttestationCredentialsProvider(&AppTask::FactoryDataProvider::GetDefaultInstance()); + SetCommissionableDataProvider(&AppTask::FactoryDataProvider::GetDefaultInstance()); #else #ifdef ENABLE_HSM_DEVICE_ATTESTATION SetDeviceAttestationCredentialsProvider(Examples::GetExampleSe05xDACProvider()); @@ -111,7 +110,7 @@ CHIP_ERROR AppTask::Init() #endif // QR code will be used with CHIP Tool - PrintOnboardingCodes(chip::RendezvousInformationFlags(chip::RendezvousInformationFlag::kBLE)); + AppTask::PrintOnboardingInfo(); #endif /* HW init leds */ @@ -196,6 +195,18 @@ void AppTask::InitServer(intptr_t arg) VerifyOrDie((chip::Server::GetInstance().Init(initParams)) == CHIP_NO_ERROR); } +void AppTask::PrintOnboardingInfo() +{ + chip::PayloadContents payload; + CHIP_ERROR err = GetPayloadContents(payload, chip::RendezvousInformationFlags(chip::RendezvousInformationFlag::kBLE)); + if (err != CHIP_NO_ERROR) + { + ChipLogError(AppServer, "GetPayloadContents() failed: %" CHIP_ERROR_FORMAT, err.Format()); + } + payload.commissioningFlow = chip::CommissioningFlow::kUserActionRequired; + PrintOnboardingCodes(payload); +} + void AppTask::AppTaskMain(void * pvParameter) { AppEvent event; @@ -711,21 +722,9 @@ void AppTask::PostLockActionRequest(int32_t aActor, BoltLockManager::Action_t aA void AppTask::PostEvent(const AppEvent * aEvent) { - portBASE_TYPE taskToWake = pdFALSE; if (sAppEventQueue != NULL) { - if (__get_IPSR()) - { - if (!xQueueSendToFrontFromISR(sAppEventQueue, aEvent, &taskToWake)) - { - K32W_LOG("Failed to post event to app task event queue"); - } - if (taskToWake) - { - portYIELD_FROM_ISR(taskToWake); - } - } - else if (!xQueueSend(sAppEventQueue, aEvent, 0)) + if (!xQueueSend(sAppEventQueue, aEvent, 0)) { K32W_LOG("Failed to post event to app task event queue"); } @@ -761,11 +760,14 @@ void AppTask::UpdateClusterStateInternal(intptr_t arg) { uint8_t newValue = !BoltLockMgr().IsUnlocked(); - // write the new on/off value - EmberAfStatus status = chip::app::Clusters::OnOff::Attributes::OnOff::Set(1, newValue); + // write the new door lock state + EmberAfStatus status = + emberAfWriteAttribute(1, chip::app::Clusters::DoorLock::Id, chip::app::Clusters::DoorLock::Attributes::LockState::Id, + (uint8_t *) &newValue, ZCL_ENUM8_ATTRIBUTE_TYPE); + if (status != EMBER_ZCL_STATUS_SUCCESS) { - ChipLogError(NotSpecified, "ERR: updating on/off %x", status); + ChipLogError(NotSpecified, "ERR: updating door lock state %x", status); } } diff --git a/examples/lock-app/nxp/k32w/k32w0/main/ZclCallbacks.cpp b/examples/lock-app/nxp/k32w/k32w0/main/ZclCallbacks.cpp index 2ce2fe1c3056c1..9033f40aaeff7e 100644 --- a/examples/lock-app/nxp/k32w/k32w0/main/ZclCallbacks.cpp +++ b/examples/lock-app/nxp/k32w/k32w0/main/ZclCallbacks.cpp @@ -29,40 +29,16 @@ using namespace ::chip; using namespace ::chip::app::Clusters; +using namespace ::chip::app::Clusters::DoorLock; -void MatterPostAttributeChangeCallback(const chip::app::ConcreteAttributePath & path, uint8_t type, uint16_t size, uint8_t * value) +bool emberAfPluginDoorLockOnDoorLockCommand(chip::EndpointId endpointId, const Optional & pinCode, + OperationErrorEnum & err) { - if (path.mClusterId != OnOff::Id) - { - ChipLogProgress(Zcl, "Unknown cluster ID: " ChipLogFormatMEI, ChipLogValueMEI(path.mClusterId)); - return; - } - - if (path.mAttributeId != OnOff::Attributes::OnOff::Id) - { - ChipLogProgress(Zcl, "Unknown attribute ID: " ChipLogFormatMEI, ChipLogValueMEI(path.mAttributeId)); - return; - } - - BoltLockMgr().InitiateAction(0, *value ? BoltLockManager::LOCK_ACTION : BoltLockManager::UNLOCK_ACTION); + return BoltLockMgr().InitiateAction(0, BoltLockManager::LOCK_ACTION); } -/** @brief OnOff Cluster Init - * - * This function is called when a specific cluster is initialized. It gives the - * application an opportunity to take care of cluster initialization procedures. - * It is called exactly once for each endpoint where cluster is present. - * - * @param endpoint Ver.: always - * - * TODO Issue #3841 - * emberAfOnOffClusterInitCallback happens before the stack initialize the cluster - * attributes to the default value. - * The logic here expects something similar to the deprecated Plugins callback - * emberAfPluginOnOffClusterServerPostInitCallback. - * - */ -void emberAfOnOffClusterInitCallback(EndpointId endpoint) +bool emberAfPluginDoorLockOnDoorUnlockCommand(chip::EndpointId endpointId, const Optional & pinCode, + OperationErrorEnum & err) { - GetAppTask().UpdateClusterState(); + return BoltLockMgr().InitiateAction(0, BoltLockManager::UNLOCK_ACTION); } diff --git a/examples/lock-app/nxp/k32w/k32w0/main/include/AppTask.h b/examples/lock-app/nxp/k32w/k32w0/main/include/AppTask.h index db06766b56c193..2e1194ed36c721 100644 --- a/examples/lock-app/nxp/k32w/k32w0/main/include/AppTask.h +++ b/examples/lock-app/nxp/k32w/k32w0/main/include/AppTask.h @@ -23,7 +23,15 @@ #include "AppEvent.h" #include "BoltLockManager.h" + +#include "CHIPProjectConfig.h" + +#if CONFIG_CHIP_K32W0_REAL_FACTORY_DATA #include "K32W0FactoryDataProvider.h" +#if CHIP_DEVICE_CONFIG_USE_CUSTOM_PROVIDER +#include "CustomFactoryDataProvider.h" +#endif +#endif #include @@ -32,6 +40,15 @@ class AppTask { +public: +#if CONFIG_CHIP_K32W0_REAL_FACTORY_DATA +#if CHIP_DEVICE_CONFIG_USE_CUSTOM_PROVIDER + using FactoryDataProvider = chip::DeviceLayer::CustomFactoryDataProvider; +#else + using FactoryDataProvider = chip::DeviceLayer::K32W0FactoryDataProvider; +#endif +#endif + public: CHIP_ERROR StartAppTask(); static void AppTaskMain(void * pvParameter); @@ -70,6 +87,7 @@ class AppTask static void UpdateClusterStateInternal(intptr_t arg); static void ThreadStart(); static void InitServer(intptr_t arg); + static void PrintOnboardingInfo(); void StartTimer(uint32_t aTimeoutInMs); enum Function_t diff --git a/examples/lock-app/nxp/k32w/k32w0/main/main.cpp b/examples/lock-app/nxp/k32w/k32w0/main/main.cpp index 4692a4068c6d52..795cd3b9fcb09b 100644 --- a/examples/lock-app/nxp/k32w/k32w0/main/main.cpp +++ b/examples/lock-app/nxp/k32w/k32w0/main/main.cpp @@ -31,6 +31,16 @@ #include "FreeRtosHooks.h" #include "app_config.h" +#if PDM_SAVE_IDLE +#include +#endif + +#if defined(cPWR_UsePowerDownMode) && (cPWR_UsePowerDownMode) +#include "fsl_gpio.h" +#include "fsl_iocon.h" +#include "gpio_pins.h" +#endif + using namespace ::chip; using namespace ::chip::Inet; using namespace ::chip::DeviceLayer; @@ -92,6 +102,12 @@ extern "C" void main_task(void const * argument) // Init Chip memory management before the stack chip::Platform::MemoryInit(); +#if PDM_SAVE_IDLE + /* OT Settings needs to be initialized + * early as XCVR is making use of it */ + otPlatSettingsInit(NULL, NULL, 0); +#endif + CHIP_ERROR ret = PlatformMgr().InitChipStack(); if (ret != CHIP_NO_ERROR) { @@ -165,3 +181,29 @@ extern "C" void otSysEventSignalPending(void) portYIELD_FROM_ISR(yieldRequired); } } + +#if defined(cPWR_UsePowerDownMode) && (cPWR_UsePowerDownMode) +extern "C" void vOptimizeConsumption(void) +{ + /* BUTTON2 change contact, BUTTON4 start adv/factoryreset */ + uint32_t u32SkipIO = (1 << IOCON_USER_BUTTON1_PIN) | (1 << IOCON_USER_BUTTON2_PIN); + + /* Pins are set to GPIO mode (IOCON FUNC0), pulldown and analog mode */ + uint32_t u32PIOvalue = (IOCON_FUNC0 | IOCON_MODE_PULLDOWN | IOCON_ANALOG_EN); + + const gpio_pin_config_t pin_config = { .pinDirection = kGPIO_DigitalInput, .outputLogic = 1U }; + + if (u32PIOvalue != 0) + { + for (int i = 0; i < 22; i++) + { + if (((u32SkipIO >> i) & 0x1) != 1) + { + /* configure GPIOs to Input mode */ + GPIO_PinInit(GPIO, 0, i, &pin_config); + IOCON_PinMuxSet(IOCON, 0, i, u32PIOvalue); + } + } + } +} +#endif diff --git a/examples/lock-app/nxp/zap/BUILD.gn b/examples/lock-app/nxp/zap/BUILD.gn new file mode 100644 index 00000000000000..ebb03aadd5a2ab --- /dev/null +++ b/examples/lock-app/nxp/zap/BUILD.gn @@ -0,0 +1,24 @@ +# Copyright (c) 2022 Project CHIP Authors +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +import("//build_overrides/chip.gni") +import("${chip_root}/examples/common/pigweed/pigweed_rpcs.gni") +import("${chip_root}/src/app/chip_data_model.gni") + +chip_data_model("zap") { + zap_file = "lock-app.zap" + + zap_pregenerated_dir = "${chip_root}/zzz_generated/lock-app/nxp/zap-generated" + is_server = true +} diff --git a/examples/lock-app/nxp/zap/lock-app.matter b/examples/lock-app/nxp/zap/lock-app.matter new file mode 100644 index 00000000000000..969b19a8ab010e --- /dev/null +++ b/examples/lock-app/nxp/zap/lock-app.matter @@ -0,0 +1,1512 @@ +// This IDL was generated automatically by ZAP. +// It is for view/code review purposes only. + +server cluster Identify = 3 { + enum IdentifyEffectIdentifier : ENUM8 { + kBlink = 0; + kBreathe = 1; + kOkay = 2; + kChannelChange = 11; + kFinishEffect = 254; + kStopEffect = 255; + } + + enum IdentifyEffectVariant : ENUM8 { + kDefault = 0; + } + + enum IdentifyIdentifyType : ENUM8 { + kNone = 0; + kVisibleLight = 1; + kVisibleLED = 2; + kAudibleBeep = 3; + kDisplay = 4; + kActuator = 5; + } + + attribute int16u identifyTime = 0; + readonly attribute enum8 identifyType = 1; + readonly attribute command_id generatedCommandList[] = 65528; + readonly attribute command_id acceptedCommandList[] = 65529; + readonly attribute attrib_id attributeList[] = 65531; + readonly attribute bitmap32 featureMap = 65532; + readonly attribute int16u clusterRevision = 65533; + + request struct IdentifyRequest { + INT16U identifyTime = 0; + } + + request struct TriggerEffectRequest { + IdentifyEffectIdentifier effectIdentifier = 0; + IdentifyEffectVariant effectVariant = 1; + } + + command access(invoke: manage) Identify(IdentifyRequest): DefaultSuccess = 0; + command access(invoke: manage) TriggerEffect(TriggerEffectRequest): DefaultSuccess = 64; +} + +server cluster Descriptor = 29 { + struct DeviceTypeStruct { + devtype_id deviceType = 0; + int16u revision = 1; + } + + readonly attribute DeviceTypeStruct deviceTypeList[] = 0; + readonly attribute CLUSTER_ID serverList[] = 1; + readonly attribute CLUSTER_ID clientList[] = 2; + readonly attribute ENDPOINT_NO partsList[] = 3; + readonly attribute command_id generatedCommandList[] = 65528; + readonly attribute command_id acceptedCommandList[] = 65529; + readonly attribute attrib_id attributeList[] = 65531; + readonly attribute bitmap32 featureMap = 65532; + readonly attribute int16u clusterRevision = 65533; +} + +server cluster AccessControl = 31 { + enum AccessControlEntryAuthModeEnum : ENUM8 { + kPase = 1; + kCase = 2; + kGroup = 3; + } + + enum AccessControlEntryPrivilegeEnum : ENUM8 { + kView = 1; + kProxyView = 2; + kOperate = 3; + kManage = 4; + kAdminister = 5; + } + + enum ChangeTypeEnum : ENUM8 { + kChanged = 0; + kAdded = 1; + kRemoved = 2; + } + + fabric_scoped struct AccessControlEntryStruct { + fabric_sensitive AccessControlEntryPrivilegeEnum privilege = 1; + fabric_sensitive AccessControlEntryAuthModeEnum authMode = 2; + nullable fabric_sensitive int64u subjects[] = 3; + nullable fabric_sensitive Target targets[] = 4; + fabric_idx fabricIndex = 254; + } + + struct Target { + nullable cluster_id cluster = 0; + nullable endpoint_no endpoint = 1; + nullable devtype_id deviceType = 2; + } + + fabric_sensitive info event access(read: administer) AccessControlEntryChanged = 0 { + nullable node_id adminNodeID = 1; + nullable INT16U adminPasscodeID = 2; + ChangeTypeEnum changeType = 3; + nullable AccessControlEntryStruct latestValue = 4; + fabric_idx fabricIndex = 254; + } + + fabric_sensitive info event access(read: administer) AccessControlExtensionChanged = 1 { + nullable node_id adminNodeID = 1; + nullable INT16U adminPasscodeID = 2; + ChangeTypeEnum changeType = 3; + nullable AccessControlExtensionStruct latestValue = 4; + fabric_idx fabricIndex = 254; + } + + attribute access(read: administer, write: administer) AccessControlEntryStruct acl[] = 0; + readonly attribute int16u subjectsPerAccessControlEntry = 2; + readonly attribute int16u targetsPerAccessControlEntry = 3; + readonly attribute int16u accessControlEntriesPerFabric = 4; + readonly attribute attrib_id attributeList[] = 65531; + readonly attribute bitmap32 featureMap = 65532; + readonly attribute int16u clusterRevision = 65533; +} + +server cluster BasicInformation = 40 { + struct CapabilityMinimaStruct { + int16u caseSessionsPerFabric = 0; + int16u subscriptionsPerFabric = 1; + } + + critical event StartUp = 0 { + INT32U softwareVersion = 0; + } + + critical event ShutDown = 1 { + } + + info event Leave = 2 { + fabric_idx fabricIndex = 0; + } + + info event ReachableChanged = 3 { + boolean reachableNewValue = 0; + } + + readonly attribute int16u dataModelRevision = 0; + readonly attribute char_string<32> vendorName = 1; + readonly attribute vendor_id vendorID = 2; + readonly attribute char_string<32> productName = 3; + readonly attribute int16u productID = 4; + attribute access(write: manage) char_string<32> nodeLabel = 5; + attribute access(write: administer) char_string<2> location = 6; + readonly attribute int16u hardwareVersion = 7; + readonly attribute char_string<64> hardwareVersionString = 8; + readonly attribute int32u softwareVersion = 9; + readonly attribute char_string<64> softwareVersionString = 10; + readonly attribute CapabilityMinimaStruct capabilityMinima = 19; + readonly attribute bitmap32 featureMap = 65532; + readonly attribute int16u clusterRevision = 65533; +} + +server cluster GeneralCommissioning = 48 { + enum CommissioningError : ENUM8 { + kOk = 0; + kValueOutsideRange = 1; + kInvalidAuthentication = 2; + kNoFailSafe = 3; + kBusyWithOtherAdmin = 4; + } + + enum RegulatoryLocationType : ENUM8 { + kIndoor = 0; + kOutdoor = 1; + kIndoorOutdoor = 2; + } + + struct BasicCommissioningInfo { + int16u failSafeExpiryLengthSeconds = 0; + int16u maxCumulativeFailsafeSeconds = 1; + } + + attribute access(write: administer) int64u breadcrumb = 0; + readonly attribute BasicCommissioningInfo basicCommissioningInfo = 1; + readonly attribute RegulatoryLocationType regulatoryConfig = 2; + readonly attribute RegulatoryLocationType locationCapability = 3; + readonly attribute boolean supportsConcurrentConnection = 4; + readonly attribute bitmap32 featureMap = 65532; + readonly attribute int16u clusterRevision = 65533; + + request struct ArmFailSafeRequest { + INT16U expiryLengthSeconds = 0; + INT64U breadcrumb = 1; + } + + request struct SetRegulatoryConfigRequest { + RegulatoryLocationType newRegulatoryConfig = 0; + CHAR_STRING countryCode = 1; + INT64U breadcrumb = 2; + } + + response struct ArmFailSafeResponse = 1 { + CommissioningError errorCode = 0; + CHAR_STRING debugText = 1; + } + + response struct SetRegulatoryConfigResponse = 3 { + CommissioningError errorCode = 0; + CHAR_STRING debugText = 1; + } + + response struct CommissioningCompleteResponse = 5 { + CommissioningError errorCode = 0; + CHAR_STRING debugText = 1; + } + + command access(invoke: administer) ArmFailSafe(ArmFailSafeRequest): ArmFailSafeResponse = 0; + command access(invoke: administer) SetRegulatoryConfig(SetRegulatoryConfigRequest): SetRegulatoryConfigResponse = 2; + fabric command access(invoke: administer) CommissioningComplete(): CommissioningCompleteResponse = 4; +} + +server cluster NetworkCommissioning = 49 { + enum NetworkCommissioningStatus : ENUM8 { + kSuccess = 0; + kOutOfRange = 1; + kBoundsExceeded = 2; + kNetworkIDNotFound = 3; + kDuplicateNetworkID = 4; + kNetworkNotFound = 5; + kRegulatoryError = 6; + kAuthFailure = 7; + kUnsupportedSecurity = 8; + kOtherConnectionFailure = 9; + kIPV6Failed = 10; + kIPBindFailed = 11; + kUnknownError = 12; + } + + enum WiFiBand : ENUM8 { + k2g4 = 0; + k3g65 = 1; + k5g = 2; + k6g = 3; + k60g = 4; + } + + bitmap NetworkCommissioningFeature : BITMAP32 { + kWiFiNetworkInterface = 0x1; + kThreadNetworkInterface = 0x2; + kEthernetNetworkInterface = 0x4; + } + + bitmap WiFiSecurity : BITMAP8 { + kUnencrypted = 0x1; + kWep = 0x2; + kWpaPersonal = 0x4; + kWpa2Personal = 0x8; + kWpa3Personal = 0x10; + } + + struct NetworkInfo { + octet_string<32> networkID = 0; + boolean connected = 1; + } + + struct WiFiInterfaceScanResult { + WiFiSecurity security = 0; + octet_string<32> ssid = 1; + octet_string<6> bssid = 2; + int16u channel = 3; + WiFiBand wiFiBand = 4; + int8s rssi = 5; + } + + struct ThreadInterfaceScanResult { + int16u panId = 0; + int64u extendedPanId = 1; + char_string<16> networkName = 2; + int16u channel = 3; + int8u version = 4; + octet_string<8> extendedAddress = 5; + int8s rssi = 6; + int8u lqi = 7; + } + + readonly attribute access(read: administer) int8u maxNetworks = 0; + readonly attribute access(read: administer) NetworkInfo networks[] = 1; + readonly attribute int8u scanMaxTimeSeconds = 2; + readonly attribute int8u connectMaxTimeSeconds = 3; + attribute access(write: administer) boolean interfaceEnabled = 4; + readonly attribute access(read: administer) nullable NetworkCommissioningStatus lastNetworkingStatus = 5; + readonly attribute access(read: administer) nullable octet_string<32> lastNetworkID = 6; + readonly attribute access(read: administer) nullable int32s lastConnectErrorValue = 7; + readonly attribute bitmap32 featureMap = 65532; + readonly attribute int16u clusterRevision = 65533; + + request struct ScanNetworksRequest { + optional nullable OCTET_STRING<32> ssid = 0; + optional INT64U breadcrumb = 1; + } + + request struct AddOrUpdateThreadNetworkRequest { + OCTET_STRING<254> operationalDataset = 0; + optional INT64U breadcrumb = 1; + } + + request struct RemoveNetworkRequest { + OCTET_STRING<32> networkID = 0; + optional INT64U breadcrumb = 1; + } + + request struct ConnectNetworkRequest { + OCTET_STRING<32> networkID = 0; + optional INT64U breadcrumb = 1; + } + + request struct ReorderNetworkRequest { + OCTET_STRING<32> networkID = 0; + INT8U networkIndex = 1; + optional INT64U breadcrumb = 2; + } + + response struct ScanNetworksResponse = 1 { + NetworkCommissioningStatus networkingStatus = 0; + optional CHAR_STRING debugText = 1; + optional WiFiInterfaceScanResult wiFiScanResults[] = 2; + optional ThreadInterfaceScanResult threadScanResults[] = 3; + } + + response struct NetworkConfigResponse = 5 { + NetworkCommissioningStatus networkingStatus = 0; + optional CHAR_STRING<512> debugText = 1; + optional INT8U networkIndex = 2; + } + + response struct ConnectNetworkResponse = 7 { + NetworkCommissioningStatus networkingStatus = 0; + optional CHAR_STRING debugText = 1; + nullable INT32S errorValue = 2; + } + + command access(invoke: administer) ScanNetworks(ScanNetworksRequest): ScanNetworksResponse = 0; + command access(invoke: administer) AddOrUpdateThreadNetwork(AddOrUpdateThreadNetworkRequest): NetworkConfigResponse = 3; + command access(invoke: administer) RemoveNetwork(RemoveNetworkRequest): NetworkConfigResponse = 4; + command access(invoke: administer) ConnectNetwork(ConnectNetworkRequest): ConnectNetworkResponse = 6; + command access(invoke: administer) ReorderNetwork(ReorderNetworkRequest): NetworkConfigResponse = 8; +} + +server cluster GeneralDiagnostics = 51 { + enum BootReasonEnum : ENUM8 { + kUnspecified = 0; + kPowerOnReboot = 1; + kBrownOutReset = 2; + kSoftwareWatchdogReset = 3; + kHardwareWatchdogReset = 4; + kSoftwareUpdateCompleted = 5; + kSoftwareReset = 6; + } + + enum HardwareFaultEnum : ENUM8 { + kUnspecified = 0; + kRadio = 1; + kSensor = 2; + kResettableOverTemp = 3; + kNonResettableOverTemp = 4; + kPowerSource = 5; + kVisualDisplayFault = 6; + kAudioOutputFault = 7; + kUserInterfaceFault = 8; + kNonVolatileMemoryError = 9; + kTamperDetected = 10; + } + + enum InterfaceTypeEnum : ENUM8 { + kUnspecified = 0; + kWiFi = 1; + kEthernet = 2; + kCellular = 3; + kThread = 4; + } + + enum NetworkFaultEnum : ENUM8 { + kUnspecified = 0; + kHardwareFailure = 1; + kNetworkJammed = 2; + kConnectionFailed = 3; + } + + enum RadioFaultEnum : ENUM8 { + kUnspecified = 0; + kWiFiFault = 1; + kCellularFault = 2; + kThreadFault = 3; + kNFCFault = 4; + kBLEFault = 5; + kEthernetFault = 6; + } + + struct NetworkInterface { + char_string<32> name = 0; + boolean isOperational = 1; + nullable boolean offPremiseServicesReachableIPv4 = 2; + nullable boolean offPremiseServicesReachableIPv6 = 3; + octet_string<8> hardwareAddress = 4; + octet_string IPv4Addresses[] = 5; + octet_string IPv6Addresses[] = 6; + InterfaceTypeEnum type = 7; + } + + critical event HardwareFaultChange = 0 { + HardwareFaultEnum current[] = 0; + HardwareFaultEnum previous[] = 1; + } + + critical event RadioFaultChange = 1 { + RadioFaultEnum current[] = 0; + RadioFaultEnum previous[] = 1; + } + + critical event NetworkFaultChange = 2 { + NetworkFaultEnum current[] = 0; + NetworkFaultEnum previous[] = 1; + } + + critical event BootReason = 3 { + BootReasonEnum bootReason = 0; + } + + readonly attribute NetworkInterface networkInterfaces[] = 0; + readonly attribute int16u rebootCount = 1; + readonly attribute boolean testEventTriggersEnabled = 8; + readonly attribute bitmap32 featureMap = 65532; + readonly attribute int16u clusterRevision = 65533; + + request struct TestEventTriggerRequest { + OCTET_STRING<16> enableKey = 0; + INT64U eventTrigger = 1; + } + + command access(invoke: manage) TestEventTrigger(TestEventTriggerRequest): DefaultSuccess = 0; +} + +server cluster SoftwareDiagnostics = 52 { + bitmap SoftwareDiagnosticsFeature : BITMAP32 { + kWaterMarks = 0x1; + } + + struct ThreadMetricsStruct { + int64u id = 0; + optional char_string<8> name = 1; + optional int32u stackFreeCurrent = 2; + optional int32u stackFreeMinimum = 3; + optional int32u stackSize = 4; + } + + info event SoftwareFault = 0 { + INT64U id = 0; + optional CHAR_STRING name = 1; + optional OCTET_STRING faultRecording = 2; + } + + readonly attribute ThreadMetricsStruct threadMetrics[] = 0; + readonly attribute int64u currentHeapFree = 1; + readonly attribute int64u currentHeapUsed = 2; + readonly attribute int64u currentHeapHighWatermark = 3; + readonly attribute bitmap32 featureMap = 65532; + readonly attribute int16u clusterRevision = 65533; + + command ResetWatermarks(): DefaultSuccess = 0; +} + +server cluster ThreadNetworkDiagnostics = 53 { + enum ConnectionStatusEnum : ENUM8 { + kConnected = 0; + kNotConnected = 1; + } + + enum NetworkFault : ENUM8 { + kUnspecified = 0; + kLinkDown = 1; + kHardwareFailure = 2; + kNetworkJammed = 3; + } + + enum RoutingRole : ENUM8 { + kUnspecified = 0; + kUnassigned = 1; + kSleepyEndDevice = 2; + kEndDevice = 3; + kReed = 4; + kRouter = 5; + kLeader = 6; + } + + bitmap ThreadNetworkDiagnosticsFeature : BITMAP32 { + kPacketCounts = 0x1; + kErrorCounts = 0x2; + kMLECounts = 0x4; + kMACCounts = 0x8; + } + + struct NeighborTable { + int64u extAddress = 0; + int32u age = 1; + int16u rloc16 = 2; + int32u linkFrameCounter = 3; + int32u mleFrameCounter = 4; + int8u lqi = 5; + nullable int8s averageRssi = 6; + nullable int8s lastRssi = 7; + int8u frameErrorRate = 8; + int8u messageErrorRate = 9; + boolean rxOnWhenIdle = 10; + boolean fullThreadDevice = 11; + boolean fullNetworkData = 12; + boolean isChild = 13; + } + + struct RouteTable { + int64u extAddress = 0; + int16u rloc16 = 1; + int8u routerId = 2; + int8u nextHop = 3; + int8u pathCost = 4; + int8u LQIIn = 5; + int8u LQIOut = 6; + int8u age = 7; + boolean allocated = 8; + boolean linkEstablished = 9; + } + + struct SecurityPolicy { + int16u rotationTime = 0; + int16u flags = 1; + } + + struct OperationalDatasetComponents { + boolean activeTimestampPresent = 0; + boolean pendingTimestampPresent = 1; + boolean masterKeyPresent = 2; + boolean networkNamePresent = 3; + boolean extendedPanIdPresent = 4; + boolean meshLocalPrefixPresent = 5; + boolean delayPresent = 6; + boolean panIdPresent = 7; + boolean channelPresent = 8; + boolean pskcPresent = 9; + boolean securityPolicyPresent = 10; + boolean channelMaskPresent = 11; + } + + info event ConnectionStatus = 0 { + ConnectionStatusEnum connectionStatus = 0; + } + + info event NetworkFaultChange = 1 { + NetworkFault current[] = 0; + NetworkFault previous[] = 1; + } + + readonly attribute nullable int16u channel = 0; + readonly attribute nullable RoutingRole routingRole = 1; + readonly attribute nullable char_string<16> networkName = 2; + readonly attribute nullable int16u panId = 3; + readonly attribute nullable int64u extendedPanId = 4; + readonly attribute nullable octet_string<17> meshLocalPrefix = 5; + readonly attribute int64u overrunCount = 6; + readonly attribute NeighborTable neighborTable[] = 7; + readonly attribute RouteTable routeTable[] = 8; + readonly attribute nullable int32u partitionId = 9; + readonly attribute nullable int8u weighting = 10; + readonly attribute nullable int8u dataVersion = 11; + readonly attribute nullable int8u stableDataVersion = 12; + readonly attribute nullable int8u leaderRouterId = 13; + readonly attribute int16u detachedRoleCount = 14; + readonly attribute int16u childRoleCount = 15; + readonly attribute int16u routerRoleCount = 16; + readonly attribute int16u leaderRoleCount = 17; + readonly attribute int16u attachAttemptCount = 18; + readonly attribute int16u partitionIdChangeCount = 19; + readonly attribute int16u betterPartitionAttachAttemptCount = 20; + readonly attribute int16u parentChangeCount = 21; + readonly attribute int32u txTotalCount = 22; + readonly attribute int32u txUnicastCount = 23; + readonly attribute int32u txBroadcastCount = 24; + readonly attribute int32u txAckRequestedCount = 25; + readonly attribute int32u txAckedCount = 26; + readonly attribute int32u txNoAckRequestedCount = 27; + readonly attribute int32u txDataCount = 28; + readonly attribute int32u txDataPollCount = 29; + readonly attribute int32u txBeaconCount = 30; + readonly attribute int32u txBeaconRequestCount = 31; + readonly attribute int32u txOtherCount = 32; + readonly attribute int32u txRetryCount = 33; + readonly attribute int32u txDirectMaxRetryExpiryCount = 34; + readonly attribute int32u txIndirectMaxRetryExpiryCount = 35; + readonly attribute int32u txErrCcaCount = 36; + readonly attribute int32u txErrAbortCount = 37; + readonly attribute int32u txErrBusyChannelCount = 38; + readonly attribute int32u rxTotalCount = 39; + readonly attribute int32u rxUnicastCount = 40; + readonly attribute int32u rxBroadcastCount = 41; + readonly attribute int32u rxDataCount = 42; + readonly attribute int32u rxDataPollCount = 43; + readonly attribute int32u rxBeaconCount = 44; + readonly attribute int32u rxBeaconRequestCount = 45; + readonly attribute int32u rxOtherCount = 46; + readonly attribute int32u rxAddressFilteredCount = 47; + readonly attribute int32u rxDestAddrFilteredCount = 48; + readonly attribute int32u rxDuplicatedCount = 49; + readonly attribute int32u rxErrNoFrameCount = 50; + readonly attribute int32u rxErrUnknownNeighborCount = 51; + readonly attribute int32u rxErrInvalidSrcAddrCount = 52; + readonly attribute int32u rxErrSecCount = 53; + readonly attribute int32u rxErrFcsCount = 54; + readonly attribute int32u rxErrOtherCount = 55; + readonly attribute nullable SecurityPolicy securityPolicy = 59; + readonly attribute nullable octet_string<4> channelPage0Mask = 60; + readonly attribute nullable OperationalDatasetComponents operationalDatasetComponents = 61; + readonly attribute NetworkFault activeNetworkFaultsList[] = 62; + readonly attribute bitmap32 featureMap = 65532; + readonly attribute int16u clusterRevision = 65533; + + command ResetCounts(): DefaultSuccess = 0; +} + +server cluster AdministratorCommissioning = 60 { + enum CommissioningWindowStatusEnum : ENUM8 { + kWindowNotOpen = 0; + kEnhancedWindowOpen = 1; + kBasicWindowOpen = 2; + } + + enum StatusCode : ENUM8 { + kBusy = 2; + kPAKEParameterError = 3; + kWindowNotOpen = 4; + } + + readonly attribute CommissioningWindowStatusEnum windowStatus = 0; + readonly attribute nullable fabric_idx adminFabricIndex = 1; + readonly attribute nullable int16u adminVendorId = 2; + readonly attribute bitmap32 featureMap = 65532; + readonly attribute int16u clusterRevision = 65533; + + request struct OpenCommissioningWindowRequest { + INT16U commissioningTimeout = 0; + OCTET_STRING PAKEPasscodeVerifier = 1; + INT16U discriminator = 2; + INT32U iterations = 3; + OCTET_STRING salt = 4; + } + + timed command access(invoke: administer) OpenCommissioningWindow(OpenCommissioningWindowRequest): DefaultSuccess = 0; + timed command access(invoke: administer) RevokeCommissioning(): DefaultSuccess = 2; +} + +server cluster OperationalCredentials = 62 { + enum CertificateChainTypeEnum : ENUM8 { + kDACCertificate = 1; + kPAICertificate = 2; + } + + enum NodeOperationalCertStatusEnum : ENUM8 { + kOk = 0; + kInvalidPublicKey = 1; + kInvalidNodeOpId = 2; + kInvalidNOC = 3; + kMissingCsr = 4; + kTableFull = 5; + kInvalidAdminSubject = 6; + kFabricConflict = 9; + kLabelConflict = 10; + kInvalidFabricIndex = 11; + } + + fabric_scoped struct NOCStruct { + fabric_sensitive octet_string noc = 1; + nullable fabric_sensitive octet_string icac = 2; + fabric_idx fabricIndex = 254; + } + + fabric_scoped struct FabricDescriptorStruct { + octet_string<65> rootPublicKey = 1; + vendor_id vendorID = 2; + fabric_id fabricID = 3; + node_id nodeID = 4; + char_string<32> label = 5; + fabric_idx fabricIndex = 254; + } + + readonly attribute access(read: administer) NOCStruct NOCs[] = 0; + readonly attribute FabricDescriptorStruct fabrics[] = 1; + readonly attribute int8u supportedFabrics = 2; + readonly attribute int8u commissionedFabrics = 3; + readonly attribute OCTET_STRING trustedRootCertificates[] = 4; + readonly attribute int8u currentFabricIndex = 5; + readonly attribute bitmap32 featureMap = 65532; + readonly attribute int16u clusterRevision = 65533; + + request struct AttestationRequestRequest { + OCTET_STRING attestationNonce = 0; + } + + request struct CertificateChainRequestRequest { + CertificateChainTypeEnum certificateType = 0; + } + + request struct CSRRequestRequest { + OCTET_STRING CSRNonce = 0; + optional boolean isForUpdateNOC = 1; + } + + request struct AddNOCRequest { + OCTET_STRING NOCValue = 0; + optional OCTET_STRING ICACValue = 1; + OCTET_STRING IPKValue = 2; + Int64u caseAdminSubject = 3; + VENDOR_ID adminVendorId = 4; + } + + request struct UpdateNOCRequest { + OCTET_STRING NOCValue = 0; + optional OCTET_STRING ICACValue = 1; + } + + request struct UpdateFabricLabelRequest { + CHAR_STRING<32> label = 0; + } + + request struct RemoveFabricRequest { + fabric_idx fabricIndex = 0; + } + + request struct AddTrustedRootCertificateRequest { + OCTET_STRING rootCACertificate = 0; + } + + response struct AttestationResponse = 1 { + OCTET_STRING attestationElements = 0; + OCTET_STRING attestationSignature = 1; + } + + response struct CertificateChainResponse = 3 { + OCTET_STRING certificate = 0; + } + + response struct CSRResponse = 5 { + OCTET_STRING NOCSRElements = 0; + OCTET_STRING attestationSignature = 1; + } + + response struct NOCResponse = 8 { + NodeOperationalCertStatusEnum statusCode = 0; + optional fabric_idx fabricIndex = 1; + optional CHAR_STRING debugText = 2; + } + + command access(invoke: administer) AttestationRequest(AttestationRequestRequest): AttestationResponse = 0; + command access(invoke: administer) CertificateChainRequest(CertificateChainRequestRequest): CertificateChainResponse = 2; + command access(invoke: administer) CSRRequest(CSRRequestRequest): CSRResponse = 4; + command access(invoke: administer) AddNOC(AddNOCRequest): NOCResponse = 6; + fabric command access(invoke: administer) UpdateNOC(UpdateNOCRequest): NOCResponse = 7; + fabric command access(invoke: administer) UpdateFabricLabel(UpdateFabricLabelRequest): NOCResponse = 9; + command access(invoke: administer) RemoveFabric(RemoveFabricRequest): NOCResponse = 10; + command access(invoke: administer) AddTrustedRootCertificate(AddTrustedRootCertificateRequest): DefaultSuccess = 11; +} + +server cluster GroupKeyManagement = 63 { + enum GroupKeySecurityPolicy : ENUM8 { + kTrustFirst = 0; + kCacheAndSync = 1; + } + + fabric_scoped struct GroupKeyMapStruct { + group_id groupId = 1; + int16u groupKeySetID = 2; + fabric_idx fabricIndex = 254; + } + + fabric_scoped struct GroupInfoMapStruct { + group_id groupId = 1; + endpoint_no endpoints[] = 2; + optional char_string<16> groupName = 3; + fabric_idx fabricIndex = 254; + } + + struct GroupKeySetStruct { + int16u groupKeySetID = 0; + GroupKeySecurityPolicy groupKeySecurityPolicy = 1; + nullable octet_string<16> epochKey0 = 2; + nullable epoch_us epochStartTime0 = 3; + nullable octet_string<16> epochKey1 = 4; + nullable epoch_us epochStartTime1 = 5; + nullable octet_string<16> epochKey2 = 6; + nullable epoch_us epochStartTime2 = 7; + } + + attribute access(write: manage) GroupKeyMapStruct groupKeyMap[] = 0; + readonly attribute GroupInfoMapStruct groupTable[] = 1; + readonly attribute int16u maxGroupsPerFabric = 2; + readonly attribute int16u maxGroupKeysPerFabric = 3; + readonly attribute bitmap32 featureMap = 65532; + readonly attribute int16u clusterRevision = 65533; + + request struct KeySetWriteRequest { + GroupKeySetStruct groupKeySet = 0; + } + + request struct KeySetReadRequest { + INT16U groupKeySetID = 0; + } + + request struct KeySetRemoveRequest { + INT16U groupKeySetID = 0; + } + + request struct KeySetReadAllIndicesRequest { + INT16U groupKeySetIDs[] = 0; + } + + response struct KeySetReadResponse = 2 { + GroupKeySetStruct groupKeySet = 0; + } + + response struct KeySetReadAllIndicesResponse = 5 { + INT16U groupKeySetIDs[] = 0; + } + + fabric command access(invoke: administer) KeySetWrite(KeySetWriteRequest): DefaultSuccess = 0; + fabric command access(invoke: administer) KeySetRead(KeySetReadRequest): KeySetReadResponse = 1; + fabric command access(invoke: administer) KeySetRemove(KeySetRemoveRequest): DefaultSuccess = 3; + fabric command access(invoke: administer) KeySetReadAllIndices(KeySetReadAllIndicesRequest): KeySetReadAllIndicesResponse = 4; +} + +server cluster DoorLock = 257 { + enum AlarmCodeEnum : ENUM8 { + kLockJammed = 0; + kLockFactoryReset = 1; + kLockRadioPowerCycled = 3; + kWrongCodeEntryLimit = 4; + kFrontEsceutcheonRemoved = 5; + kDoorForcedOpen = 6; + kDoorAjar = 7; + kForcedUser = 8; + } + + enum CredentialRuleEnum : ENUM8 { + kSingle = 0; + kDual = 1; + kTri = 2; + } + + enum CredentialTypeEnum : ENUM8 { + kProgrammingPIN = 0; + kPin = 1; + kRfid = 2; + kFingerprint = 3; + kFingerVein = 4; + kFace = 5; + } + + enum DataOperationTypeEnum : ENUM8 { + kAdd = 0; + kClear = 1; + kModify = 2; + } + + enum DlLockState : ENUM8 { + kNotFullyLocked = 0; + kLocked = 1; + kUnlocked = 2; + } + + enum DlLockType : ENUM8 { + kDeadBolt = 0; + kMagnetic = 1; + kOther = 2; + kMortise = 3; + kRim = 4; + kLatchBolt = 5; + kCylindricalLock = 6; + kTubularLock = 7; + kInterconnectedLock = 8; + kDeadLatch = 9; + kDoorFurniture = 10; + } + + enum DlStatus : ENUM8 { + kSuccess = 0; + kFailure = 1; + kDuplicate = 2; + kOccupied = 3; + kInvalidField = 133; + kResourceExhausted = 137; + kNotFound = 139; + } + + enum DoorLockOperationEventCode : ENUM8 { + kUnknownOrMfgSpecific = 0; + kLock = 1; + kUnlock = 2; + kLockInvalidPinOrId = 3; + kLockInvalidSchedule = 4; + kUnlockInvalidPinOrId = 5; + kUnlockInvalidSchedule = 6; + kOneTouchLock = 7; + kKeyLock = 8; + kKeyUnlock = 9; + kAutoLock = 10; + kScheduleLock = 11; + kScheduleUnlock = 12; + kManualLock = 13; + kManualUnlock = 14; + } + + enum DoorLockProgrammingEventCode : ENUM8 { + kUnknownOrMfgSpecific = 0; + kMasterCodeChanged = 1; + kPinAdded = 2; + kPinDeleted = 3; + kPinChanged = 4; + kIdAdded = 5; + kIdDeleted = 6; + } + + enum DoorLockSetPinOrIdStatus : ENUM8 { + kSuccess = 0; + kGeneralFailure = 1; + kMemoryFull = 2; + kDuplicateCodeError = 3; + } + + enum DoorLockUserStatus : ENUM8 { + kAvailable = 0; + kOccupiedEnabled = 1; + kOccupiedDisabled = 3; + kNotSupported = 255; + } + + enum DoorLockUserType : ENUM8 { + kUnrestricted = 0; + kYearDayScheduleUser = 1; + kWeekDayScheduleUser = 2; + kMasterUser = 3; + kNonAccessUser = 4; + kNotSupported = 255; + } + + enum DoorStateEnum : ENUM8 { + kDoorOpen = 0; + kDoorClosed = 1; + kDoorJammed = 2; + kDoorForcedOpen = 3; + kDoorUnspecifiedError = 4; + kDoorAjar = 5; + } + + enum LockDataTypeEnum : ENUM8 { + kUnspecified = 0; + kProgrammingCode = 1; + kUserIndex = 2; + kWeekDaySchedule = 3; + kYearDaySchedule = 4; + kHolidaySchedule = 5; + kPin = 6; + kRfid = 7; + kFingerprint = 8; + } + + enum LockOperationTypeEnum : ENUM8 { + kLock = 0; + kUnlock = 1; + kNonAccessUserEvent = 2; + kForcedUserEvent = 3; + } + + enum OperatingModeEnum : ENUM8 { + kNormal = 0; + kVacation = 1; + kPrivacy = 2; + kNoRemoteLockUnlock = 3; + kPassage = 4; + } + + enum OperationErrorEnum : ENUM8 { + kUnspecified = 0; + kInvalidCredential = 1; + kDisabledUserDenied = 2; + kRestricted = 3; + kInsufficientBattery = 4; + } + + enum OperationSourceEnum : ENUM8 { + kUnspecified = 0; + kManual = 1; + kProprietaryRemote = 2; + kKeypad = 3; + kAuto = 4; + kButton = 5; + kSchedule = 6; + kRemote = 7; + kRfid = 8; + kBiometric = 9; + } + + enum UserStatusEnum : ENUM8 { + kAvailable = 0; + kOccupiedEnabled = 1; + kOccupiedDisabled = 3; + } + + enum UserTypeEnum : ENUM8 { + kUnrestrictedUser = 0; + kYearDayScheduleUser = 1; + kWeekDayScheduleUser = 2; + kProgrammingUser = 3; + kNonAccessUser = 4; + kForcedUser = 5; + kDisposableUser = 6; + kExpiringUser = 7; + kScheduleRestrictedUser = 8; + kRemoteOnlyUser = 9; + } + + bitmap DaysMaskMap : BITMAP8 { + kSunday = 0x1; + kMonday = 0x2; + kTuesday = 0x4; + kWednesday = 0x8; + kThursday = 0x10; + kFriday = 0x20; + kSaturday = 0x40; + } + + bitmap DlCredentialRuleMask : BITMAP8 { + kSingle = 0x1; + kDual = 0x2; + kTri = 0x4; + } + + bitmap DlCredentialRulesSupport : BITMAP8 { + kSingle = 0x1; + kDual = 0x2; + kTri = 0x4; + } + + bitmap DlDefaultConfigurationRegister : BITMAP16 { + kEnableLocalProgrammingEnabled = 0x1; + kKeypadInterfaceDefaultAccessEnabled = 0x2; + kRemoteInterfaceDefaultAccessIsEnabled = 0x4; + kSoundEnabled = 0x20; + kAutoRelockTimeSet = 0x40; + kLEDSettingsSet = 0x80; + } + + bitmap DlKeypadOperationEventMask : BITMAP16 { + kUnknown = 0x1; + kLock = 0x2; + kUnlock = 0x4; + kLockInvalidPIN = 0x8; + kLockInvalidSchedule = 0x10; + kUnlockInvalidCode = 0x20; + kUnlockInvalidSchedule = 0x40; + kNonAccessUserOpEvent = 0x80; + } + + bitmap DlKeypadProgrammingEventMask : BITMAP16 { + kUnknown = 0x1; + kProgrammingPINChanged = 0x2; + kPINAdded = 0x4; + kPINCleared = 0x8; + kPINChanged = 0x10; + } + + bitmap DlLocalProgrammingFeatures : BITMAP8 { + kAddUsersCredentialsSchedulesLocally = 0x1; + kModifyUsersCredentialsSchedulesLocally = 0x2; + kClearUsersCredentialsSchedulesLocally = 0x4; + kAdjustLockSettingsLocally = 0x8; + } + + bitmap DlManualOperationEventMask : BITMAP16 { + kUnknown = 0x1; + kThumbturnLock = 0x2; + kThumbturnUnlock = 0x4; + kOneTouchLock = 0x8; + kKeyLock = 0x10; + kKeyUnlock = 0x20; + kAutoLock = 0x40; + kScheduleLock = 0x80; + kScheduleUnlock = 0x100; + kManualLock = 0x200; + kManualUnlock = 0x400; + } + + bitmap DlRFIDOperationEventMask : BITMAP16 { + kUnknown = 0x1; + kLock = 0x2; + kUnlock = 0x4; + kLockInvalidRFID = 0x8; + kLockInvalidSchedule = 0x10; + kUnlockInvalidRFID = 0x20; + kUnlockInvalidSchedule = 0x40; + } + + bitmap DlRFIDProgrammingEventMask : BITMAP16 { + kUnknown = 0x1; + kRFIDCodeAdded = 0x20; + kRFIDCodeCleared = 0x40; + } + + bitmap DlRemoteOperationEventMask : BITMAP16 { + kUnknown = 0x1; + kLock = 0x2; + kUnlock = 0x4; + kLockInvalidCode = 0x8; + kLockInvalidSchedule = 0x10; + kUnlockInvalidCode = 0x20; + kUnlockInvalidSchedule = 0x40; + } + + bitmap DlRemoteProgrammingEventMask : BITMAP16 { + kUnknown = 0x1; + kProgrammingPINChanged = 0x2; + kPINAdded = 0x4; + kPINCleared = 0x8; + kPINChanged = 0x10; + kRFIDCodeAdded = 0x20; + kRFIDCodeCleared = 0x40; + } + + bitmap DlSupportedOperatingModes : BITMAP16 { + kNormal = 0x1; + kVacation = 0x2; + kPrivacy = 0x4; + kNoRemoteLockUnlock = 0x8; + kPassage = 0x10; + } + + bitmap DoorLockDayOfWeek : BITMAP8 { + kSunday = 0x1; + kMonday = 0x2; + kTuesday = 0x4; + kWednesday = 0x8; + kThursday = 0x10; + kFriday = 0x20; + kSaturday = 0x40; + } + + bitmap DoorLockFeature : BITMAP32 { + kPinCredential = 0x1; + kRfidCredential = 0x2; + kFingerCredentials = 0x4; + kLogging = 0x8; + kWeekDayAccessSchedules = 0x10; + kDoorPositionSensor = 0x20; + kFaceCredentials = 0x40; + kCredentialsOverTheAirAccess = 0x80; + kUser = 0x100; + kNotification = 0x200; + kYearDayAccessSchedules = 0x400; + kHolidaySchedules = 0x800; + } + + struct CredentialStruct { + CredentialTypeEnum credentialType = 0; + int16u credentialIndex = 1; + } + + critical event DoorLockAlarm = 0 { + AlarmCodeEnum alarmCode = 0; + } + + critical event DoorStateChange = 1 { + DoorStateEnum doorState = 0; + } + + critical event LockOperation = 2 { + LockOperationTypeEnum lockOperationType = 0; + OperationSourceEnum operationSource = 1; + nullable INT16U userIndex = 2; + nullable fabric_idx fabricIndex = 3; + nullable NODE_ID sourceNode = 4; + optional nullable CredentialStruct credentials[] = 5; + } + + critical event LockOperationError = 3 { + LockOperationTypeEnum lockOperationType = 0; + OperationSourceEnum operationSource = 1; + OperationErrorEnum operationError = 2; + nullable INT16U userIndex = 3; + nullable fabric_idx fabricIndex = 4; + nullable NODE_ID sourceNode = 5; + optional nullable CredentialStruct credentials[] = 6; + } + + info event LockUserChange = 4 { + LockDataTypeEnum lockDataType = 0; + DataOperationTypeEnum dataOperationType = 1; + OperationSourceEnum operationSource = 2; + nullable INT16U userIndex = 3; + nullable fabric_idx fabricIndex = 4; + nullable NODE_ID sourceNode = 5; + nullable INT16U dataIndex = 6; + } + + readonly attribute nullable DlLockState lockState = 0; + readonly attribute DlLockType lockType = 1; + readonly attribute boolean actuatorEnabled = 2; + readonly attribute int16u numberOfTotalUsersSupported = 17; + readonly attribute DlCredentialRuleMask credentialRulesSupport = 27; + attribute access(write: manage) int32u autoRelockTime = 35; + attribute access(write: manage) OperatingModeEnum operatingMode = 37; + readonly attribute DlSupportedOperatingModes supportedOperatingModes = 38; + attribute access(write: administer) int16u expiringUserTimeout = 53; + readonly attribute command_id generatedCommandList[] = 65528; + readonly attribute command_id acceptedCommandList[] = 65529; + readonly attribute attrib_id attributeList[] = 65531; + readonly attribute bitmap32 featureMap = 65532; + readonly attribute int16u clusterRevision = 65533; + + request struct LockDoorRequest { + optional OCTET_STRING PINCode = 0; + } + + request struct UnlockDoorRequest { + optional OCTET_STRING PINCode = 0; + } + + request struct SetUserRequest { + DataOperationTypeEnum operationType = 0; + INT16U userIndex = 1; + nullable CHAR_STRING userName = 2; + nullable INT32U userUniqueID = 3; + nullable UserStatusEnum userStatus = 4; + nullable UserTypeEnum userType = 5; + nullable CredentialRuleEnum credentialRule = 6; + } + + request struct GetUserRequest { + INT16U userIndex = 0; + } + + request struct ClearUserRequest { + INT16U userIndex = 0; + } + + request struct SetCredentialRequest { + DataOperationTypeEnum operationType = 0; + CredentialStruct credential = 1; + LONG_OCTET_STRING credentialData = 2; + nullable INT16U userIndex = 3; + nullable UserStatusEnum userStatus = 4; + nullable UserTypeEnum userType = 5; + } + + request struct GetCredentialStatusRequest { + CredentialStruct credential = 0; + } + + response struct GetUserResponse = 28 { + INT16U userIndex = 0; + nullable CHAR_STRING userName = 1; + nullable INT32U userUniqueID = 2; + nullable UserStatusEnum userStatus = 3; + nullable UserTypeEnum userType = 4; + nullable CredentialRuleEnum credentialRule = 5; + nullable CredentialStruct credentials[] = 6; + nullable fabric_idx creatorFabricIndex = 7; + nullable fabric_idx lastModifiedFabricIndex = 8; + nullable INT16U nextUserIndex = 9; + } + + response struct SetCredentialResponse = 35 { + DlStatus status = 0; + nullable INT16U userIndex = 1; + nullable INT16U nextCredentialIndex = 2; + } + + response struct GetCredentialStatusResponse = 37 { + boolean credentialExists = 0; + nullable INT16U userIndex = 1; + nullable fabric_idx creatorFabricIndex = 2; + nullable fabric_idx lastModifiedFabricIndex = 3; + nullable INT16U nextCredentialIndex = 4; + } + + timed command LockDoor(LockDoorRequest): DefaultSuccess = 0; + timed command UnlockDoor(UnlockDoorRequest): DefaultSuccess = 1; + timed command access(invoke: administer) SetUser(SetUserRequest): DefaultSuccess = 26; + command access(invoke: administer) GetUser(GetUserRequest): GetUserResponse = 27; + timed command access(invoke: administer) ClearUser(ClearUserRequest): DefaultSuccess = 29; + timed command access(invoke: administer) SetCredential(SetCredentialRequest): SetCredentialResponse = 34; + command access(invoke: administer) GetCredentialStatus(GetCredentialStatusRequest): GetCredentialStatusResponse = 36; +} + +endpoint 0 { + device type rootdevice = 22, version 1; + + server cluster Descriptor { + callback attribute deviceTypeList; + callback attribute serverList; + callback attribute clientList; + callback attribute partsList; + ram attribute featureMap; + callback attribute clusterRevision default = 1; + } + + server cluster AccessControl { + callback attribute acl; + callback attribute subjectsPerAccessControlEntry default = 4; + callback attribute targetsPerAccessControlEntry default = 3; + callback attribute accessControlEntriesPerFabric default = 3; + callback attribute attributeList; + ram attribute featureMap; + ram attribute clusterRevision default = 1; + } + + server cluster BasicInformation { + callback attribute dataModelRevision default = 10; + callback attribute vendorName; + callback attribute vendorID; + callback attribute productName; + callback attribute productID; + persist attribute nodeLabel; + callback attribute location default = "XX"; + callback attribute hardwareVersion; + callback attribute hardwareVersionString; + callback attribute softwareVersion; + callback attribute softwareVersionString; + callback attribute capabilityMinima; + ram attribute featureMap; + ram attribute clusterRevision default = 1; + } + + server cluster GeneralCommissioning { + ram attribute breadcrumb; + callback attribute basicCommissioningInfo; + callback attribute regulatoryConfig; + callback attribute locationCapability; + callback attribute supportsConcurrentConnection default = 1; + ram attribute featureMap; + ram attribute clusterRevision default = 1; + } + + server cluster NetworkCommissioning { + ram attribute maxNetworks; + callback attribute networks; + ram attribute scanMaxTimeSeconds; + ram attribute connectMaxTimeSeconds; + ram attribute interfaceEnabled; + ram attribute lastNetworkingStatus; + ram attribute lastNetworkID; + ram attribute lastConnectErrorValue; + ram attribute featureMap default = 2; + ram attribute clusterRevision default = 1; + } + + server cluster GeneralDiagnostics { + callback attribute networkInterfaces; + callback attribute rebootCount; + callback attribute testEventTriggersEnabled; + ram attribute featureMap; + ram attribute clusterRevision default = 1; + } + + server cluster SoftwareDiagnostics { + callback attribute threadMetrics; + callback attribute currentHeapFree; + callback attribute currentHeapUsed; + callback attribute currentHeapHighWatermark; + ram attribute featureMap default = 1; + ram attribute clusterRevision default = 1; + } + + server cluster ThreadNetworkDiagnostics { + callback attribute channel; + callback attribute routingRole; + callback attribute networkName; + callback attribute panId; + callback attribute extendedPanId; + callback attribute meshLocalPrefix; + callback attribute overrunCount; + callback attribute neighborTable; + callback attribute routeTable; + callback attribute partitionId; + callback attribute weighting; + callback attribute dataVersion; + callback attribute stableDataVersion; + callback attribute leaderRouterId; + callback attribute detachedRoleCount; + callback attribute childRoleCount; + callback attribute routerRoleCount; + callback attribute leaderRoleCount; + callback attribute attachAttemptCount; + callback attribute partitionIdChangeCount; + callback attribute betterPartitionAttachAttemptCount; + callback attribute parentChangeCount; + callback attribute txTotalCount; + callback attribute txUnicastCount; + callback attribute txBroadcastCount; + callback attribute txAckRequestedCount; + callback attribute txAckedCount; + callback attribute txNoAckRequestedCount; + callback attribute txDataCount; + callback attribute txDataPollCount; + callback attribute txBeaconCount; + callback attribute txBeaconRequestCount; + callback attribute txOtherCount; + callback attribute txRetryCount; + callback attribute txDirectMaxRetryExpiryCount; + callback attribute txIndirectMaxRetryExpiryCount; + callback attribute txErrCcaCount; + callback attribute txErrAbortCount; + callback attribute txErrBusyChannelCount; + callback attribute rxTotalCount; + callback attribute rxUnicastCount; + callback attribute rxBroadcastCount; + callback attribute rxDataCount; + callback attribute rxDataPollCount; + callback attribute rxBeaconCount; + callback attribute rxBeaconRequestCount; + callback attribute rxOtherCount; + callback attribute rxAddressFilteredCount; + callback attribute rxDestAddrFilteredCount; + callback attribute rxDuplicatedCount; + callback attribute rxErrNoFrameCount; + callback attribute rxErrUnknownNeighborCount; + callback attribute rxErrInvalidSrcAddrCount; + callback attribute rxErrSecCount; + callback attribute rxErrFcsCount; + callback attribute rxErrOtherCount; + callback attribute securityPolicy; + callback attribute channelPage0Mask; + callback attribute operationalDatasetComponents; + callback attribute activeNetworkFaultsList; + ram attribute featureMap default = 0x000F; + ram attribute clusterRevision default = 1; + } + + server cluster AdministratorCommissioning { + callback attribute windowStatus; + callback attribute adminFabricIndex default = 1; + callback attribute adminVendorId; + ram attribute featureMap; + ram attribute clusterRevision default = 1; + } + + server cluster OperationalCredentials { + callback attribute NOCs; + callback attribute fabrics; + callback attribute supportedFabrics; + callback attribute commissionedFabrics; + callback attribute trustedRootCertificates; + callback attribute currentFabricIndex; + ram attribute featureMap; + ram attribute clusterRevision default = 1; + } + + server cluster GroupKeyManagement { + callback attribute groupKeyMap; + callback attribute groupTable; + callback attribute maxGroupsPerFabric; + callback attribute maxGroupKeysPerFabric; + ram attribute featureMap; + ram attribute clusterRevision default = 1; + } +} +endpoint 1 { + device type anonymousEndpointType = 10, version 1; + + server cluster Identify { + ram attribute identifyTime; + ram attribute identifyType; + callback attribute generatedCommandList; + callback attribute acceptedCommandList; + callback attribute attributeList; + ram attribute featureMap; + ram attribute clusterRevision default = 4; + } + + server cluster Descriptor { + callback attribute deviceTypeList; + callback attribute serverList; + callback attribute clientList; + callback attribute partsList; + callback attribute generatedCommandList; + callback attribute acceptedCommandList; + callback attribute attributeList; + ram attribute featureMap; + ram attribute clusterRevision default = 1; + } + + server cluster DoorLock { + ram attribute lockState; + ram attribute lockType; + ram attribute actuatorEnabled; + ram attribute numberOfTotalUsersSupported; + ram attribute credentialRulesSupport default = 1; + ram attribute autoRelockTime; + ram attribute operatingMode; + ram attribute supportedOperatingModes default = 0xFFF6; + ram attribute expiringUserTimeout default = 1440; + callback attribute generatedCommandList; + callback attribute acceptedCommandList; + callback attribute attributeList; + ram attribute featureMap default = 0x1000; + ram attribute clusterRevision default = 6; + } +} + + diff --git a/examples/lock-app/nxp/zap/lock-app.zap b/examples/lock-app/nxp/zap/lock-app.zap new file mode 100644 index 00000000000000..04cafa535bd076 --- /dev/null +++ b/examples/lock-app/nxp/zap/lock-app.zap @@ -0,0 +1,6725 @@ +{ + "featureLevel": 89, + "creator": "zap", + "keyValuePairs": [ + { + "key": "commandDiscovery", + "value": "1" + }, + { + "key": "defaultResponsePolicy", + "value": "always" + }, + { + "key": "manufacturerCodes", + "value": "0x1002" + } + ], + "package": [ + { + "pathRelativity": "relativeToZap", + "path": "../../../../src/app/zap-templates/zcl/zcl.json", + "type": "zcl-properties", + "category": "matter", + "version": 1, + "description": "Matter SDK ZCL data" + }, + { + "pathRelativity": "relativeToZap", + "path": "../../../../src/app/zap-templates/app-templates.json", + "type": "gen-templates-json", + "version": "chip-v1" + } + ], + "endpointTypes": [ + { + "name": "MA-rootdevice", + "deviceTypeName": "MA-rootdevice", + "deviceTypeCode": 22, + "deviceTypeProfileId": 259, + "clusters": [ + { + "name": "Identify", + "code": 3, + "mfgCode": null, + "define": "IDENTIFY_CLUSTER", + "side": "client", + "enabled": 0, + "commands": [ + { + "name": "Identify", + "code": 0, + "mfgCode": null, + "source": "client", + "incoming": 1, + "outgoing": 0 + } + ], + "attributes": [ + { + "name": "ClusterRevision", + "code": 65533, + "mfgCode": null, + "side": "client", + "type": "int16u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "4", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + } + ] + }, + { + "name": "Identify", + "code": 3, + "mfgCode": null, + "define": "IDENTIFY_CLUSTER", + "side": "server", + "enabled": 0, + "attributes": [ + { + "name": "IdentifyTime", + "code": 0, + "mfgCode": null, + "side": "server", + "type": "int16u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0x0000", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "ClusterRevision", + "code": 65533, + "mfgCode": null, + "side": "server", + "type": "int16u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "4", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + } + ] + }, + { + "name": "Groups", + "code": 4, + "mfgCode": null, + "define": "GROUPS_CLUSTER", + "side": "client", + "enabled": 0, + "commands": [ + { + "name": "AddGroup", + "code": 0, + "mfgCode": null, + "source": "client", + "incoming": 1, + "outgoing": 0 + }, + { + "name": "ViewGroup", + "code": 1, + "mfgCode": null, + "source": "client", + "incoming": 1, + "outgoing": 0 + }, + { + "name": "GetGroupMembership", + "code": 2, + "mfgCode": null, + "source": "client", + "incoming": 1, + "outgoing": 0 + }, + { + "name": "RemoveGroup", + "code": 3, + "mfgCode": null, + "source": "client", + "incoming": 1, + "outgoing": 0 + }, + { + "name": "RemoveAllGroups", + "code": 4, + "mfgCode": null, + "source": "client", + "incoming": 1, + "outgoing": 0 + }, + { + "name": "AddGroupIfIdentifying", + "code": 5, + "mfgCode": null, + "source": "client", + "incoming": 1, + "outgoing": 0 + } + ], + "attributes": [ + { + "name": "ClusterRevision", + "code": 65533, + "mfgCode": null, + "side": "client", + "type": "int16u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "4", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + } + ] + }, + { + "name": "Groups", + "code": 4, + "mfgCode": null, + "define": "GROUPS_CLUSTER", + "side": "server", + "enabled": 0, + "commands": [ + { + "name": "AddGroupResponse", + "code": 0, + "mfgCode": null, + "source": "server", + "incoming": 0, + "outgoing": 1 + }, + { + "name": "ViewGroupResponse", + "code": 1, + "mfgCode": null, + "source": "server", + "incoming": 0, + "outgoing": 1 + }, + { + "name": "GetGroupMembershipResponse", + "code": 2, + "mfgCode": null, + "source": "server", + "incoming": 0, + "outgoing": 1 + }, + { + "name": "RemoveGroupResponse", + "code": 3, + "mfgCode": null, + "source": "server", + "incoming": 0, + "outgoing": 1 + } + ], + "attributes": [ + { + "name": "NameSupport", + "code": 0, + "mfgCode": null, + "side": "server", + "type": "bitmap8", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "FeatureMap", + "code": 65532, + "mfgCode": null, + "side": "server", + "type": "bitmap32", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "ClusterRevision", + "code": 65533, + "mfgCode": null, + "side": "server", + "type": "int16u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "4", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + } + ] + }, + { + "name": "Scenes", + "code": 5, + "mfgCode": null, + "define": "SCENES_CLUSTER", + "side": "client", + "enabled": 0, + "commands": [ + { + "name": "AddScene", + "code": 0, + "mfgCode": null, + "source": "client", + "incoming": 1, + "outgoing": 0 + }, + { + "name": "ViewScene", + "code": 1, + "mfgCode": null, + "source": "client", + "incoming": 1, + "outgoing": 0 + }, + { + "name": "RemoveScene", + "code": 2, + "mfgCode": null, + "source": "client", + "incoming": 1, + "outgoing": 0 + }, + { + "name": "RemoveAllScenes", + "code": 3, + "mfgCode": null, + "source": "client", + "incoming": 1, + "outgoing": 0 + }, + { + "name": "StoreScene", + "code": 4, + "mfgCode": null, + "source": "client", + "incoming": 1, + "outgoing": 0 + }, + { + "name": "RecallScene", + "code": 5, + "mfgCode": null, + "source": "client", + "incoming": 1, + "outgoing": 0 + }, + { + "name": "GetSceneMembership", + "code": 6, + "mfgCode": null, + "source": "client", + "incoming": 1, + "outgoing": 0 + } + ], + "attributes": [ + { + "name": "ClusterRevision", + "code": 65533, + "mfgCode": null, + "side": "client", + "type": "int16u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "4", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + } + ] + }, + { + "name": "Scenes", + "code": 5, + "mfgCode": null, + "define": "SCENES_CLUSTER", + "side": "server", + "enabled": 0, + "commands": [ + { + "name": "AddSceneResponse", + "code": 0, + "mfgCode": null, + "source": "server", + "incoming": 0, + "outgoing": 1 + }, + { + "name": "ViewSceneResponse", + "code": 1, + "mfgCode": null, + "source": "server", + "incoming": 0, + "outgoing": 1 + }, + { + "name": "RemoveSceneResponse", + "code": 2, + "mfgCode": null, + "source": "server", + "incoming": 0, + "outgoing": 1 + }, + { + "name": "RemoveAllScenesResponse", + "code": 3, + "mfgCode": null, + "source": "server", + "incoming": 0, + "outgoing": 1 + }, + { + "name": "StoreSceneResponse", + "code": 4, + "mfgCode": null, + "source": "server", + "incoming": 0, + "outgoing": 1 + }, + { + "name": "GetSceneMembershipResponse", + "code": 6, + "mfgCode": null, + "source": "server", + "incoming": 0, + "outgoing": 1 + } + ], + "attributes": [ + { + "name": "SceneCount", + "code": 0, + "mfgCode": null, + "side": "server", + "type": "int8u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0x00", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "CurrentScene", + "code": 1, + "mfgCode": null, + "side": "server", + "type": "int8u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0x00", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "CurrentGroup", + "code": 2, + "mfgCode": null, + "side": "server", + "type": "group_id", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0x0000", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "SceneValid", + "code": 3, + "mfgCode": null, + "side": "server", + "type": "boolean", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0x00", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "NameSupport", + "code": 4, + "mfgCode": null, + "side": "server", + "type": "bitmap8", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "ClusterRevision", + "code": 65533, + "mfgCode": null, + "side": "server", + "type": "int16u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "4", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + } + ] + }, + { + "name": "On/Off", + "code": 6, + "mfgCode": null, + "define": "ON_OFF_CLUSTER", + "side": "client", + "enabled": 0, + "commands": [ + { + "name": "Off", + "code": 0, + "mfgCode": null, + "source": "client", + "incoming": 1, + "outgoing": 0 + }, + { + "name": "On", + "code": 1, + "mfgCode": null, + "source": "client", + "incoming": 1, + "outgoing": 0 + }, + { + "name": "Toggle", + "code": 2, + "mfgCode": null, + "source": "client", + "incoming": 1, + "outgoing": 0 + } + ], + "attributes": [ + { + "name": "ClusterRevision", + "code": 65533, + "mfgCode": null, + "side": "client", + "type": "int16u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "4", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + } + ] + }, + { + "name": "On/Off", + "code": 6, + "mfgCode": null, + "define": "ON_OFF_CLUSTER", + "side": "server", + "enabled": 0, + "attributes": [ + { + "name": "OnOff", + "code": 0, + "mfgCode": null, + "side": "server", + "type": "boolean", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0x00", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "ClusterRevision", + "code": 65533, + "mfgCode": null, + "side": "server", + "type": "int16u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "4", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + } + ] + }, + { + "name": "On/off Switch Configuration", + "code": 7, + "mfgCode": null, + "define": "ON_OFF_SWITCH_CONFIGURATION_CLUSTER", + "side": "client", + "enabled": 0, + "attributes": [ + { + "name": "ClusterRevision", + "code": 65533, + "mfgCode": null, + "side": "client", + "type": "int16u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "1", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + } + ] + }, + { + "name": "On/off Switch Configuration", + "code": 7, + "mfgCode": null, + "define": "ON_OFF_SWITCH_CONFIGURATION_CLUSTER", + "side": "server", + "enabled": 0, + "attributes": [ + { + "name": "switch type", + "code": 0, + "mfgCode": null, + "side": "server", + "type": "enum8", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "switch actions", + "code": 16, + "mfgCode": null, + "side": "server", + "type": "enum8", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0x00", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "ClusterRevision", + "code": 65533, + "mfgCode": null, + "side": "server", + "type": "int16u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "1", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + } + ] + }, + { + "name": "Level Control", + "code": 8, + "mfgCode": null, + "define": "LEVEL_CONTROL_CLUSTER", + "side": "client", + "enabled": 0, + "commands": [ + { + "name": "MoveToLevel", + "code": 0, + "mfgCode": null, + "source": "client", + "incoming": 1, + "outgoing": 0 + }, + { + "name": "Move", + "code": 1, + "mfgCode": null, + "source": "client", + "incoming": 1, + "outgoing": 0 + }, + { + "name": "Step", + "code": 2, + "mfgCode": null, + "source": "client", + "incoming": 1, + "outgoing": 0 + }, + { + "name": "Stop", + "code": 3, + "mfgCode": null, + "source": "client", + "incoming": 1, + "outgoing": 0 + }, + { + "name": "MoveToLevelWithOnOff", + "code": 4, + "mfgCode": null, + "source": "client", + "incoming": 1, + "outgoing": 0 + }, + { + "name": "MoveWithOnOff", + "code": 5, + "mfgCode": null, + "source": "client", + "incoming": 1, + "outgoing": 0 + }, + { + "name": "StepWithOnOff", + "code": 6, + "mfgCode": null, + "source": "client", + "incoming": 1, + "outgoing": 0 + }, + { + "name": "StopWithOnOff", + "code": 7, + "mfgCode": null, + "source": "client", + "incoming": 1, + "outgoing": 0 + } + ], + "attributes": [ + { + "name": "ClusterRevision", + "code": 65533, + "mfgCode": null, + "side": "client", + "type": "int16u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "5", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + } + ] + }, + { + "name": "Level Control", + "code": 8, + "mfgCode": null, + "define": "LEVEL_CONTROL_CLUSTER", + "side": "server", + "enabled": 0, + "attributes": [ + { + "name": "CurrentLevel", + "code": 0, + "mfgCode": null, + "side": "server", + "type": "int8u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0x00", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "ClusterRevision", + "code": 65533, + "mfgCode": null, + "side": "server", + "type": "int16u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "5", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + } + ] + }, + { + "name": "Descriptor", + "code": 29, + "mfgCode": null, + "define": "DESCRIPTOR_CLUSTER", + "side": "client", + "enabled": 0, + "attributes": [ + { + "name": "ClusterRevision", + "code": 65533, + "mfgCode": null, + "side": "client", + "type": "int16u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "1", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + } + ] + }, + { + "name": "Descriptor", + "code": 29, + "mfgCode": null, + "define": "DESCRIPTOR_CLUSTER", + "side": "server", + "enabled": 1, + "attributes": [ + { + "name": "DeviceTypeList", + "code": 0, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "ServerList", + "code": 1, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "ClientList", + "code": 2, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "PartsList", + "code": 3, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "FeatureMap", + "code": 65532, + "mfgCode": null, + "side": "server", + "type": "bitmap32", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "ClusterRevision", + "code": 65533, + "mfgCode": null, + "side": "server", + "type": "int16u", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "1", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + } + ] + }, + { + "name": "Access Control", + "code": 31, + "mfgCode": null, + "define": "ACCESS_CONTROL_CLUSTER", + "side": "client", + "enabled": 0, + "attributes": [ + { + "name": "ClusterRevision", + "code": 65533, + "mfgCode": null, + "side": "client", + "type": "int16u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "1", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + } + ] + }, + { + "name": "Access Control", + "code": 31, + "mfgCode": null, + "define": "ACCESS_CONTROL_CLUSTER", + "side": "server", + "enabled": 1, + "attributes": [ + { + "name": "ACL", + "code": 0, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "Extension", + "code": 1, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 0, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "SubjectsPerAccessControlEntry", + "code": 2, + "mfgCode": null, + "side": "server", + "type": "int16u", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "4", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "TargetsPerAccessControlEntry", + "code": 3, + "mfgCode": null, + "side": "server", + "type": "int16u", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "3", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "AccessControlEntriesPerFabric", + "code": 4, + "mfgCode": null, + "side": "server", + "type": "int16u", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "3", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "AttributeList", + "code": 65531, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "FeatureMap", + "code": 65532, + "mfgCode": null, + "side": "server", + "type": "bitmap32", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "ClusterRevision", + "code": 65533, + "mfgCode": null, + "side": "server", + "type": "int16u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "1", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + } + ], + "events": [ + { + "name": "AccessControlEntryChanged", + "code": 0, + "mfgCode": null, + "side": "server", + "included": 1 + }, + { + "name": "AccessControlExtensionChanged", + "code": 1, + "mfgCode": null, + "side": "server", + "included": 1 + } + ] + }, + { + "name": "Basic Information", + "code": 40, + "mfgCode": null, + "define": "BASIC_INFORMATION_CLUSTER", + "side": "client", + "enabled": 0, + "attributes": [ + { + "name": "ClusterRevision", + "code": 65533, + "mfgCode": null, + "side": "client", + "type": "int16u", + "included": 1, + "storageOption": "RAM", + "singleton": 1, + "bounded": 0, + "defaultValue": "1", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + } + ] + }, + { + "name": "Basic Information", + "code": 40, + "mfgCode": null, + "define": "BASIC_INFORMATION_CLUSTER", + "side": "server", + "enabled": 1, + "attributes": [ + { + "name": "DataModelRevision", + "code": 0, + "mfgCode": null, + "side": "server", + "type": "int16u", + "included": 1, + "storageOption": "External", + "singleton": 1, + "bounded": 0, + "defaultValue": "10", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "VendorName", + "code": 1, + "mfgCode": null, + "side": "server", + "type": "char_string", + "included": 1, + "storageOption": "External", + "singleton": 1, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "VendorID", + "code": 2, + "mfgCode": null, + "side": "server", + "type": "vendor_id", + "included": 1, + "storageOption": "External", + "singleton": 1, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "ProductName", + "code": 3, + "mfgCode": null, + "side": "server", + "type": "char_string", + "included": 1, + "storageOption": "External", + "singleton": 1, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "ProductID", + "code": 4, + "mfgCode": null, + "side": "server", + "type": "int16u", + "included": 1, + "storageOption": "External", + "singleton": 1, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "NodeLabel", + "code": 5, + "mfgCode": null, + "side": "server", + "type": "char_string", + "included": 1, + "storageOption": "NVM", + "singleton": 1, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "Location", + "code": 6, + "mfgCode": null, + "side": "server", + "type": "char_string", + "included": 1, + "storageOption": "External", + "singleton": 1, + "bounded": 0, + "defaultValue": "XX", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "HardwareVersion", + "code": 7, + "mfgCode": null, + "side": "server", + "type": "int16u", + "included": 1, + "storageOption": "External", + "singleton": 1, + "bounded": 0, + "defaultValue": "0", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "HardwareVersionString", + "code": 8, + "mfgCode": null, + "side": "server", + "type": "char_string", + "included": 1, + "storageOption": "External", + "singleton": 1, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "SoftwareVersion", + "code": 9, + "mfgCode": null, + "side": "server", + "type": "int32u", + "included": 1, + "storageOption": "External", + "singleton": 1, + "bounded": 0, + "defaultValue": "0", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "SoftwareVersionString", + "code": 10, + "mfgCode": null, + "side": "server", + "type": "char_string", + "included": 1, + "storageOption": "External", + "singleton": 1, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "ManufacturingDate", + "code": 11, + "mfgCode": null, + "side": "server", + "type": "char_string", + "included": 0, + "storageOption": "External", + "singleton": 1, + "bounded": 0, + "defaultValue": "20210614123456ZZ", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "PartNumber", + "code": 12, + "mfgCode": null, + "side": "server", + "type": "char_string", + "included": 0, + "storageOption": "External", + "singleton": 1, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "ProductURL", + "code": 13, + "mfgCode": null, + "side": "server", + "type": "long_char_string", + "included": 0, + "storageOption": "External", + "singleton": 1, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "ProductLabel", + "code": 14, + "mfgCode": null, + "side": "server", + "type": "char_string", + "included": 0, + "storageOption": "External", + "singleton": 1, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "SerialNumber", + "code": 15, + "mfgCode": null, + "side": "server", + "type": "char_string", + "included": 0, + "storageOption": "External", + "singleton": 1, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "LocalConfigDisabled", + "code": 16, + "mfgCode": null, + "side": "server", + "type": "boolean", + "included": 0, + "storageOption": "NVM", + "singleton": 1, + "bounded": 0, + "defaultValue": "0", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "Reachable", + "code": 17, + "mfgCode": null, + "side": "server", + "type": "boolean", + "included": 0, + "storageOption": "RAM", + "singleton": 1, + "bounded": 0, + "defaultValue": "1", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "UniqueID", + "code": 18, + "mfgCode": null, + "side": "server", + "type": "char_string", + "included": 0, + "storageOption": "External", + "singleton": 1, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "CapabilityMinima", + "code": 19, + "mfgCode": null, + "side": "server", + "type": "CapabilityMinimaStruct", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "FeatureMap", + "code": 65532, + "mfgCode": null, + "side": "server", + "type": "bitmap32", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "ClusterRevision", + "code": 65533, + "mfgCode": null, + "side": "server", + "type": "int16u", + "included": 1, + "storageOption": "RAM", + "singleton": 1, + "bounded": 0, + "defaultValue": "1", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + } + ], + "events": [ + { + "name": "StartUp", + "code": 0, + "mfgCode": null, + "side": "server", + "included": 1 + }, + { + "name": "ShutDown", + "code": 1, + "mfgCode": null, + "side": "server", + "included": 1 + }, + { + "name": "Leave", + "code": 2, + "mfgCode": null, + "side": "server", + "included": 1 + } + ] + }, + { + "name": "OTA Software Update Provider", + "code": 41, + "mfgCode": null, + "define": "OTA_SOFTWARE_UPDATE_PROVIDER_CLUSTER", + "side": "client", + "enabled": 0, + "commands": [ + { + "name": "QueryImage", + "code": 0, + "mfgCode": null, + "source": "client", + "incoming": 0, + "outgoing": 1 + }, + { + "name": "ApplyUpdateRequest", + "code": 2, + "mfgCode": null, + "source": "client", + "incoming": 0, + "outgoing": 1 + }, + { + "name": "NotifyUpdateApplied", + "code": 4, + "mfgCode": null, + "source": "client", + "incoming": 0, + "outgoing": 1 + } + ], + "attributes": [ + { + "name": "ClusterRevision", + "code": 65533, + "mfgCode": null, + "side": "client", + "type": "int16u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "1", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + } + ] + }, + { + "name": "OTA Software Update Provider", + "code": 41, + "mfgCode": null, + "define": "OTA_SOFTWARE_UPDATE_PROVIDER_CLUSTER", + "side": "server", + "enabled": 0, + "commands": [ + { + "name": "QueryImageResponse", + "code": 1, + "mfgCode": null, + "source": "server", + "incoming": 1, + "outgoing": 0 + }, + { + "name": "ApplyUpdateResponse", + "code": 3, + "mfgCode": null, + "source": "server", + "incoming": 1, + "outgoing": 0 + } + ], + "attributes": [ + { + "name": "AttributeList", + "code": 65531, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 0, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "FeatureMap", + "code": 65532, + "mfgCode": null, + "side": "server", + "type": "bitmap32", + "included": 0, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "ClusterRevision", + "code": 65533, + "mfgCode": null, + "side": "server", + "type": "int16u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "1", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + } + ] + }, + { + "name": "OTA Software Update Requestor", + "code": 42, + "mfgCode": null, + "define": "OTA_SOFTWARE_UPDATE_REQUESTOR_CLUSTER", + "side": "client", + "enabled": 0, + "commands": [ + { + "name": "AnnounceOTAProvider", + "code": 0, + "mfgCode": null, + "source": "client", + "incoming": 1, + "outgoing": 0 + } + ], + "attributes": [ + { + "name": "ClusterRevision", + "code": 65533, + "mfgCode": null, + "side": "client", + "type": "int16u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "1", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + } + ] + }, + { + "name": "OTA Software Update Requestor", + "code": 42, + "mfgCode": null, + "define": "OTA_SOFTWARE_UPDATE_REQUESTOR_CLUSTER", + "side": "server", + "enabled": 0, + "attributes": [ + { + "name": "DefaultOTAProviders", + "code": 0, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "0", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "UpdatePossible", + "code": 1, + "mfgCode": null, + "side": "server", + "type": "boolean", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "1", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "UpdateState", + "code": 2, + "mfgCode": null, + "side": "server", + "type": "OTAUpdateStateEnum", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "UpdateStateProgress", + "code": 3, + "mfgCode": null, + "side": "server", + "type": "int8u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "AttributeList", + "code": 65531, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 0, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "FeatureMap", + "code": 65532, + "mfgCode": null, + "side": "server", + "type": "bitmap32", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "ClusterRevision", + "code": 65533, + "mfgCode": null, + "side": "server", + "type": "int16u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "1", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + } + ], + "events": [ + { + "name": "StateTransition", + "code": 0, + "mfgCode": null, + "side": "server", + "included": 1 + }, + { + "name": "VersionApplied", + "code": 1, + "mfgCode": null, + "side": "server", + "included": 1 + }, + { + "name": "DownloadError", + "code": 2, + "mfgCode": null, + "side": "server", + "included": 1 + } + ] + }, + { + "name": "Localization Configuration", + "code": 43, + "mfgCode": null, + "define": "LOCALIZATION_CONFIGURATION_CLUSTER", + "side": "client", + "enabled": 0 + }, + { + "name": "Localization Configuration", + "code": 43, + "mfgCode": null, + "define": "LOCALIZATION_CONFIGURATION_CLUSTER", + "side": "server", + "enabled": 0, + "attributes": [ + { + "name": "ActiveLocale", + "code": 0, + "mfgCode": null, + "side": "server", + "type": "char_string", + "included": 1, + "storageOption": "NVM", + "singleton": 0, + "bounded": 0, + "defaultValue": "en-US", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "SupportedLocales", + "code": 1, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "FeatureMap", + "code": 65532, + "mfgCode": null, + "side": "server", + "type": "bitmap32", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "ClusterRevision", + "code": 65533, + "mfgCode": null, + "side": "server", + "type": "int16u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "1", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + } + ] + }, + { + "name": "Time Format Localization", + "code": 44, + "mfgCode": null, + "define": "TIME_FORMAT_LOCALIZATION_CLUSTER", + "side": "client", + "enabled": 0 + }, + { + "name": "Time Format Localization", + "code": 44, + "mfgCode": null, + "define": "TIME_FORMAT_LOCALIZATION_CLUSTER", + "side": "server", + "enabled": 0, + "attributes": [ + { + "name": "HourFormat", + "code": 0, + "mfgCode": null, + "side": "server", + "type": "HourFormat", + "included": 1, + "storageOption": "NVM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "ActiveCalendarType", + "code": 1, + "mfgCode": null, + "side": "server", + "type": "CalendarType", + "included": 1, + "storageOption": "NVM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "SupportedCalendarTypes", + "code": 2, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "FeatureMap", + "code": 65532, + "mfgCode": null, + "side": "server", + "type": "bitmap32", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "ClusterRevision", + "code": 65533, + "mfgCode": null, + "side": "server", + "type": "int16u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "1", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + } + ] + }, + { + "name": "Unit Localization", + "code": 45, + "mfgCode": null, + "define": "UNIT_LOCALIZATION_CLUSTER", + "side": "client", + "enabled": 0 + }, + { + "name": "Unit Localization", + "code": 45, + "mfgCode": null, + "define": "UNIT_LOCALIZATION_CLUSTER", + "side": "server", + "enabled": 0, + "attributes": [ + { + "name": "TemperatureUnit", + "code": 0, + "mfgCode": null, + "side": "server", + "type": "TempUnit", + "included": 0, + "storageOption": "NVM", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "FeatureMap", + "code": 65532, + "mfgCode": null, + "side": "server", + "type": "bitmap32", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "ClusterRevision", + "code": 65533, + "mfgCode": null, + "side": "server", + "type": "int16u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "1", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + } + ] + }, + { + "name": "General Commissioning", + "code": 48, + "mfgCode": null, + "define": "GENERAL_COMMISSIONING_CLUSTER", + "side": "client", + "enabled": 0, + "commands": [ + { + "name": "ArmFailSafe", + "code": 0, + "mfgCode": null, + "source": "client", + "incoming": 1, + "outgoing": 1 + }, + { + "name": "SetRegulatoryConfig", + "code": 2, + "mfgCode": null, + "source": "client", + "incoming": 1, + "outgoing": 0 + }, + { + "name": "CommissioningComplete", + "code": 4, + "mfgCode": null, + "source": "client", + "incoming": 1, + "outgoing": 1 + } + ], + "attributes": [ + { + "name": "ClusterRevision", + "code": 65533, + "mfgCode": null, + "side": "client", + "type": "int16u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "1", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + } + ] + }, + { + "name": "General Commissioning", + "code": 48, + "mfgCode": null, + "define": "GENERAL_COMMISSIONING_CLUSTER", + "side": "server", + "enabled": 1, + "commands": [ + { + "name": "ArmFailSafeResponse", + "code": 1, + "mfgCode": null, + "source": "server", + "incoming": 1, + "outgoing": 1 + }, + { + "name": "SetRegulatoryConfigResponse", + "code": 3, + "mfgCode": null, + "source": "server", + "incoming": 0, + "outgoing": 1 + }, + { + "name": "CommissioningCompleteResponse", + "code": 5, + "mfgCode": null, + "source": "server", + "incoming": 1, + "outgoing": 1 + } + ], + "attributes": [ + { + "name": "Breadcrumb", + "code": 0, + "mfgCode": null, + "side": "server", + "type": "int64u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0x0000000000000000", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "BasicCommissioningInfo", + "code": 1, + "mfgCode": null, + "side": "server", + "type": "BasicCommissioningInfo", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "RegulatoryConfig", + "code": 2, + "mfgCode": null, + "side": "server", + "type": "RegulatoryLocationType", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "0", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "LocationCapability", + "code": 3, + "mfgCode": null, + "side": "server", + "type": "RegulatoryLocationType", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "0", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "SupportsConcurrentConnection", + "code": 4, + "mfgCode": null, + "side": "server", + "type": "boolean", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "1", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "FeatureMap", + "code": 65532, + "mfgCode": null, + "side": "server", + "type": "bitmap32", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "ClusterRevision", + "code": 65533, + "mfgCode": null, + "side": "server", + "type": "int16u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "1", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + } + ] + }, + { + "name": "Network Commissioning", + "code": 49, + "mfgCode": null, + "define": "NETWORK_COMMISSIONING_CLUSTER", + "side": "client", + "enabled": 0, + "commands": [ + { + "name": "ScanNetworks", + "code": 0, + "mfgCode": null, + "source": "client", + "incoming": 1, + "outgoing": 1 + }, + { + "name": "AddOrUpdateWiFiNetwork", + "code": 2, + "mfgCode": null, + "source": "client", + "incoming": 0, + "outgoing": 0 + }, + { + "name": "AddOrUpdateThreadNetwork", + "code": 3, + "mfgCode": null, + "source": "client", + "incoming": 1, + "outgoing": 0 + }, + { + "name": "RemoveNetwork", + "code": 4, + "mfgCode": null, + "source": "client", + "incoming": 1, + "outgoing": 0 + }, + { + "name": "ConnectNetwork", + "code": 6, + "mfgCode": null, + "source": "client", + "incoming": 1, + "outgoing": 0 + }, + { + "name": "ReorderNetwork", + "code": 8, + "mfgCode": null, + "source": "client", + "incoming": 1, + "outgoing": 0 + } + ], + "attributes": [ + { + "name": "ClusterRevision", + "code": 65533, + "mfgCode": null, + "side": "client", + "type": "int16u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "1", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + } + ] + }, + { + "name": "Network Commissioning", + "code": 49, + "mfgCode": null, + "define": "NETWORK_COMMISSIONING_CLUSTER", + "side": "server", + "enabled": 1, + "commands": [ + { + "name": "ScanNetworksResponse", + "code": 1, + "mfgCode": null, + "source": "server", + "incoming": 1, + "outgoing": 1 + }, + { + "name": "NetworkConfigResponse", + "code": 5, + "mfgCode": null, + "source": "server", + "incoming": 0, + "outgoing": 1 + }, + { + "name": "ConnectNetworkResponse", + "code": 7, + "mfgCode": null, + "source": "server", + "incoming": 0, + "outgoing": 1 + } + ], + "attributes": [ + { + "name": "MaxNetworks", + "code": 0, + "mfgCode": null, + "side": "server", + "type": "int8u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "Networks", + "code": 1, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "ScanMaxTimeSeconds", + "code": 2, + "mfgCode": null, + "side": "server", + "type": "int8u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "ConnectMaxTimeSeconds", + "code": 3, + "mfgCode": null, + "side": "server", + "type": "int8u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "InterfaceEnabled", + "code": 4, + "mfgCode": null, + "side": "server", + "type": "boolean", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "LastNetworkingStatus", + "code": 5, + "mfgCode": null, + "side": "server", + "type": "NetworkCommissioningStatus", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "LastNetworkID", + "code": 6, + "mfgCode": null, + "side": "server", + "type": "octet_string", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "LastConnectErrorValue", + "code": 7, + "mfgCode": null, + "side": "server", + "type": "int32s", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "GeneratedCommandList", + "code": 65528, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 0, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "FeatureMap", + "code": 65532, + "mfgCode": null, + "side": "server", + "type": "bitmap32", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "2", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "ClusterRevision", + "code": 65533, + "mfgCode": null, + "side": "server", + "type": "int16u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "1", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + } + ] + }, + { + "name": "Diagnostic Logs", + "code": 50, + "mfgCode": null, + "define": "DIAGNOSTIC_LOGS_CLUSTER", + "side": "client", + "enabled": 0, + "commands": [ + { + "name": "RetrieveLogsRequest", + "code": 0, + "mfgCode": null, + "source": "client", + "incoming": 0, + "outgoing": 1 + } + ], + "attributes": [ + { + "name": "FeatureMap", + "code": 65532, + "mfgCode": null, + "side": "client", + "type": "bitmap32", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "ClusterRevision", + "code": 65533, + "mfgCode": null, + "side": "client", + "type": "int16u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "1", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + } + ] + }, + { + "name": "Diagnostic Logs", + "code": 50, + "mfgCode": null, + "define": "DIAGNOSTIC_LOGS_CLUSTER", + "side": "server", + "enabled": 0, + "commands": [ + { + "name": "RetrieveLogsRequest", + "code": 0, + "mfgCode": null, + "source": "client", + "incoming": 1, + "outgoing": 0 + }, + { + "name": "RetrieveLogsResponse", + "code": 1, + "mfgCode": null, + "source": "server", + "incoming": 1, + "outgoing": 0 + } + ], + "attributes": [ + { + "name": "GeneratedCommandList", + "code": 65528, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "AcceptedCommandList", + "code": 65529, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "AttributeList", + "code": 65531, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "FeatureMap", + "code": 65532, + "mfgCode": null, + "side": "server", + "type": "bitmap32", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "ClusterRevision", + "code": 65533, + "mfgCode": null, + "side": "server", + "type": "int16u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "1", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + } + ] + }, + { + "name": "General Diagnostics", + "code": 51, + "mfgCode": null, + "define": "GENERAL_DIAGNOSTICS_CLUSTER", + "side": "client", + "enabled": 0, + "attributes": [ + { + "name": "ClusterRevision", + "code": 65533, + "mfgCode": null, + "side": "client", + "type": "int16u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "1", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + } + ] + }, + { + "name": "General Diagnostics", + "code": 51, + "mfgCode": null, + "define": "GENERAL_DIAGNOSTICS_CLUSTER", + "side": "server", + "enabled": 1, + "commands": [ + { + "name": "TestEventTrigger", + "code": 0, + "mfgCode": null, + "source": "client", + "incoming": 1, + "outgoing": 0 + } + ], + "attributes": [ + { + "name": "NetworkInterfaces", + "code": 0, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "RebootCount", + "code": 1, + "mfgCode": null, + "side": "server", + "type": "int16u", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "0x0000", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "UpTime", + "code": 2, + "mfgCode": null, + "side": "server", + "type": "int64u", + "included": 0, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "0x0000000000000000", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "TotalOperationalHours", + "code": 3, + "mfgCode": null, + "side": "server", + "type": "int32u", + "included": 0, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "0x00000000", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "BootReason", + "code": 4, + "mfgCode": null, + "side": "server", + "type": "BootReasonEnum", + "included": 0, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "ActiveHardwareFaults", + "code": 5, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 0, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "ActiveRadioFaults", + "code": 6, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 0, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "ActiveNetworkFaults", + "code": 7, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 0, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "TestEventTriggersEnabled", + "code": 8, + "mfgCode": null, + "side": "server", + "type": "boolean", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "false", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "FeatureMap", + "code": 65532, + "mfgCode": null, + "side": "server", + "type": "bitmap32", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "ClusterRevision", + "code": 65533, + "mfgCode": null, + "side": "server", + "type": "int16u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "1", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + } + ], + "events": [ + { + "name": "BootReason", + "code": 3, + "mfgCode": null, + "side": "server", + "included": 1 + } + ] + }, + { + "name": "Software Diagnostics", + "code": 52, + "mfgCode": null, + "define": "SOFTWARE_DIAGNOSTICS_CLUSTER", + "side": "client", + "enabled": 0, + "commands": [ + { + "name": "ResetWatermarks", + "code": 0, + "mfgCode": null, + "source": "client", + "incoming": 1, + "outgoing": 1 + } + ], + "attributes": [ + { + "name": "ClusterRevision", + "code": 65533, + "mfgCode": null, + "side": "client", + "type": "int16u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "1", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + } + ] + }, + { + "name": "Software Diagnostics", + "code": 52, + "mfgCode": null, + "define": "SOFTWARE_DIAGNOSTICS_CLUSTER", + "side": "server", + "enabled": 1, + "attributes": [ + { + "name": "ThreadMetrics", + "code": 0, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "CurrentHeapFree", + "code": 1, + "mfgCode": null, + "side": "server", + "type": "int64u", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "0x0000000000000000", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "CurrentHeapUsed", + "code": 2, + "mfgCode": null, + "side": "server", + "type": "int64u", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "0x0000000000000000", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "CurrentHeapHighWatermark", + "code": 3, + "mfgCode": null, + "side": "server", + "type": "int64u", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "0x0000000000000000", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "FeatureMap", + "code": 65532, + "mfgCode": null, + "side": "server", + "type": "bitmap32", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "1", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "ClusterRevision", + "code": 65533, + "mfgCode": null, + "side": "server", + "type": "int16u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "1", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + } + ] + }, + { + "name": "Thread Network Diagnostics", + "code": 53, + "mfgCode": null, + "define": "THREAD_NETWORK_DIAGNOSTICS_CLUSTER", + "side": "client", + "enabled": 0, + "commands": [ + { + "name": "ResetCounts", + "code": 0, + "mfgCode": null, + "source": "client", + "incoming": 1, + "outgoing": 0 + } + ], + "attributes": [ + { + "name": "ClusterRevision", + "code": 65533, + "mfgCode": null, + "side": "client", + "type": "int16u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "1", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + } + ] + }, + { + "name": "Thread Network Diagnostics", + "code": 53, + "mfgCode": null, + "define": "THREAD_NETWORK_DIAGNOSTICS_CLUSTER", + "side": "server", + "enabled": 1, + "attributes": [ + { + "name": "Channel", + "code": 0, + "mfgCode": null, + "side": "server", + "type": "int16u", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "RoutingRole", + "code": 1, + "mfgCode": null, + "side": "server", + "type": "RoutingRole", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "NetworkName", + "code": 2, + "mfgCode": null, + "side": "server", + "type": "char_string", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "0", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "PanId", + "code": 3, + "mfgCode": null, + "side": "server", + "type": "int16u", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "0x0000", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "ExtendedPanId", + "code": 4, + "mfgCode": null, + "side": "server", + "type": "int64u", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "0x0000000000000000", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "MeshLocalPrefix", + "code": 5, + "mfgCode": null, + "side": "server", + "type": "octet_string", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "OverrunCount", + "code": 6, + "mfgCode": null, + "side": "server", + "type": "int64u", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "0x0000000000000000", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "NeighborTable", + "code": 7, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "RouteTable", + "code": 8, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "PartitionId", + "code": 9, + "mfgCode": null, + "side": "server", + "type": "int32u", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "Weighting", + "code": 10, + "mfgCode": null, + "side": "server", + "type": "int8u", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "DataVersion", + "code": 11, + "mfgCode": null, + "side": "server", + "type": "int8u", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "StableDataVersion", + "code": 12, + "mfgCode": null, + "side": "server", + "type": "int8u", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "LeaderRouterId", + "code": 13, + "mfgCode": null, + "side": "server", + "type": "int8u", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "DetachedRoleCount", + "code": 14, + "mfgCode": null, + "side": "server", + "type": "int16u", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "0x0000", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "ChildRoleCount", + "code": 15, + "mfgCode": null, + "side": "server", + "type": "int16u", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "0x0000", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "RouterRoleCount", + "code": 16, + "mfgCode": null, + "side": "server", + "type": "int16u", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "0x0000", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "LeaderRoleCount", + "code": 17, + "mfgCode": null, + "side": "server", + "type": "int16u", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "0x0000", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "AttachAttemptCount", + "code": 18, + "mfgCode": null, + "side": "server", + "type": "int16u", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "0x0000", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "PartitionIdChangeCount", + "code": 19, + "mfgCode": null, + "side": "server", + "type": "int16u", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "0x0000", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "BetterPartitionAttachAttemptCount", + "code": 20, + "mfgCode": null, + "side": "server", + "type": "int16u", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "0x0000", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "ParentChangeCount", + "code": 21, + "mfgCode": null, + "side": "server", + "type": "int16u", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "0x0000", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "TxTotalCount", + "code": 22, + "mfgCode": null, + "side": "server", + "type": "int32u", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "0x0000", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "TxUnicastCount", + "code": 23, + "mfgCode": null, + "side": "server", + "type": "int32u", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "0x0000", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "TxBroadcastCount", + "code": 24, + "mfgCode": null, + "side": "server", + "type": "int32u", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "0x0000", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "TxAckRequestedCount", + "code": 25, + "mfgCode": null, + "side": "server", + "type": "int32u", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "0x0000", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "TxAckedCount", + "code": 26, + "mfgCode": null, + "side": "server", + "type": "int32u", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "0x0000", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "TxNoAckRequestedCount", + "code": 27, + "mfgCode": null, + "side": "server", + "type": "int32u", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "0x0000", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "TxDataCount", + "code": 28, + "mfgCode": null, + "side": "server", + "type": "int32u", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "0x0000", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "TxDataPollCount", + "code": 29, + "mfgCode": null, + "side": "server", + "type": "int32u", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "0x0000", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "TxBeaconCount", + "code": 30, + "mfgCode": null, + "side": "server", + "type": "int32u", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "0x0000", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "TxBeaconRequestCount", + "code": 31, + "mfgCode": null, + "side": "server", + "type": "int32u", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "0x0000", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "TxOtherCount", + "code": 32, + "mfgCode": null, + "side": "server", + "type": "int32u", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "0x0000", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "TxRetryCount", + "code": 33, + "mfgCode": null, + "side": "server", + "type": "int32u", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "0x0000", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "TxDirectMaxRetryExpiryCount", + "code": 34, + "mfgCode": null, + "side": "server", + "type": "int32u", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "0x0000", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "TxIndirectMaxRetryExpiryCount", + "code": 35, + "mfgCode": null, + "side": "server", + "type": "int32u", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "0x0000", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "TxErrCcaCount", + "code": 36, + "mfgCode": null, + "side": "server", + "type": "int32u", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "0x0000", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "TxErrAbortCount", + "code": 37, + "mfgCode": null, + "side": "server", + "type": "int32u", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "0x0000", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "TxErrBusyChannelCount", + "code": 38, + "mfgCode": null, + "side": "server", + "type": "int32u", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "0x0000", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "RxTotalCount", + "code": 39, + "mfgCode": null, + "side": "server", + "type": "int32u", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "0x0000", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "RxUnicastCount", + "code": 40, + "mfgCode": null, + "side": "server", + "type": "int32u", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "0x0000", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "RxBroadcastCount", + "code": 41, + "mfgCode": null, + "side": "server", + "type": "int32u", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "0x0000", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "RxDataCount", + "code": 42, + "mfgCode": null, + "side": "server", + "type": "int32u", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "0x0000", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "RxDataPollCount", + "code": 43, + "mfgCode": null, + "side": "server", + "type": "int32u", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "0x0000", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "RxBeaconCount", + "code": 44, + "mfgCode": null, + "side": "server", + "type": "int32u", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "0x0000", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "RxBeaconRequestCount", + "code": 45, + "mfgCode": null, + "side": "server", + "type": "int32u", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "0x0000", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "RxOtherCount", + "code": 46, + "mfgCode": null, + "side": "server", + "type": "int32u", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "0x0000", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "RxAddressFilteredCount", + "code": 47, + "mfgCode": null, + "side": "server", + "type": "int32u", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "0x0000", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "RxDestAddrFilteredCount", + "code": 48, + "mfgCode": null, + "side": "server", + "type": "int32u", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "0x0000", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "RxDuplicatedCount", + "code": 49, + "mfgCode": null, + "side": "server", + "type": "int32u", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "0x0000", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "RxErrNoFrameCount", + "code": 50, + "mfgCode": null, + "side": "server", + "type": "int32u", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "0x0000", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "RxErrUnknownNeighborCount", + "code": 51, + "mfgCode": null, + "side": "server", + "type": "int32u", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "0x0000", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "RxErrInvalidSrcAddrCount", + "code": 52, + "mfgCode": null, + "side": "server", + "type": "int32u", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "0x0000", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "RxErrSecCount", + "code": 53, + "mfgCode": null, + "side": "server", + "type": "int32u", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "0x0000", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "RxErrFcsCount", + "code": 54, + "mfgCode": null, + "side": "server", + "type": "int32u", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "0x0000", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "RxErrOtherCount", + "code": 55, + "mfgCode": null, + "side": "server", + "type": "int32u", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "0x0000", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "ActiveTimestamp", + "code": 56, + "mfgCode": null, + "side": "server", + "type": "int64u", + "included": 0, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "0x0000000000000000", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "PendingTimestamp", + "code": 57, + "mfgCode": null, + "side": "server", + "type": "int64u", + "included": 0, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "0x0000000000000000", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "Delay", + "code": 58, + "mfgCode": null, + "side": "server", + "type": "int32u", + "included": 0, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "0x0000", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "SecurityPolicy", + "code": 59, + "mfgCode": null, + "side": "server", + "type": "SecurityPolicy", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "ChannelPage0Mask", + "code": 60, + "mfgCode": null, + "side": "server", + "type": "octet_string", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "0x0000", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "OperationalDatasetComponents", + "code": 61, + "mfgCode": null, + "side": "server", + "type": "OperationalDatasetComponents", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "ActiveNetworkFaultsList", + "code": 62, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "FeatureMap", + "code": 65532, + "mfgCode": null, + "side": "server", + "type": "bitmap32", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0x000F", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "ClusterRevision", + "code": 65533, + "mfgCode": null, + "side": "server", + "type": "int16u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "1", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + } + ] + }, + { + "name": "WiFi Network Diagnostics", + "code": 54, + "mfgCode": null, + "define": "WIFI_NETWORK_DIAGNOSTICS_CLUSTER", + "side": "client", + "enabled": 0, + "commands": [ + { + "name": "ResetCounts", + "code": 0, + "mfgCode": null, + "source": "client", + "incoming": 1, + "outgoing": 0 + } + ], + "attributes": [ + { + "name": "ClusterRevision", + "code": 65533, + "mfgCode": null, + "side": "client", + "type": "int16u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "1", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + } + ] + }, + { + "name": "WiFi Network Diagnostics", + "code": 54, + "mfgCode": null, + "define": "WIFI_NETWORK_DIAGNOSTICS_CLUSTER", + "side": "server", + "enabled": 0, + "attributes": [ + { + "name": "BSSID", + "code": 0, + "mfgCode": null, + "side": "server", + "type": "octet_string", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "SecurityType", + "code": 1, + "mfgCode": null, + "side": "server", + "type": "SecurityType", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "WiFiVersion", + "code": 2, + "mfgCode": null, + "side": "server", + "type": "WiFiVersionType", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "ChannelNumber", + "code": 3, + "mfgCode": null, + "side": "server", + "type": "int16u", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "0x0000", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "RSSI", + "code": 4, + "mfgCode": null, + "side": "server", + "type": "int8s", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "0x00", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "BeaconLostCount", + "code": 5, + "mfgCode": null, + "side": "server", + "type": "int32u", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "0x00000000", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "BeaconRxCount", + "code": 6, + "mfgCode": null, + "side": "server", + "type": "int32u", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "0x00000000", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "PacketMulticastRxCount", + "code": 7, + "mfgCode": null, + "side": "server", + "type": "int32u", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "0x00000000", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "PacketMulticastTxCount", + "code": 8, + "mfgCode": null, + "side": "server", + "type": "int32u", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "0x00000000", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "PacketUnicastRxCount", + "code": 9, + "mfgCode": null, + "side": "server", + "type": "int32u", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "0x00000000", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "PacketUnicastTxCount", + "code": 10, + "mfgCode": null, + "side": "server", + "type": "int32u", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "0x00000000", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "CurrentMaxRate", + "code": 11, + "mfgCode": null, + "side": "server", + "type": "int64u", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "0x0000000000000000", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "OverrunCount", + "code": 12, + "mfgCode": null, + "side": "server", + "type": "int64u", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "0x0000000000000000", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "FeatureMap", + "code": 65532, + "mfgCode": null, + "side": "server", + "type": "bitmap32", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "3", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "ClusterRevision", + "code": 65533, + "mfgCode": null, + "side": "server", + "type": "int16u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "1", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + } + ] + }, + { + "name": "Ethernet Network Diagnostics", + "code": 55, + "mfgCode": null, + "define": "ETHERNET_NETWORK_DIAGNOSTICS_CLUSTER", + "side": "client", + "enabled": 0, + "commands": [ + { + "name": "ResetCounts", + "code": 0, + "mfgCode": null, + "source": "client", + "incoming": 1, + "outgoing": 1 + } + ], + "attributes": [ + { + "name": "ClusterRevision", + "code": 65533, + "mfgCode": null, + "side": "client", + "type": "int16u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "1", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + } + ] + }, + { + "name": "Ethernet Network Diagnostics", + "code": 55, + "mfgCode": null, + "define": "ETHERNET_NETWORK_DIAGNOSTICS_CLUSTER", + "side": "server", + "enabled": 0, + "attributes": [ + { + "name": "PHYRate", + "code": 0, + "mfgCode": null, + "side": "server", + "type": "PHYRate", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "FullDuplex", + "code": 1, + "mfgCode": null, + "side": "server", + "type": "boolean", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "0x00", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "PacketRxCount", + "code": 2, + "mfgCode": null, + "side": "server", + "type": "int64u", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "0x0000000000000000", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "PacketTxCount", + "code": 3, + "mfgCode": null, + "side": "server", + "type": "int64u", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "0x0000000000000000", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "TxErrCount", + "code": 4, + "mfgCode": null, + "side": "server", + "type": "int64u", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "0x0000000000000000", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "CollisionCount", + "code": 5, + "mfgCode": null, + "side": "server", + "type": "int64u", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "0x0000000000000000", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "OverrunCount", + "code": 6, + "mfgCode": null, + "side": "server", + "type": "int64u", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "0x0000000000000000", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "CarrierDetect", + "code": 7, + "mfgCode": null, + "side": "server", + "type": "boolean", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "0x00", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "TimeSinceReset", + "code": 8, + "mfgCode": null, + "side": "server", + "type": "int64u", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "0x0000000000000000", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "FeatureMap", + "code": 65532, + "mfgCode": null, + "side": "server", + "type": "bitmap32", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "3", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "ClusterRevision", + "code": 65533, + "mfgCode": null, + "side": "server", + "type": "int16u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "1", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + } + ] + }, + { + "name": "Switch", + "code": 59, + "mfgCode": null, + "define": "SWITCH_CLUSTER", + "side": "client", + "enabled": 0 + }, + { + "name": "Switch", + "code": 59, + "mfgCode": null, + "define": "SWITCH_CLUSTER", + "side": "server", + "enabled": 0, + "attributes": [ + { + "name": "FeatureMap", + "code": 65532, + "mfgCode": null, + "side": "server", + "type": "bitmap32", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "ClusterRevision", + "code": 65533, + "mfgCode": null, + "side": "server", + "type": "int16u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "1", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + } + ] + }, + { + "name": "AdministratorCommissioning", + "code": 60, + "mfgCode": null, + "define": "ADMINISTRATOR_COMMISSIONING_CLUSTER", + "side": "client", + "enabled": 0, + "commands": [ + { + "name": "OpenCommissioningWindow", + "code": 0, + "mfgCode": null, + "source": "client", + "incoming": 1, + "outgoing": 1 + }, + { + "name": "OpenBasicCommissioningWindow", + "code": 1, + "mfgCode": null, + "source": "client", + "incoming": 0, + "outgoing": 1 + }, + { + "name": "RevokeCommissioning", + "code": 2, + "mfgCode": null, + "source": "client", + "incoming": 1, + "outgoing": 1 + } + ], + "attributes": [ + { + "name": "ClusterRevision", + "code": 65533, + "mfgCode": null, + "side": "client", + "type": "int16u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "1", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + } + ] + }, + { + "name": "AdministratorCommissioning", + "code": 60, + "mfgCode": null, + "define": "ADMINISTRATOR_COMMISSIONING_CLUSTER", + "side": "server", + "enabled": 1, + "attributes": [ + { + "name": "WindowStatus", + "code": 0, + "mfgCode": null, + "side": "server", + "type": "CommissioningWindowStatus", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "0", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "AdminFabricIndex", + "code": 1, + "mfgCode": null, + "side": "server", + "type": "fabric_idx", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "1", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "AdminVendorId", + "code": 2, + "mfgCode": null, + "side": "server", + "type": "int16u", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "0", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "FeatureMap", + "code": 65532, + "mfgCode": null, + "side": "server", + "type": "bitmap32", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "ClusterRevision", + "code": 65533, + "mfgCode": null, + "side": "server", + "type": "int16u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "1", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + } + ] + }, + { + "name": "Operational Credentials", + "code": 62, + "mfgCode": null, + "define": "OPERATIONAL_CREDENTIALS_CLUSTER", + "side": "client", + "enabled": 0, + "commands": [ + { + "name": "AttestationRequest", + "code": 0, + "mfgCode": null, + "source": "client", + "incoming": 1, + "outgoing": 1 + }, + { + "name": "CertificateChainRequest", + "code": 2, + "mfgCode": null, + "source": "client", + "incoming": 1, + "outgoing": 1 + }, + { + "name": "CSRRequest", + "code": 4, + "mfgCode": null, + "source": "client", + "incoming": 1, + "outgoing": 1 + }, + { + "name": "AddNOC", + "code": 6, + "mfgCode": null, + "source": "client", + "incoming": 1, + "outgoing": 1 + }, + { + "name": "UpdateNOC", + "code": 7, + "mfgCode": null, + "source": "client", + "incoming": 1, + "outgoing": 0 + }, + { + "name": "UpdateFabricLabel", + "code": 9, + "mfgCode": null, + "source": "client", + "incoming": 1, + "outgoing": 1 + }, + { + "name": "RemoveFabric", + "code": 10, + "mfgCode": null, + "source": "client", + "incoming": 1, + "outgoing": 1 + }, + { + "name": "AddTrustedRootCertificate", + "code": 11, + "mfgCode": null, + "source": "client", + "incoming": 1, + "outgoing": 1 + } + ], + "attributes": [ + { + "name": "ClusterRevision", + "code": 65533, + "mfgCode": null, + "side": "client", + "type": "int16u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "1", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + } + ] + }, + { + "name": "Operational Credentials", + "code": 62, + "mfgCode": null, + "define": "OPERATIONAL_CREDENTIALS_CLUSTER", + "side": "server", + "enabled": 1, + "commands": [ + { + "name": "AttestationResponse", + "code": 1, + "mfgCode": null, + "source": "server", + "incoming": 1, + "outgoing": 1 + }, + { + "name": "CertificateChainResponse", + "code": 3, + "mfgCode": null, + "source": "server", + "incoming": 1, + "outgoing": 1 + }, + { + "name": "CSRResponse", + "code": 5, + "mfgCode": null, + "source": "server", + "incoming": 1, + "outgoing": 1 + }, + { + "name": "NOCResponse", + "code": 8, + "mfgCode": null, + "source": "server", + "incoming": 1, + "outgoing": 1 + } + ], + "attributes": [ + { + "name": "NOCs", + "code": 0, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "Fabrics", + "code": 1, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "SupportedFabrics", + "code": 2, + "mfgCode": null, + "side": "server", + "type": "int8u", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "CommissionedFabrics", + "code": 3, + "mfgCode": null, + "side": "server", + "type": "int8u", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "TrustedRootCertificates", + "code": 4, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "CurrentFabricIndex", + "code": 5, + "mfgCode": null, + "side": "server", + "type": "int8u", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "FeatureMap", + "code": 65532, + "mfgCode": null, + "side": "server", + "type": "bitmap32", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "ClusterRevision", + "code": 65533, + "mfgCode": null, + "side": "server", + "type": "int16u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "1", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + } + ] + }, + { + "name": "Group Key Management", + "code": 63, + "mfgCode": null, + "define": "GROUP_KEY_MANAGEMENT_CLUSTER", + "side": "client", + "enabled": 0, + "commands": [ + { + "name": "KeySetWrite", + "code": 0, + "mfgCode": null, + "source": "client", + "incoming": 1, + "outgoing": 0 + }, + { + "name": "KeySetRead", + "code": 1, + "mfgCode": null, + "source": "client", + "incoming": 1, + "outgoing": 0 + }, + { + "name": "KeySetRemove", + "code": 3, + "mfgCode": null, + "source": "client", + "incoming": 1, + "outgoing": 0 + }, + { + "name": "KeySetReadAllIndices", + "code": 4, + "mfgCode": null, + "source": "client", + "incoming": 1, + "outgoing": 0 + } + ] + }, + { + "name": "Group Key Management", + "code": 63, + "mfgCode": null, + "define": "GROUP_KEY_MANAGEMENT_CLUSTER", + "side": "server", + "enabled": 1, + "commands": [ + { + "name": "KeySetReadResponse", + "code": 2, + "mfgCode": null, + "source": "server", + "incoming": 0, + "outgoing": 1 + }, + { + "name": "KeySetReadAllIndicesResponse", + "code": 5, + "mfgCode": null, + "source": "server", + "incoming": 0, + "outgoing": 1 + } + ], + "attributes": [ + { + "name": "GroupKeyMap", + "code": 0, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "GroupTable", + "code": 1, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "MaxGroupsPerFabric", + "code": 2, + "mfgCode": null, + "side": "server", + "type": "int16u", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "MaxGroupKeysPerFabric", + "code": 3, + "mfgCode": null, + "side": "server", + "type": "int16u", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "FeatureMap", + "code": 65532, + "mfgCode": null, + "side": "server", + "type": "bitmap32", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "ClusterRevision", + "code": 65533, + "mfgCode": null, + "side": "server", + "type": "int16u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "1", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + } + ] + }, + { + "name": "Fixed Label", + "code": 64, + "mfgCode": null, + "define": "FIXED_LABEL_CLUSTER", + "side": "client", + "enabled": 0 + }, + { + "name": "Fixed Label", + "code": 64, + "mfgCode": null, + "define": "FIXED_LABEL_CLUSTER", + "side": "server", + "enabled": 0, + "attributes": [ + { + "name": "LabelList", + "code": 0, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "FeatureMap", + "code": 65532, + "mfgCode": null, + "side": "server", + "type": "bitmap32", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "ClusterRevision", + "code": 65533, + "mfgCode": null, + "side": "server", + "type": "int16u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "1", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + } + ] + }, + { + "name": "User Label", + "code": 65, + "mfgCode": null, + "define": "USER_LABEL_CLUSTER", + "side": "client", + "enabled": 0 + }, + { + "name": "User Label", + "code": 65, + "mfgCode": null, + "define": "USER_LABEL_CLUSTER", + "side": "server", + "enabled": 0, + "attributes": [ + { + "name": "LabelList", + "code": 0, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "FeatureMap", + "code": 65532, + "mfgCode": null, + "side": "server", + "type": "bitmap32", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "ClusterRevision", + "code": 65533, + "mfgCode": null, + "side": "server", + "type": "int16u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "1", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + } + ] + } + ] + }, + { + "name": "Anonymous Endpoint Type", + "deviceTypeName": "MA-doorlock", + "deviceTypeCode": 10, + "deviceTypeProfileId": 259, + "clusters": [ + { + "name": "Identify", + "code": 3, + "mfgCode": null, + "define": "IDENTIFY_CLUSTER", + "side": "client", + "enabled": 0, + "commands": [ + { + "name": "Identify", + "code": 0, + "mfgCode": null, + "source": "client", + "incoming": 1, + "outgoing": 0 + }, + { + "name": "TriggerEffect", + "code": 64, + "mfgCode": null, + "source": "client", + "incoming": 1, + "outgoing": 0 + } + ], + "attributes": [ + { + "name": "FeatureMap", + "code": 65532, + "mfgCode": null, + "side": "client", + "type": "bitmap32", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "ClusterRevision", + "code": 65533, + "mfgCode": null, + "side": "client", + "type": "int16u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "4", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + } + ] + }, + { + "name": "Identify", + "code": 3, + "mfgCode": null, + "define": "IDENTIFY_CLUSTER", + "side": "server", + "enabled": 1, + "attributes": [ + { + "name": "IdentifyTime", + "code": 0, + "mfgCode": null, + "side": "server", + "type": "int16u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0x0", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "IdentifyType", + "code": 1, + "mfgCode": null, + "side": "server", + "type": "enum8", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0x0", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "GeneratedCommandList", + "code": 65528, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "AcceptedCommandList", + "code": 65529, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "AttributeList", + "code": 65531, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "FeatureMap", + "code": 65532, + "mfgCode": null, + "side": "server", + "type": "bitmap32", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "ClusterRevision", + "code": 65533, + "mfgCode": null, + "side": "server", + "type": "int16u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "4", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + } + ] + }, + { + "name": "Descriptor", + "code": 29, + "mfgCode": null, + "define": "DESCRIPTOR_CLUSTER", + "side": "client", + "enabled": 0, + "attributes": [ + { + "name": "FeatureMap", + "code": 65532, + "mfgCode": null, + "side": "client", + "type": "bitmap32", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "ClusterRevision", + "code": 65533, + "mfgCode": null, + "side": "client", + "type": "int16u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "1", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + } + ] + }, + { + "name": "Descriptor", + "code": 29, + "mfgCode": null, + "define": "DESCRIPTOR_CLUSTER", + "side": "server", + "enabled": 1, + "attributes": [ + { + "name": "DeviceTypeList", + "code": 0, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "ServerList", + "code": 1, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "ClientList", + "code": 2, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "PartsList", + "code": 3, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "GeneratedCommandList", + "code": 65528, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "AcceptedCommandList", + "code": 65529, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "AttributeList", + "code": 65531, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "FeatureMap", + "code": 65532, + "mfgCode": null, + "side": "server", + "type": "bitmap32", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "ClusterRevision", + "code": 65533, + "mfgCode": null, + "side": "server", + "type": "int16u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "1", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + } + ] + }, + { + "name": "Door Lock", + "code": 257, + "mfgCode": null, + "define": "DOOR_LOCK_CLUSTER", + "side": "client", + "enabled": 0, + "commands": [ + { + "name": "LockDoor", + "code": 0, + "mfgCode": null, + "source": "client", + "incoming": 1, + "outgoing": 0 + }, + { + "name": "UnlockDoor", + "code": 1, + "mfgCode": null, + "source": "client", + "incoming": 1, + "outgoing": 0 + }, + { + "name": "SetUser", + "code": 26, + "mfgCode": null, + "source": "client", + "incoming": 1, + "outgoing": 0 + }, + { + "name": "GetUser", + "code": 27, + "mfgCode": null, + "source": "client", + "incoming": 1, + "outgoing": 0 + }, + { + "name": "ClearUser", + "code": 29, + "mfgCode": null, + "source": "client", + "incoming": 1, + "outgoing": 0 + }, + { + "name": "SetCredential", + "code": 34, + "mfgCode": null, + "source": "client", + "incoming": 1, + "outgoing": 0 + }, + { + "name": "GetCredentialStatus", + "code": 36, + "mfgCode": null, + "source": "client", + "incoming": 1, + "outgoing": 0 + } + ], + "attributes": [ + { + "name": "FeatureMap", + "code": 65532, + "mfgCode": null, + "side": "client", + "type": "bitmap32", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "ClusterRevision", + "code": 65533, + "mfgCode": null, + "side": "client", + "type": "int16u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "6", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + } + ] + }, + { + "name": "Door Lock", + "code": 257, + "mfgCode": null, + "define": "DOOR_LOCK_CLUSTER", + "side": "server", + "enabled": 1, + "commands": [ + { + "name": "GetUserResponse", + "code": 28, + "mfgCode": null, + "source": "server", + "incoming": 0, + "outgoing": 1 + }, + { + "name": "SetCredentialResponse", + "code": 35, + "mfgCode": null, + "source": "server", + "incoming": 0, + "outgoing": 1 + }, + { + "name": "GetCredentialStatusResponse", + "code": 37, + "mfgCode": null, + "source": "server", + "incoming": 0, + "outgoing": 1 + } + ], + "attributes": [ + { + "name": "LockState", + "code": 0, + "mfgCode": null, + "side": "server", + "type": "DlLockState", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "LockType", + "code": 1, + "mfgCode": null, + "side": "server", + "type": "DlLockType", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "ActuatorEnabled", + "code": 2, + "mfgCode": null, + "side": "server", + "type": "boolean", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "DoorState", + "code": 3, + "mfgCode": null, + "side": "server", + "type": "DlDoorState", + "included": 0, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "DoorOpenEvents", + "code": 4, + "mfgCode": null, + "side": "server", + "type": "int32u", + "included": 0, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "DoorClosedEvents", + "code": 5, + "mfgCode": null, + "side": "server", + "type": "int32u", + "included": 0, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "OpenPeriod", + "code": 6, + "mfgCode": null, + "side": "server", + "type": "int16u", + "included": 0, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "NumberOfTotalUsersSupported", + "code": 17, + "mfgCode": null, + "side": "server", + "type": "int16u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "NumberOfPINUsersSupported", + "code": 18, + "mfgCode": null, + "side": "server", + "type": "int16u", + "included": 0, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "NumberOfRFIDUsersSupported", + "code": 19, + "mfgCode": null, + "side": "server", + "type": "int16u", + "included": 0, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "NumberOfWeekDaySchedulesSupportedPerUser", + "code": 20, + "mfgCode": null, + "side": "server", + "type": "int8u", + "included": 0, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "NumberOfYearDaySchedulesSupportedPerUser", + "code": 21, + "mfgCode": null, + "side": "server", + "type": "int8u", + "included": 0, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "NumberOfHolidaySchedulesSupported", + "code": 22, + "mfgCode": null, + "side": "server", + "type": "int8u", + "included": 0, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "MaxPINCodeLength", + "code": 23, + "mfgCode": null, + "side": "server", + "type": "int8u", + "included": 0, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "MinPINCodeLength", + "code": 24, + "mfgCode": null, + "side": "server", + "type": "int8u", + "included": 0, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "MaxRFIDCodeLength", + "code": 25, + "mfgCode": null, + "side": "server", + "type": "int8u", + "included": 0, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "MinRFIDCodeLength", + "code": 26, + "mfgCode": null, + "side": "server", + "type": "int8u", + "included": 0, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "CredentialRulesSupport", + "code": 27, + "mfgCode": null, + "side": "server", + "type": "DlCredentialRuleMask", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "1", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "NumberOfCredentialsSupportedPerUser", + "code": 28, + "mfgCode": null, + "side": "server", + "type": "int8u", + "included": 0, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "Language", + "code": 33, + "mfgCode": null, + "side": "server", + "type": "char_string", + "included": 0, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "LEDSettings", + "code": 34, + "mfgCode": null, + "side": "server", + "type": "int8u", + "included": 0, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "AutoRelockTime", + "code": 35, + "mfgCode": null, + "side": "server", + "type": "int32u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "SoundVolume", + "code": 36, + "mfgCode": null, + "side": "server", + "type": "int8u", + "included": 0, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "OperatingMode", + "code": 37, + "mfgCode": null, + "side": "server", + "type": "DlOperatingMode", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "SupportedOperatingModes", + "code": 38, + "mfgCode": null, + "side": "server", + "type": "DlSupportedOperatingModes", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0xFFF6", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "DefaultConfigurationRegister", + "code": 39, + "mfgCode": null, + "side": "server", + "type": "DlDefaultConfigurationRegister", + "included": 0, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "EnableLocalProgramming", + "code": 40, + "mfgCode": null, + "side": "server", + "type": "boolean", + "included": 0, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "1", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "EnableOneTouchLocking", + "code": 41, + "mfgCode": null, + "side": "server", + "type": "boolean", + "included": 0, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "EnableInsideStatusLED", + "code": 42, + "mfgCode": null, + "side": "server", + "type": "boolean", + "included": 0, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "EnablePrivacyModeButton", + "code": 43, + "mfgCode": null, + "side": "server", + "type": "boolean", + "included": 0, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "LocalProgrammingFeatures", + "code": 44, + "mfgCode": null, + "side": "server", + "type": "DlLocalProgrammingFeatures", + "included": 0, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "WrongCodeEntryLimit", + "code": 48, + "mfgCode": null, + "side": "server", + "type": "int8u", + "included": 0, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "UserCodeTemporaryDisableTime", + "code": 49, + "mfgCode": null, + "side": "server", + "type": "int8u", + "included": 0, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "SendPINOverTheAir", + "code": 50, + "mfgCode": null, + "side": "server", + "type": "boolean", + "included": 0, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "RequirePINforRemoteOperation", + "code": 51, + "mfgCode": null, + "side": "server", + "type": "boolean", + "included": 0, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "ExpiringUserTimeout", + "code": 53, + "mfgCode": null, + "side": "server", + "type": "int16u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "1440", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "GeneratedCommandList", + "code": 65528, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "AcceptedCommandList", + "code": 65529, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "AttributeList", + "code": 65531, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "FeatureMap", + "code": 65532, + "mfgCode": null, + "side": "server", + "type": "bitmap32", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0x1000", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "ClusterRevision", + "code": 65533, + "mfgCode": null, + "side": "server", + "type": "int16u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "6", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + } + ], + "events": [ + { + "name": "DoorLockAlarm", + "code": 0, + "mfgCode": null, + "side": "server", + "included": 1 + }, + { + "name": "DoorStateChange", + "code": 1, + "mfgCode": null, + "side": "server", + "included": 0 + }, + { + "name": "LockOperation", + "code": 2, + "mfgCode": null, + "side": "server", + "included": 1 + }, + { + "name": "LockOperationError", + "code": 3, + "mfgCode": null, + "side": "server", + "included": 1 + }, + { + "name": "LockUserChange", + "code": 4, + "mfgCode": null, + "side": "server", + "included": 1 + } + ] + } + ] + } + ], + "endpoints": [ + { + "endpointTypeName": "MA-rootdevice", + "endpointTypeIndex": 0, + "profileId": 259, + "endpointId": 0, + "networkId": 0, + "endpointVersion": 1, + "deviceIdentifier": 22 + }, + { + "endpointTypeName": "Anonymous Endpoint Type", + "endpointTypeIndex": 1, + "profileId": 259, + "endpointId": 1, + "networkId": 0, + "endpointVersion": 1, + "deviceIdentifier": 10 + } + ], + "log": [] +} \ No newline at end of file diff --git a/examples/platform/nxp/doc/manufacturing_flow.md b/examples/platform/nxp/doc/manufacturing_flow.md index 6fc2ff5e1e49cd..bfa064407ea229 100644 --- a/examples/platform/nxp/doc/manufacturing_flow.md +++ b/examples/platform/nxp/doc/manufacturing_flow.md @@ -26,34 +26,64 @@ possible for a final stage application to generate its own manufacturing data: user@ubuntu:~/Desktop/git/connectedhomeip$ ./examples/platform/nxp/k32w/k32w0/scripts/generate_cert.sh ./src/tools/chip-cert/out/chip-cert ``` -* Generate new provisioning data and convert all the data to a binary: +- Generate new provisioning data and convert all the data to a binary + (unencrypted data): ``` - user@ubuntu:~/Desktop/git/connectedhomeip$ python3 ./scripts/tools/nxp/generate_nxp_chip_factory_bin.py -i 10000 -s ABCDEFGHIJKLMNOPQRSXYZ -p 14014 -d 1000 --dac_cert /home/ubuntu/manufacturing/Chip-DAC-NXP-Cert.der --dac_key /home/ubuntu/manufacturing/Chip-DAC-NXP-Key.der --pai_cert /home/ubuntu/manufacturing/Chip-PAI-NXP-Cert.der --spake2p_path ./src/tools/spake2p/out/spake2p --out out.bin + user@ubuntu:~/Desktop/git/connectedhomeip$ python3 ./scripts/tools/nxp/factory_data_generator/generate.py -i 10000 -s UXKLzwHdN3DZZLBaL2iVGhQi/OoQwIwJRQV4rpEalbA= -p 14014 -d 1000 --vid 0x1037 --pid 0xa220 --vendor_name "NXP Semiconductors" --product_name "Lighting app" --serial_num "SN:12345678" --date "2022-10-21" --hw_version 1 --hw_version_str "1.0" --cert_declaration /home/ubuntu/manufacturing/Chip-Test-CD-1037-a220.der --dac_cert /home/ubuntu/manufacturing/Chip-DAC-NXP-Cert.der --dac_key /home/ubuntu/manufacturing/Chip-DAC-NXP-Key.der --pai_cert /home/ubuntu/manufacturing/Chip-PAI-NXP-Cert.der --spake2p_path ./src/tools/spake2p/out/spake2p --out out.bin ``` - Here is the interpretation of the parameters: +- Same example as above, but with an already generated verifier passed as + input: + + ``` + user@ubuntu:~/Desktop/git/connectedhomeip$ python3 ./scripts/tools/nxp/factory_data_generator/generate.py -i 10000 -s UXKLzwHdN3DZZLBaL2iVGhQi/OoQwIwJRQV4rpEalbA= -p 14014 -d 1000 --vid 0x1037 --pid 0xa220 --vendor_name "NXP Semiconductors" --product_name "Lighting app" --serial_num "SN:12345678" --date "2022-10-21" --hw_version 1 --hw_version_str "1.0" --cert_declaration /home/ubuntu/manufacturing/Chip-Test-CD-1037-a220.der --dac_cert /home/ubuntu/manufacturing/Chip-DAC-NXP-Cert.der --dac_key /home/ubuntu/manufacturing/Chip-DAC-NXP-Key.der --pai_cert /home/ubuntu/manufacturing/Chip-PAI-NXP-Cert.der --spake2p_path ./src/tools/spake2p/out/spake2p --spake2p_verifier ivD5n3L2t5+zeFt6SjW7BhHRF30gFXWZVvvXgDxgCNcE+BGuTA5AUaVm3qDZBcMMKn1a6CakI4SxyPUnJr0CpJ4pwpr0DvpTlkQKqaRvkOQfAQ1XDyf55DuavM5KVGdDrg== --out out.bin + ``` + +- Generate new provisioning data and convert all the data to a binary + (encrypted data with the AES key): ``` - -i -> SPAKE2+ iteration - -s -> SPAKE2+ salt - -p -> SPAKE2+ passcode - - d -> discriminator - --dac_cert -> path to the DAC (der format) location - --dac_key -> path to the DAC key (der format) location - --pai_cert -> path to the PAI (der format) location - --spake2p_path -> path to the spake2p tool (compile it from ./src/tools/spake2p) - --out -> name of the binary that will be used for storing all the generated data + user@ubuntu:~/Desktop/git/connectedhomeip$ python3 ./scripts/tools/nxp/factory_data_generator/generate.py -i 10000 -s UXKLzwHdN3DZZLBaL2iVGhQi/OoQwIwJRQV4rpEalbA= -p 14014 -d 1000 --vid 0x1037 --pid 0xa220 --vendor_name "NXP Semiconductors" --product_name "Lighting app" --serial_num "SN:12345678" --date "2022-10-21" --hw_version 1 --hw_version_str "1.0" --cert_declaration /home/ubuntu/manufacturing/Chip-Test-CD-1037-a220.der --dac_cert /home/ubuntu/manufacturing/Chip-DAC-NXP-Cert.der --dac_key /home/ubuntu/manufacturing/Chip-DAC-NXP-Key.der --pai_cert /home/ubuntu/manufacturing/Chip-PAI-NXP-Cert.der --spake2p_path ./src/tools/spake2p/out/spake2p --out outEncrypted.bin --aes128_key 2B7E151628AED2A6ABF7158809CF4F3C + ``` + + Here is the interpretation of the parameters: ``` + -i -> SPAKE2+ iteration + -s -> SPAKE2+ salt (passed as base64 encoded string) + -p -> SPAKE2+ passcode + -d -> discriminator + --vid -> Vendor ID + --pid -> Product ID + --vendor_name -> Vendor Name + --product_name -> Product Name + --serial_num -> Serial Number + --date -> Manufacturing Date (YYYY-MM-DD format) + --hw_version -> Hardware Version as number + --hw_version_str -> Hardware Version as string + --cert_declaration -> path to the Certification Declaration (der format) location + --dac_cert -> path to the DAC (der format) location + --dac_key -> path to the DAC key (der format) location + --pai_cert -> path to the PAI (der format) location + --spake2p_path -> path to the spake2p tool (compile it from ./src/tools/spake2p) + --out -> name of the binary that will be used for storing all the generated data + --aes128_key -> 128 bits AES key used to encrypt the whole dataset + --spake2p_verifier -> SPAKE2+ verifier (passed as base64 encoded string). If this option is set, + all SPAKE2+ inputs will be encoded in the final binary. The spake2p tool + will not be used to generate a new verifier on the fly. + ``` + +- Write out.bin to the \$platform: -* Write out.bin to the internal flash at location 0x9D200: + For the K32W0x1 platform, the binary needs to be written in the internal + flash at location 0x9D600 using DK6Programmer: ``` - DK6Programmer.exe -Y -V2 -s -P 1000000 -Y -p FLASH@0x9D200="out.bin" + DK6Programmer.exe -Y -V2 -s -P 1000000 -Y -p FLASH@0x9D600="out.bin" ``` -* Generate a new CD (certification declaration): +- Generate a new CD (certification declaration): Inside _gen-test-cds.sh_, the parameters _vids_, _pid0_, _device_type_id_ must be changed accordingly. Use _Chip-Test-CD-Signing-\*_ key and @@ -68,21 +98,21 @@ possible for a final stage application to generate its own manufacturing data: user@ubuntu:~/Desktop/git/connectedhomeip$ ./credentials/test/gen-test-cds.sh ./src/tools/chip-cert/out/chip-cert ``` -* Set the correct VID/PID and CD in the - examples/\$APP_NAME/nxp/k32w/k32w0/ChipProjectConfig.h file VID and PID - values should correspond to the ones used for DAC. CD bytes should be the - ones obtained at the step above: +- Set the correct VID/PID and CD in the + examples/$APP_NAME/nxp/$platform/ChipProjectConfig.h file VID and PID values + should correspond to the ones used for DAC. CD bytes should be the ones + obtained at the step above: ``` user@ubuntu:~/manufacturing hexdump -ve '1/1 "0x%.2x, "' Chip-Test-CD-1037-A220.der ``` -* Use _chip_with_factory_data=1_ gn compilation argument +- Use _chip_with_factory_data=1_ gn compilation argument This is needed in order to load the data from the special flash section. Build and flash the application. -* Run chip-tool with a new PAA: +- Run chip-tool with a new PAA: ``` ./chip-tool pairing ble-thread 2 hex: $hex_value 14014 1000 --paa-trust-store-path /home/ubuntu/certs/paa @@ -103,7 +133,7 @@ possible for a final stage application to generate its own manufacturing data: This is needed for testing self-generated DACs, but likely not required for "true production" with production PAI issued DACs. -* Useful information/Known issues +- Useful information/Known issues Implementation of manufacturing data provisioning has been validated using test certificates generated by OpenSSL 1.1.1l. diff --git a/examples/platform/nxp/k32w/k32w0/app/ldscripts/chip-k32w0x-linker.ld b/examples/platform/nxp/k32w/k32w0/app/ldscripts/chip-k32w0x-linker.ld index 996d7d16e73766..6b9dad04822d1b 100644 --- a/examples/platform/nxp/k32w/k32w0/app/ldscripts/chip-k32w0x-linker.ld +++ b/examples/platform/nxp/k32w/k32w0/app/ldscripts/chip-k32w0x-linker.ld @@ -54,8 +54,8 @@ m_int_sector_size = 512; /* first 8K: SSBL, next 8K: SSBL update region */ m_app_start = DEFINED(__app_load_address__) ? __app_load_address__ : 0x0; -/* PSECT: 8.5K */ -m_psect_size = 0x2200; +/* flash_config: 8.5K */ +m_flash_config_size = 0x2200; /* sizeof(BOOT_BLOCK_T) + sizeof(IMAGE_CERT_T) + SIGNATURE_LEN + alignment = 1024 bytes */ m_app_meta_data = 0x400; @@ -67,7 +67,7 @@ m_factory_data_size = 0x800; m_ssbl_size = 0x4000; /* default app size, without OTA */ -m_app_default_size = m_int_flash_size - m_psect_size - m_app_meta_data - m_factory_data_size; +m_app_default_size = m_int_flash_size - m_flash_config_size - m_app_meta_data - m_factory_data_size; m_app_size = DEFINED(__app_stated_size__) ? __app_stated_size__ : m_app_default_size; @@ -99,7 +99,12 @@ NV_STORAGE_SECTOR_SIZE = m_ext_flash_sector_size; NV_STORAGE_START_ADDRESS = m_ext_flash_size - 1; NV_STORAGE_END_ADDRESS = NV_STORAGE_START_ADDRESS - NV_STORAGE_SIZE + 1; -FACTORY_DATA_START_ADDRESS = m_int_flash_size - m_psect_size - m_app_meta_data - m_factory_data_size; +INT_STORAGE_START = m_int_flash_size - 1; +INT_STORAGE_SIZE = m_int_flash_size; +INT_STORAGE_END = 0x00000000; +INT_STORAGE_SECTOR_SIZE = m_int_sector_size; + +FACTORY_DATA_START_ADDRESS = m_int_flash_size - m_flash_config_size - m_factory_data_size; FACTORY_DATA_END_ADDRESS = FACTORY_DATA_START_ADDRESS + m_factory_data_size - 1; __ram_vector_table__ = 1; @@ -365,4 +370,7 @@ SECTIONS __FACTORY_DATA_START = FACTORY_DATA_START_ADDRESS; __FACTORY_DATA_SIZE = m_factory_data_size; + + ASSERT(((m_app_start + m_app_size + m_app_meta_data + m_factory_data_size + m_flash_config_size) <= m_int_flash_size), + "Internal flash capacity exceeded") } diff --git a/examples/platform/nxp/k32w/k32w0/app/support/FreeRtosHooks.c b/examples/platform/nxp/k32w/k32w0/app/support/FreeRtosHooks.c index 508db54ca5dec2..8a05dca08621e5 100644 --- a/examples/platform/nxp/k32w/k32w0/app/support/FreeRtosHooks.c +++ b/examples/platform/nxp/k32w/k32w0/app/support/FreeRtosHooks.c @@ -31,6 +31,7 @@ #include "PWR_Interface.h" #include "TimersManager.h" #include "board.h" +#include "pdm_ram_storage_glue.h" /* Bluetooth Low Energy */ #include "ble_config.h" @@ -53,6 +54,24 @@ #define APP_DBG_LOG(...) #endif +#if (configUSE_TICKLESS_IDLE != 0) +#define DBG_PostStepTickAssess 0 +#if DBG_PostStepTickAssess && !gTimestampUseWtimer_c +#error "gTimestampUseWtimer_c required for DBG_PostStepTickAssess" +#endif +#if defined(gPWR_FreqScalingWFI) && (gPWR_FreqScalingWFI != 0) +/* this MACRO is required when gPWR_FreqScalingWFI is not equal to zero (system clock frequency + reduced in WFI) */ +#define App_SuppressTickInStopMode 1 +#else +#define App_SuppressTickInStopMode 0 +#endif +#if gPWR_CpuClk_48MHz +/* for systick accuracy, this is recommended to enable FRO calibration */ +#define gApp_SystemClockCalibration 1 +#endif +#endif + #define PDM_MAX_WRITES_INFINITE 0xFF static inline void mutex_init(mbedtls_threading_mutex_t * p_mutex) @@ -236,11 +255,13 @@ extern void OTAIdleActivities(void); void vApplicationIdleHook(void) { - vTaskSuspendAll(); - PDM_vIdleTask(PDM_MAX_WRITES_INFINITE); - xTaskResumeAll(); + FS_vIdleTask(PDM_MAX_WRITES_INFINITE); OTAIdleActivities(); +#if gAdcUsed_d + BOARD_ADCMeasure(); +#endif + BOARD_ActionOnIdle(); } diff --git a/examples/platform/nxp/k32w/k32w0/common/CustomFactoryDataProvider.cpp b/examples/platform/nxp/k32w/k32w0/common/CustomFactoryDataProvider.cpp new file mode 100644 index 00000000000000..249eddf975713f --- /dev/null +++ b/examples/platform/nxp/k32w/k32w0/common/CustomFactoryDataProvider.cpp @@ -0,0 +1,60 @@ +/* + * + * Copyright (c) 2022 Project CHIP Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "CustomFactoryDataProvider.h" + +namespace chip { +namespace DeviceLayer { + +static constexpr size_t kMaxLengthCustomId1 = 10; +static constexpr size_t kMaxLengthCustomId2 = 50; +static constexpr size_t kMaxLengthCustomId3 = 100; + +CustomFactoryDataProvider & CustomFactoryDataProvider::GetDefaultInstance() +{ + static CustomFactoryDataProvider sInstance; + return sInstance; +} + +CHIP_ERROR CustomFactoryDataProvider::SetCustomIds() +{ + static_assert(CustomFactoryIds::kCustomMaxId == K32W0FactoryDataProvider::kNumberOfIds, + "kNumberOfIds is computed based on CHIP_DEVICE_CONFIG_CUSTOM_PROVIDER_NUMBER_IDS."); + maxLengths[CustomFactoryIds::kCustomId1] = kMaxLengthCustomId1; + maxLengths[CustomFactoryIds::kCustomId2] = kMaxLengthCustomId2; + maxLengths[CustomFactoryIds::kCustomId3] = kMaxLengthCustomId3; + + return CHIP_NO_ERROR; +} + +CHIP_ERROR CustomFactoryDataProvider::ParseFunctionExample() +{ + uint8_t data_buf[kMaxLengthCustomId1]; + MutableByteSpan buffer(data_buf); + memset(buffer.data(), 0, buffer.size()); + uint16_t userDataSize = 0; + // A user can use K32W0FactoryDataProvider::SearchForId to read an id from internal + // flash factory data section. + ReturnErrorOnFailure(SearchForId(CustomFactoryIds::kCustomId1, buffer.data(), buffer.size(), userDataSize)); + + // Data should now be ready for custom parsing. + + return CHIP_NO_ERROR; +} + +} // namespace DeviceLayer +} // namespace chip diff --git a/examples/platform/nxp/k32w/k32w0/common/CustomFactoryDataProvider.h b/examples/platform/nxp/k32w/k32w0/common/CustomFactoryDataProvider.h new file mode 100644 index 00000000000000..5a8fc5e0507fc0 --- /dev/null +++ b/examples/platform/nxp/k32w/k32w0/common/CustomFactoryDataProvider.h @@ -0,0 +1,56 @@ +/* + * + * Copyright (c) 2022 Project CHIP Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#pragma once + +#include "K32W0FactoryDataProvider.h" + +namespace chip { +namespace DeviceLayer { + +/** + * @brief This is an example class that extends the platform factory data provider + * to support custom functionality. Users should implement their own custom + * provider based on this example. + */ + +class CustomFactoryDataProvider : public K32W0FactoryDataProvider +{ +public: + /* Custom IDs should start from FactoryDataId::kMaxId, which is + * the next available valid ID. Last default ID is kMaxId - 1. + */ + enum CustomFactoryIds + { + kCustomId1 = FactoryDataId::kMaxId, + kCustomId2, + kCustomId3, + kCustomMaxId + }; + + static CustomFactoryDataProvider & GetDefaultInstance(); + + CustomFactoryDataProvider() {} + + /* SetCustomIds() must be implemented in order to define custom IDs. */ + CHIP_ERROR SetCustomIds() override; + + /* Declare here custom functions to be implemented. */ + CHIP_ERROR ParseFunctionExample(); +}; + +} // namespace DeviceLayer +} // namespace chip diff --git a/examples/platform/nxp/k32w/k32w0/common/README.md b/examples/platform/nxp/k32w/k32w0/common/README.md new file mode 100644 index 00000000000000..442529562babd2 --- /dev/null +++ b/examples/platform/nxp/k32w/k32w0/common/README.md @@ -0,0 +1,62 @@ +--- +orphan: true +--- + +## Usage of custom Factory Data Provider + +`K32W0FactoryDataProvider` is the default factory data provider. It implements +three interfaces from common Matter stack: + +- CommissionableDataProvider +- DeviceAttestationCredentialsProvider +- DeviceInstanceInfoProvider + +A user can inherit `K32W0FactoryDataProvider` to provide additional +functionality (such as parsing custom factory data fields) that is customer +specific. Additionally, each method from the above three interfaces could be +overwritten in the custom provider, but the current platform provider +implementation should be enough for most use cases. + +What **MUST** be done to enable usage of a custom factory provider: + +- Set `use_custom_factory_provider=1`. This option is only available when + factory data is used (`chip_with_factory_data=1`). An assert will be raised + if the condition is not met. +- Modify the `BUILD.gn` of the application to take into account the new files + where the custom factory provider is implemented: + + ``` + if (chip_with_factory_data == 1 && use_custom_factory_provider == 1) + { + sources += [ + "${k32w0_platform_dir}/common/CustomFactoryDataProvider.h", + "${k32w0_platform_dir}/common/CustomFactoryDataProvider.cpp", + ] + + defines = [ + "CHIP_DEVICE_CONFIG_USE_CUSTOM_PROVIDER=1", + "CHIP_DEVICE_CONFIG_CUSTOM_PROVIDER_NUMBER_IDS=3" + ] + } + ``` + + Note that new flags were introduced: + + - `CHIP_DEVICE_CONFIG_USE_CUSTOM_PROVIDER`: select between using + `K32W0FactoryDataProvider` or `CustomFactoryDataProvider` when + registering the provider. + - `CHIP_DEVICE_CONFIG_CUSTOM_PROVIDER_NUMBER_IDS`: set the number of + custom IDs (which are different than the default IDs). If this macro is + not correctly set, compilation should fail. + +- The default IDs are validated directly in `SearchForId`, but custom IDs + should set their maximum lengths through `SetCustomIds` method. +- `K32W0FactoryDataProvider::kNumberOfIds` is computed at compile time and + should represent the number of IDs (custom + default). Custom IDs should + start from `FactoryDataId::kMaxId`, which is the next valid ID. IDs + `[1, FactoryDataId::kMaxId - 1]` are reserved for default factory data IDs. + +Please refer to `CustomFactoryDataProvider` for a minimal example of a custom +factory data provider and note that its implementation is just an example of how +to integrate a custom provider into the application, while still using the +default implementation provided by `K32W0FactoryDataProvider`. diff --git a/examples/shell/nxp/k32w/k32w0/main/main.cpp b/examples/shell/nxp/k32w/k32w0/main/main.cpp index 152900341c4067..59b4ddcd063ea1 100644 --- a/examples/shell/nxp/k32w/k32w0/main/main.cpp +++ b/examples/shell/nxp/k32w/k32w0/main/main.cpp @@ -36,6 +36,10 @@ #include "FreeRtosHooks.h" #include "app_config.h" +#if PDM_SAVE_IDLE +#include +#endif + const uint16_t shell_task_size = 3096; const uint8_t shell_task_priority = 0; @@ -97,6 +101,12 @@ extern "C" void main_task(void const * argument) // Init Chip memory management before the stack chip::Platform::MemoryInit(); +#if PDM_SAVE_IDLE + /* OT Settings needs to be initialized + * early as XCVR is making use of it */ + otPlatSettingsInit(NULL, NULL, 0); +#endif + CHIP_ERROR ret = PlatformMgr().InitChipStack(); if (ret != CHIP_NO_ERROR) { diff --git a/scripts/build/build/targets.py b/scripts/build/build/targets.py index c9ebdfc00728a9..2a6b1701de403e 100755 --- a/scripts/build/build/targets.py +++ b/scripts/build/build/targets.py @@ -381,6 +381,8 @@ def BuildK32WTarget(): target.AppendModifier(name="no-ota", disable_ota=True) target.AppendModifier(name="low-power", low_power=True).OnlyIfRe("-nologs") target.AppendModifier(name="nologs", disable_logs=True) + target.AppendModifier(name="crypto-platform", crypto_platform=True) + target.AppendModifier(name="tokenizer", tokenizer=True).ExceptIfRe("-nologs") return target diff --git a/scripts/build/builders/k32w.py b/scripts/build/builders/k32w.py index eb367cc644c5c0..be17730c481148 100644 --- a/scripts/build/builders/k32w.py +++ b/scripts/build/builders/k32w.py @@ -65,7 +65,8 @@ def __init__(self, disable_ota: bool = False, disable_logs: bool = False, se05x: bool = False, - tinycrypt: bool = False): + tinycrypt: bool = False, + crypto_platform: bool = False): super(K32WBuilder, self).__init__( root=app.BuildRoot(root), runner=runner) @@ -79,6 +80,7 @@ def __init__(self, self.disable_logs = disable_logs self.se05x = se05x self.tinycrypt = tinycrypt + self.crypto_platform = crypto_platform def GnBuildArgs(self): args = [ @@ -109,7 +111,10 @@ def GnBuildArgs(self): args.append('chip_with_se05x=true') if self.tinycrypt: - args.append('chip_crypto=\"tinycrypt\" mbedtls_repo=\"//third_party/connectedhomeip/third_party/nxp/libs/mbedtls\"') + args.append('chip_crypto=\"platform\" chip_crypto_flavor=\"tinycrypt\"') + + if self.crypto_platform: + args.append('chip_crypto=\"platform\"') return args diff --git a/scripts/build/testdata/all_targets_linux_x64.txt b/scripts/build/testdata/all_targets_linux_x64.txt index f6cdca0035930a..7b7ae2126f1e85 100644 --- a/scripts/build/testdata/all_targets_linux_x64.txt +++ b/scripts/build/testdata/all_targets_linux_x64.txt @@ -12,7 +12,7 @@ linux-{x64,arm64}-{rpc-console,all-clusters,all-clusters-minimal,chip-tool,therm linux-x64-efr32-test-runner[-clang] imx-{chip-tool,lighting-app,thermostat,all-clusters-app,all-clusters-minimal-app,ota-provider-app}[-release] infineon-psoc6-{lock,light,all-clusters,all-clusters-minimal}[-ota][-updateimage] -k32w-{light,shell,lock,contact}[-se05x][-no-ble][-no-ota][-low-power][-nologs] +k32w-{light,shell,lock,contact}[-se05x][-no-ble][-no-ota][-low-power][-nologs][-crypto-platform][-tokenizer] mbed-cy8cproto_062_4343w-{lock,light,all-clusters,all-clusters-minimal,pigweed,shell}[-release][-develop][-debug] mw320-all-clusters-app nrf-{nrf5340dk,nrf52840dk,nrf52840dongle}-{all-clusters,all-clusters-minimal,lock,light,light-switch,shell,pump,pump-controller,window-covering}[-rpc] diff --git a/scripts/tools/nxp/factory_data_generator/README.md b/scripts/tools/nxp/factory_data_generator/README.md new file mode 100644 index 00000000000000..74380f0ff8d502 --- /dev/null +++ b/scripts/tools/nxp/factory_data_generator/README.md @@ -0,0 +1,71 @@ +## NXP Factory Data Generator + +For usage of the tool, please see +[Guide for writing manufacturing data on NXP devices](../../../../examples/platform/nxp/doc/manufacturing_flow.md). + +## Tool implementation + +The tool comprises of three files: `generate.py`, `default.py`, `custom.py` + +### `generate.py` + +Uses `argparse` module to parse input arguments. By setting `type` attribute to +class constructors when adding new arguments, they will be parsed into instances +of `InputArgument`. Please note that not all arguments will be encoded in the +output binary, so some arguments will not be `InputArgument` objects (for +example `spake2p_path`). + +From all arguments, only the `InputArgument` instances will be selected to +generate data in the form of `(K, L, V)` tuples. These tuples are appended to a +list that will be used to generate the output binary. + +### `default.py` + +Defines the base `InputArgument` class and its derived classes that will be +referenced as **default classes**. + +`InputArgument` offers an abstract interface in the form of three methods: +`key()`, `length()`, `encode()`, that will be used to generate the `(K, L, V)` +tuple through the public `output()` method. Each custom class should implement +the abstract interface, if its direct parent does not offer a relevant +implementation. + +### `custom.py` + +Defines classes for each argument that should generate data in the output binary +(will be referenced as **custom classes**). Please note that each new class +should derive from a default class, not from `InputArgument` directly. + +### How to add a new argument + +Example of defining a new argument class in `custom.py`: + +``` +class FooArgument(BarArgument): + def __init__(self, arg): + super().__init__(arg) + + def key(self): + return + + def length(self): + return + + def encode(self): + return + + def custom_function(self): + pass +``` + +where `BarArgument` is one of the **default classes**. Please note that a user +can define additional methods if needed (e.g. `custom_function`; also see +`generate_private_key` from `DacPKey` class). + +Then use this class in `generate.py` to create a `FooArgument` object from an +option: + +``` +parser.add_argument("--foo", required=True, type=FooArgument, + help="[int | hex] Foo argument.") +``` diff --git a/scripts/tools/nxp/factory_data_generator/custom.py b/scripts/tools/nxp/factory_data_generator/custom.py new file mode 100644 index 00000000000000..e272921d81fc7a --- /dev/null +++ b/scripts/tools/nxp/factory_data_generator/custom.py @@ -0,0 +1,277 @@ +#!/usr/bin/env python3 +# +# Copyright (c) 2022 Project CHIP Authors +# All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +'''This file should contain custom classes derived any class from default.py. + +Each class implemented here should describe an input parameter and should +implement the InputArgument abstract interface, if its base class does not +already offer an implementation or if there is a need of a custom behavior. + +Example of defining a new argument class: + + class FooArgument(IntArgument): + def __init__(self, arg): + super().__init__(arg) + + def key(self): + return + + def length(self): + return + + def encode(self): + return + + def custom_function(self): + pass + +Then use this class in generate.py to create a FooArgument object from an +option: + + parser.add_argument("--foo", required=True, type=FooArgument, + help="[int | hex] Foo argument.") +''' + +from cryptography.hazmat.backends import default_backend +from cryptography.hazmat.primitives.serialization import load_der_private_key +from default import * + + +class Verifier(Base64Argument): + + def __init__(self, arg): + super().__init__(arg) + + def key(self): + return 1 + + +class Salt(Base64Argument): + + def __init__(self, arg): + super().__init__(arg) + + def key(self): + return 2 + + +class IterationCount(IntArgument): + + def __init__(self, arg): + super().__init__(arg) + + def key(self): + return 3 + + +class DacPKey(FileArgument): + + def __init__(self, arg): + super().__init__(arg) + self.private_key = None + + def key(self): + return 4 + + def length(self): + assert (self.private_key is not None) + return len(self.private_key) + + def encode(self): + assert (self.private_key is not None) + return self.private_key + + def generate_private_key(self, password): + keys = load_der_private_key(self.val, password, backend=default_backend()) + self.private_key = keys.private_numbers().private_value.to_bytes( + 32, byteorder='big' + ) + + +class DacCert(FileArgument): + + def __init__(self, arg): + super().__init__(arg) + + def key(self): + return 5 + + +class PaiCert(FileArgument): + + def __init__(self, arg): + super().__init__(arg) + + def key(self): + return 6 + + +class Discriminator(IntArgument): + + def __init__(self, arg): + super().__init__(arg) + + def key(self): + return 7 + + +class SetupPasscode(IntArgument): + + def __init__(self, arg): + super().__init__(arg) + + def key(self): + return 8 + + +class VendorId(IntArgument): + + def __init__(self, arg): + super().__init__(arg) + + def key(self): + return 9 + + def length(self): + return 2 + + +class ProductId(IntArgument): + + def __init__(self, arg): + super().__init__(arg) + + def key(self): + return 10 + + def length(self): + return 2 + + +class CertDeclaration(FileArgument): + + def __init__(self, arg): + super().__init__(arg) + + def key(self): + return 11 + + +class VendorName(StrArgument): + + def __init__(self, arg): + super().__init__(arg) + + def key(self): + return 12 + + +class ProductName(StrArgument): + + def __init__(self, arg): + super().__init__(arg) + + def key(self): + return 13 + + +class SerialNum(StrArgument): + + def __init__(self, arg): + super().__init__(arg) + + def key(self): + return 14 + + +class ManufacturingDate(StrArgument): + + def __init__(self, arg): + super().__init__(arg) + + def key(self): + return 15 + + def max_length(self): + return 16 + + +class HardwareVersion(IntArgument): + + def __init__(self, arg): + super().__init__(arg) + + def key(self): + return 16 + + def length(self): + return 2 + + +class HardwareVersionStr(StrArgument): + + def __init__(self, arg): + super().__init__(arg) + + def key(self): + return 17 + + def max_length(self): + return 64 + + +class UniqueId(StrArgument): + + def __init__(self, arg): + super().__init__(arg) + + def key(self): + return 18 + + +class PartNumber(StrArgument): + + def __init__(self, arg): + super().__init__(arg) + + def key(self): + return 19 + + +class ProductURL(StrArgument): + + def __init__(self, arg): + super().__init__(arg) + + def key(self): + return 20 + + def max_length(self): + return 256 + + +class ProductLabel(StrArgument): + + def __init__(self, arg): + super().__init__(arg) + + def key(self): + return 21 + + def max_length(self): + return 64 diff --git a/scripts/tools/nxp/factory_data_generator/default.py b/scripts/tools/nxp/factory_data_generator/default.py new file mode 100644 index 00000000000000..c2c3b39d615bc2 --- /dev/null +++ b/scripts/tools/nxp/factory_data_generator/default.py @@ -0,0 +1,132 @@ +#!/usr/bin/env python3 +# +# Copyright (c) 2022 Project CHIP Authors +# All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +'''This file should contain default argument classes. + +Base class is InputArgument. It defines the abstract interface to be +implemented and offers a way to compute a KLV value through output(). +Other classes that derive InputArgument directly will be referenced +as default classes throughout the docstrings. + +The default classes should not be used to instantiate arguments. +If one wants to add another argument, a custom class should be derived +from one of the default classes. +''' + +import base64 +import logging +import sys + + +class InputArgument: + '''Base class for any input argument that will be added to KLV. + + The user will define its arguments as instances of InputArgument + by setting the "type" attribute of ArgumentParser add_argument to + an instance of a derived class. This means that all derived classes + must accept an additional "arg" parameter in the constructor. In the + end, the list of arguments will be parsed into objects derived from + InputArgument (or default derived classes), which decouples the object + creation from its processing. + + Abstract methods: + key: Should be overwritten by final classes to return a "magic number". + length: Can be overwritten by default classes to specify a default value + (e.g. int arguments with a default length value of 4); can also + be overwritten by final classes to specify a custom value for a + certain argument. + encode: Should be overwritten to generate the correct bytes array from + its internal value. + + Main usage is to iterate over an iterable entity of InputArguments and call + the output() method to generate the (K, L, V) tuple. Note that the output() + method should not be implemented, since its a common functionality across + all InputArgument classes. + ''' + + def __init__(self): + self.val = None + + def key(self): + logging.error("key() should be implemented in derived classes.") + + def length(self): + logging.error("length() should be implemented in derived classes.") + + def encode(self): + logging.error("encode() should be implemented in derived classes.") + + def output(self): + out = (self.key(), self.length(), self.encode()) + logging.info("'{}' length: {}".format(type(self).__name__, self.length())) + return out + + +class IntArgument(InputArgument): + + def __init__(self, arg): + super().__init__() + self.val = int(arg, 0) + + def length(self): + return 4 + + def encode(self): + return self.val.to_bytes(self.length(), "little") + + +class Base64Argument(InputArgument): + + def __init__(self, arg): + super().__init__() + self.val = base64.b64decode(arg) + + def length(self): + return len(self.encode()) + + def encode(self): + return base64.b64encode(self.val) + + +class StrArgument(InputArgument): + + def __init__(self, arg): + super().__init__() + self.val = str(arg) + + def length(self): + return len(self.encode()) + + def encode(self): + return str.encode(self.val) + + def max_length(self): + return 32 + + +class FileArgument(InputArgument): + + def __init__(self, arg): + super().__init__() + with open(arg, "rb") as _file: + self.val = _file.read() + + def length(self): + return len(self.val) + + def encode(self): + return self.val diff --git a/scripts/tools/nxp/factory_data_generator/generate.py b/scripts/tools/nxp/factory_data_generator/generate.py new file mode 100755 index 00000000000000..24beb361a31c13 --- /dev/null +++ b/scripts/tools/nxp/factory_data_generator/generate.py @@ -0,0 +1,236 @@ +#!/usr/bin/env python3 +# +# Copyright (c) 2022 Project CHIP Authors +# All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +import argparse +import hashlib +import logging +import os +import subprocess +import sys + +from custom import * +from default import InputArgument + + +def set_logger(): + stdout_handler = logging.StreamHandler(stream=sys.stdout) + logging.basicConfig( + level=logging.DEBUG, + format='[%(levelname)s] %(message)s', + handlers=[stdout_handler] + ) + + +class Spake2p: + + def __init__(self): + pass + + def generate(self, args): + params = self._generate_params(args) + args.spake2p_verifier = Verifier(params["Verifier"]) + args.salt = Salt(params["Salt"]) + args.it = IterationCount(params["Iteration Count"]) + + def _generate_params(self, args): + cmd = [ + args.spake2p_path, "gen-verifier", + "--iteration-count", str(args.it.val), + "--salt", args.salt.encode(), + "--pin-code", str(args.passcode.val), + "--out", "-" + ] + + out = subprocess.run(cmd, check=True, stdout=subprocess.PIPE).stdout + out = out.decode("utf-8").splitlines() + return dict(zip(out[0].split(','), out[1].split(','))) + + +class KlvGenerator: + + def __init__(self, args): + self.args = args + self._validate_args() + self.spake2p = Spake2p() + if self.args.spake2p_verifier is None: + self.spake2p.generate(self.args) + self.args.dac_key.generate_private_key(self.args.dac_key_password) + + def _validate_args(self): + if self.args.dac_key_password is None: + logging.warning( + "DAC Key password not provided. It means DAC Key is not protected." + ) + + str_args = [obj for key, obj in vars(self.args).items() if isinstance(obj, StrArgument)] + for str_arg in str_args: + logging.info("key: {} len: {} maxlen: {}".format(str_arg.key(), str_arg.length(), str_arg.max_length())) + assert str_arg.length() <= str_arg.max_length() + + def generate(self): + '''Return a list of (K, L, V) tuples. + + args is essentially a dict, so the entries are not ordered. + Sort the objects to ensure the same order of KLV data every + time (sorted by key), thus ensuring that SHA256 can be used + correctly to compare two output binaries. + + The new list will contain only InputArgument objects, which + generate a (K, L, V) tuple through output() method. + ''' + data = list() + + data = [obj for key, obj in vars(self.args).items() if isinstance(obj, InputArgument)] + data = [arg.output() for arg in sorted(data, key=lambda x: x.key())] + + return data + + def to_bin(self, klv, out, aes128_key): + fullContent = bytearray() + with open(out, "wb") as file: + for entry in klv: + fullContent += entry[0].to_bytes(1, "little") + fullContent += entry[1].to_bytes(2, "little") + fullContent += entry[2] + size = len(fullContent) + + if (aes128_key is None): + # Calculate 4 bytes of hashing + hashing = hashlib.sha256(fullContent).hexdigest() + hashing = hashing[0:8] + logging.info("4 byte section hash (for integrity check): {}".format(hashing)) + + # Add 4 bytes of hashing to generated binary to check for integrity + fullContent = bytearray.fromhex(hashing) + fullContent + + # Add length of data to binary to know how to calculate SHA on embedded + fullContent = size.to_bytes(4, "little") + fullContent + + # Add hash id + hashId = bytearray.fromhex("CE47BA5E") + hashId.reverse() + fullContent = hashId + fullContent + + size = len(fullContent) + + logging.info("Size of final generated binary is: {} bytes".format(size)) + file.write(fullContent) + else: + # In case a aes128_key is given the data will be encrypted + # Always add a padding to be 16 bytes aligned + padding_len = size % 16 + padding_len = 16 - padding_len + padding_bytes = bytearray(padding_len) + logging.info("(Before padding) Size of generated binary is: {} bytes".format(size)) + fullContent += padding_bytes + size = len(fullContent) + logging.info("(After padding) Size of generated binary is: {} bytes".format(size)) + from Crypto.Cipher import AES + cipher = AES.new(bytes.fromhex(aes128_key), AES.MODE_ECB) + fullContentCipher = cipher.encrypt(fullContent) + + # Add 4 bytes of hashing to generated binary to check for integrity + hashing = hashlib.sha256(fullContent).hexdigest() + hashing = hashing[0:8] + logging.info("4 byte section hash (for integrity check): {}".format(hashing)) + fullContentCipher = bytearray.fromhex(hashing) + fullContentCipher + + # Add length of data to binary to know how to calculate SHA on embedded + fullContentCipher = size.to_bytes(4, "little") + fullContentCipher + + # Add hash id + hashId = bytearray.fromhex("CE47BA5E") + hashId.reverse() + fullContentCipher = hashId.reverse() + fullContentCipher + + size = len(fullContentCipher) + + logging.info("Size of final generated binary is: {} bytes".format(size)) + file.write(fullContentCipher) + + out_hash = hashlib.sha256(fullContent).hexdigest() + logging.info("SHA256 of generated binary: {}".format(out_hash)) + + +def main(): + set_logger() + parser = argparse.ArgumentParser(description="NXP Factory Data Generator") + optional = parser + required = parser.add_argument_group("required arguments") + + required.add_argument("-i", "--it", required=True, type=IterationCount, + help="[int | hex] Spake2 Iteration Counter") + required.add_argument("-s", "--salt", required=True, type=Salt, + help="[base64 str] Spake2 Salt") + required.add_argument("-p", "--passcode", required=True, type=SetupPasscode, + help="[int | hex] PASE session passcode") + required.add_argument("-d", "--discriminator", required=True, type=Discriminator, + help="[int | hex] BLE Pairing discriminator") + required.add_argument("--vid", required=True, type=VendorId, + help="[int | hex] Vendor Identifier (VID)") + required.add_argument("--pid", required=True, type=ProductId, + help="[int | hex] Product Identifier (PID)") + required.add_argument("--vendor_name", required=True, type=VendorName, + help="[str] Vendor Name") + required.add_argument("--product_name", required=True, type=ProductName, + help="[str] Product Name") + required.add_argument("--hw_version", required=True, type=HardwareVersion, + help="[int | hex] Hardware version as number") + required.add_argument("--hw_version_str", required=True, type=HardwareVersionStr, + help="[str] Hardware version as string") + required.add_argument("--cert_declaration", required=True, type=CertDeclaration, + help="[path] Path to Certification Declaration in DER format") + required.add_argument("--dac_cert", required=True, type=DacCert, + help="[path] Path to DAC certificate in DER format") + required.add_argument("--dac_key", required=True, type=DacPKey, + help="[path] Path to DAC key in DER format") + required.add_argument("--pai_cert", required=True, type=PaiCert, + help="[path] Path to PAI certificate in DER format") + required.add_argument("--spake2p_path", required=True, type=str, + help="[path] Path to spake2p tool") + required.add_argument("--out", required=True, type=str, + help="[path] Path to output binary") + + optional.add_argument("--dac_key_password", type=str, + help="[path] Password to decode DAC Key if available") + optional.add_argument("--spake2p_verifier", type=Verifier, + help="[base64 str] Already generated spake2p verifier") + optional.add_argument("--aes128_key", + help="[hex] AES 128 bits key used to encrypt the whole dataset") + optional.add_argument("--date", type=ManufacturingDate, + help="[str] Manufacturing Date (YYYY-MM-DD)") + optional.add_argument("--part_number", type=PartNumber, + help="[str] PartNumber as String") + optional.add_argument("--product_url", type=ProductURL, + help="[str] ProductURL as String") + optional.add_argument("--product_label", type=ProductLabel, + help="[str] ProductLabel as String") + optional.add_argument("--serial_num", type=SerialNum, + help="[str] Serial Number") + optional.add_argument("--unique_id", type=UniqueId, + help="[str] Unique identifier for the device") + + args = parser.parse_args() + + klv = KlvGenerator(args) + data = klv.generate() + klv.to_bin(data, args.out, args.aes128_key) + + +if __name__ == "__main__": + main() diff --git a/scripts/tools/nxp/generate_nxp_chip_factory_bin.py b/scripts/tools/nxp/generate_nxp_chip_factory_bin.py deleted file mode 100755 index 0db2f2ced7f8e2..00000000000000 --- a/scripts/tools/nxp/generate_nxp_chip_factory_bin.py +++ /dev/null @@ -1,171 +0,0 @@ -#!/usr/bin/env python3 -# -# Copyright (c) 2022 Project CHIP Authors -# All rights reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. -# - -import argparse -import base64 -import logging -import os -import subprocess - -from cryptography.hazmat.backends import default_backend -from cryptography.hazmat.primitives.serialization import load_der_private_key - -# Keys used to store KLV -KLV_KEYS = { - "Verifier": 1, - "Salt": 2, - "IC": 3, - "DacPKey": 4, - "DacCert": 5, - "PaiCert": 6, - "Disc": 7 -} - - -def type_int(n): - return int(n, 0) - - -def read_der(der_file): - with open(der_file, "rb") as file: - return file.read() - - -def generate_spake2_params(spake2_path, passcode, it, salt): - cmd = [ - spake2_path, "gen-verifier", "--iteration-count", - str(it), "--salt", - str(salt), "--pin-code", - str(passcode), "--out", "-" - ] - - out = subprocess.run(cmd, check=True, stdout=subprocess.PIPE).stdout - out = out.decode("utf-8").splitlines() - return dict(zip(out[0].split(','), out[1].split(','))) - - -def get_private_key_der(der_file, password): - data = read_der(der_file) - keys = load_der_private_key(data, password, backend=default_backend()) - private_key = keys.private_numbers().private_value.to_bytes( - 32, byteorder='big') - return private_key - - -def generate_klv(spake2_params, args): - klv = [] - - spake2p_verifier = str.encode(spake2_params["Verifier"]) - spake2p_salt = str.encode(spake2_params["Salt"]) - spake2p_it = int(spake2_params["Iteration Count"]).to_bytes(4, "little") - dac_private_key = get_private_key_der(args.dac_key, args.dac_key_password) - dac_cert = read_der(args.dac_cert) - pai_cert = read_der(args.pai_cert) - discriminator = int(args.discrimnator).to_bytes(4, "little") - - klv.append((KLV_KEYS["Verifier"], len(spake2p_verifier), spake2p_verifier)) - print("Verifier length: ", len(spake2p_verifier)) - klv.append((KLV_KEYS["Salt"], len(spake2p_salt), spake2p_salt)) - print("SALT length: ", len(spake2p_salt)) - klv.append((KLV_KEYS["IC"], 4, spake2p_it)) - klv.append((KLV_KEYS["DacPKey"], len(dac_private_key), dac_private_key)) - print("DAC Private Key length: ", len(dac_private_key)) - klv.append((KLV_KEYS["DacCert"], len(dac_cert), dac_cert)) - print("DAC Certificate length: ", len(dac_cert)) - klv.append((KLV_KEYS["PaiCert"], len(pai_cert), pai_cert)) - print("PAI Certificate length: ", len(pai_cert)) - klv.append((KLV_KEYS["Disc"], 4, discriminator)) - return klv - - -def klv_to_bin(klv, out): - with open(out, "wb") as file: - for entry in klv: - file.write(entry[0].to_bytes(1, "little")) - file.write(entry[1].to_bytes(2, "little")) - file.write(entry[2]) - size = file.seek(0, os.SEEK_END) - print("Size of generated binary is:", size, "bytes") - - -def main(): - parser = argparse.ArgumentParser(description="NXP Factory Data Generator") - - parser.add_argument("-i", - "--it", - required=True, - type=type_int, - help="[int | hex] Spake2 Iteration Counter") - parser.add_argument("-s", - "--salt", - type=str, - required=True, - help="[ascii] Spake2 Salt") - parser.add_argument("-p", - "--passcode", - type=type_int, - required=True, - help="[int | hex] PASE session passcode") - parser.add_argument("-d", - "--discrimnator", - type=type_int, - required=True, - help="[int | hex] BLE Pairing discrimantor") - parser.add_argument("--dac_cert", - type=str, - required=True, - help="[path] Path to DAC certificate in DER format") - parser.add_argument("--dac_key", - type=str, - required=True, - help="[path] Path to DAC key in DER format") - parser.add_argument("--dac_key_password", - type=str, - required=False, - help="[path] Password to decode DAC Key if available") - parser.add_argument("--pai_cert", - type=str, - required=True, - help="[path] Path to PAI certificate in DER format") - parser.add_argument("--spake2p_path", - type=str, - required=True, - help="[path] Path to Spake2P") - parser.add_argument("--out", - type=str, - required=True, - help="[path] Path to output binary") - - args = parser.parse_args() - - if args.dac_key_password is None: - logging.warning( - "DAC Key password not provided. It means DAC Key is not protected." - ) - - spake2_params = generate_spake2_params(args.spake2p_path, args.passcode, - args.it, args.salt) - klv = generate_klv(spake2_params, args) - klv_to_bin(klv, args.out) - - -if __name__ == "__main__": - main() - -# Example usage: -# python3 generate_nxp_chip_factory_bin.py -i 10000 -s ABCDEFGHIJKLMNOPQRS -p 14014 -d 1000 --dac_cert /home/john/nxp/connectedhomeip_nxp/Chip-DAC-NXP-Cert.der --dac_key /home/john/nxp/connectedhomeip_nxp/Chip-DAC-NXP-Key.der --pai_cert /home/john/nxp/connectedhomeip_nxp/Chip-PAI-NXP-Cert.der --spake2p_path /home/john/nxp/connectedhomeip_nxp/out/host/spake2p --out out.bin diff --git a/scripts/tools/zap_regen_all.py b/scripts/tools/zap_regen_all.py index 1a4e5768bb209a..243198925713fd 100755 --- a/scripts/tools/zap_regen_all.py +++ b/scripts/tools/zap_regen_all.py @@ -293,7 +293,7 @@ def getGlobalTemplatesTargets(): generate_subdir = example_name # Special casing lighting app because separate folders - if example_name == "lighting-app": + if example_name == "lighting-app" or example_name == "lock-app": if 'nxp' in str(filepath): generate_subdir = f"{example_name}/nxp" diff --git a/src/crypto/BUILD.gn b/src/crypto/BUILD.gn index df1ac5851cfffd..8c8b6961ace5d1 100644 --- a/src/crypto/BUILD.gn +++ b/src/crypto/BUILD.gn @@ -32,9 +32,9 @@ if (chip_crypto == "") { assert( chip_crypto == "mbedtls" || chip_crypto == "psa" || - chip_crypto == "openssl" || chip_crypto == "tinycrypt" || - chip_crypto == "boringssl" || chip_crypto == "platform", - "Please select a valid crypto implementation: mbedtls, psa, openssl, tinycrypt, boringssl, platform") + chip_crypto == "openssl" || chip_crypto == "boringssl" || + chip_crypto == "platform", + "Please select a valid crypto implementation: mbedtls, psa, openssl, boringssl, platform") buildconfig_header("crypto_buildconfig") { header = "CryptoBuildConfig.h" @@ -130,16 +130,6 @@ if (chip_crypto == "openssl") { public_deps += [ "${mbedtls_root}:mbedtls" ] } } -} else if (chip_crypto == "tinycrypt") { - import("//build_overrides/mbedtls.gni") - - source_set("cryptopal_tinycrypt") { - sources = [ "CHIPCryptoPALTinyCrypt.cpp" ] - public_deps = [ - ":public_headers", - "${mbedtls_root}:mbedtls", - ] - } } static_library("crypto") { @@ -167,8 +157,6 @@ static_library("crypto") { public_deps += [ ":cryptopal_openssl" ] } else if (chip_crypto == "boringssl") { public_deps += [ ":cryptopal_boringssl" ] - } else if (chip_crypto == "tinycrypt") { - public_deps += [ ":cryptopal_tinycrypt" ] } else if (chip_crypto == "platform") { # Platform implementation is responsible for bringing their # own implementation and dependencies diff --git a/src/crypto/crypto.gni b/src/crypto/crypto.gni index b0fc8a9dfe5965..4fc63b800826b8 100644 --- a/src/crypto/crypto.gni +++ b/src/crypto/crypto.gni @@ -13,7 +13,7 @@ # limitations under the License. declare_args() { - # Crypto implementation: mbedtls, openssl, tinycrypt, boringssl, platform. + # Crypto implementation: mbedtls, openssl, boringssl, platform. chip_crypto = "" chip_with_se05x = 0 diff --git a/src/lib/shell/streamer_k32w.cpp b/src/lib/shell/streamer_k32w.cpp index 68523e7a2c44ff..fadcb82f1913e1 100644 --- a/src/lib/shell/streamer_k32w.cpp +++ b/src/lib/shell/streamer_k32w.cpp @@ -23,7 +23,6 @@ #include #include -#include "app_config.h" #include #include diff --git a/src/platform/nxp/common/CHIPNXPPlatformDefaultConfig.h b/src/platform/nxp/common/CHIPNXPPlatformDefaultConfig.h new file mode 100644 index 00000000000000..6070fbc84dcdb7 --- /dev/null +++ b/src/platform/nxp/common/CHIPNXPPlatformDefaultConfig.h @@ -0,0 +1,227 @@ +/* + * + * Copyright (c) 2020-2022 Project CHIP Authors + * Copyright (c) 2020 Google LLC. + * All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/** + * @file + * Platform-specific configuration overrides for CHIP on + * NXP platforms. + */ + +#pragma once + +#include + +// ==================== General Platform Adaptations ==================== + +#ifndef CHIP_CONFIG_ABORT +#define CHIP_CONFIG_ABORT() abort() +#endif // CHIP_CONFIG_ABORT + +#ifndef CHIP_CONFIG_PERSISTED_STORAGE_KEY_TYPE +#define CHIP_CONFIG_PERSISTED_STORAGE_KEY_TYPE uint16_t +#endif // CHIP_CONFIG_PERSISTED_STORAGE_KEY_TYPE + +#ifndef CHIP_CONFIG_PERSISTED_STORAGE_ENC_MSG_CNTR_ID +#define CHIP_CONFIG_PERSISTED_STORAGE_ENC_MSG_CNTR_ID 1 +#endif // CHIP_CONFIG_PERSISTED_STORAGE_ENC_MSG_CNTR_ID + +#ifndef CHIP_CONFIG_PERSISTED_STORAGE_MAX_KEY_LENGTH +#define CHIP_CONFIG_PERSISTED_STORAGE_MAX_KEY_LENGTH 2 +#endif // CHIP_CONFIG_PERSISTED_STORAGE_MAX_KEY_LENGTH + +#ifndef CHIP_CONFIG_LIFETIIME_PERSISTED_COUNTER_KEY +#define CHIP_CONFIG_LIFETIIME_PERSISTED_COUNTER_KEY 0x01 +#endif // CHIP_CONFIG_LIFETIIME_PERSISTED_COUNTER_KEY + +#ifndef CHIP_CONFIG_PERSISTED_STORAGE_KEY_GLOBAL_MESSAGE_COUNTER +#define CHIP_CONFIG_PERSISTED_STORAGE_KEY_GLOBAL_MESSAGE_COUNTER 0x2 +#endif // CHIP_CONFIG_PERSISTED_STORAGE_KEY_GLOBAL_MESSAGE_COUNTER + +#ifndef CHIP_CONFIG_TIME_ENABLE_CLIENT +#define CHIP_CONFIG_TIME_ENABLE_CLIENT 1 +#endif // CHIP_CONFIG_TIME_ENABLE_CLIENT + +#ifndef CHIP_CONFIG_TIME_ENABLE_SERVER +#define CHIP_CONFIG_TIME_ENABLE_SERVER 0 +#endif // CHIP_CONFIG_TIME_ENABLE_SERVER + +#ifndef CHIP_CONFIG_ERROR_CLASS +#define CHIP_CONFIG_ERROR_CLASS 1 +#endif // CHIP_CONFIG_ERROR_CLASS + +#ifndef CHIP_CONFIG_SHA256_CONTEXT_SIZE +#define CHIP_CONFIG_SHA256_CONTEXT_SIZE (sizeof(unsigned int) * 76) +#endif // CHIP_CONFIG_SHA256_CONTEXT_SIZE + +// ==================== Security Adaptations ==================== + +#ifndef CHIP_CONFIG_USE_OPENSSL_ECC +#define CHIP_CONFIG_USE_OPENSSL_ECC 0 +#endif // CHIP_CONFIG_USE_OPENSSL_ECC + +#ifndef CHIP_CONFIG_USE_MICRO_ECC +#define CHIP_CONFIG_USE_MICRO_ECC 0 +#endif // CHIP_CONFIG_USE_MICRO_ECC + +#ifndef CHIP_CONFIG_HASH_IMPLEMENTATION_OPENSSL +#define CHIP_CONFIG_HASH_IMPLEMENTATION_OPENSSL 0 +#endif // CHIP_CONFIG_HASH_IMPLEMENTATION_OPENSSL + +#ifndef CHIP_CONFIG_HASH_IMPLEMENTATION_MINCRYPT +#define CHIP_CONFIG_HASH_IMPLEMENTATION_MINCRYPT 1 +#endif // CHIP_CONFIG_HASH_IMPLEMENTATION_MINCRYPT + +#ifndef CHIP_CONFIG_HASH_IMPLEMENTATION_MBEDTLS +#define CHIP_CONFIG_HASH_IMPLEMENTATION_MBEDTLS 0 +#endif // CHIP_CONFIG_HASH_IMPLEMENTATION_MBEDTLS + +#ifndef CHIP_CONFIG_HASH_IMPLEMENTATION_PLATFORM +#define CHIP_CONFIG_HASH_IMPLEMENTATION_PLATFORM 0 +#endif // CHIP_CONFIG_HASH_IMPLEMENTATION_PLATFORM + +#ifndef CHIP_CONFIG_AES_IMPLEMENTATION_OPENSSL +#define CHIP_CONFIG_AES_IMPLEMENTATION_OPENSSL 0 +#endif // CHIP_CONFIG_AES_IMPLEMENTATION_OPENSSL + +#ifndef CHIP_CONFIG_AES_IMPLEMENTATION_AESNI +#define CHIP_CONFIG_AES_IMPLEMENTATION_AESNI 0 +#endif // CHIP_CONFIG_AES_IMPLEMENTATION_AESNI + +#ifndef CHIP_CONFIG_AES_IMPLEMENTATION_MBEDTLS +#define CHIP_CONFIG_AES_IMPLEMENTATION_MBEDTLS 0 +#endif // CHIP_CONFIG_AES_IMPLEMENTATION_MBEDTLS + +#ifndef CHIP_CONFIG_AES_IMPLEMENTATION_PLATFORM +#define CHIP_CONFIG_AES_IMPLEMENTATION_PLATFORM 1 +#endif // CHIP_CONFIG_AES_IMPLEMENTATION_PLATFORM + +#ifndef CHIP_CONFIG_RNG_IMPLEMENTATION_OPENSSL +#define CHIP_CONFIG_RNG_IMPLEMENTATION_OPENSSL 0 +#endif // CHIP_CONFIG_RNG_IMPLEMENTATION_OPENSSL + +#ifndef CHIP_CONFIG_RNG_IMPLEMENTATION_CHIPDRBG +#define CHIP_CONFIG_RNG_IMPLEMENTATION_CHIPDRBG 1 +#endif // CHIP_CONFIG_RNG_IMPLEMENTATION_CHIPDRBG + +#ifndef CHIP_CONFIG_RNG_IMPLEMENTATION_PLATFORM +#define CHIP_CONFIG_RNG_IMPLEMENTATION_PLATFORM 0 +#endif // CHIP_CONFIG_RNG_IMPLEMENTATION_PLATFORM + +#ifndef CHIP_CONFIG_ENABLE_PASE_INITIATOR +#define CHIP_CONFIG_ENABLE_PASE_INITIATOR 0 +#endif // CHIP_CONFIG_ENABLE_PASE_INITIATOR + +#ifndef CHIP_CONFIG_ENABLE_PASE_RESPONDER +#define CHIP_CONFIG_ENABLE_PASE_RESPONDER 1 +#endif // CHIP_CONFIG_ENABLE_PASE_RESPONDER + +#ifndef CHIP_CONFIG_ENABLE_CASE_INITIATOR +#define CHIP_CONFIG_ENABLE_CASE_INITIATOR 1 +#endif // CHIP_CONFIG_ENABLE_CASE_INITIATOR + +#ifndef CHIP_CONFIG_SUPPORT_PASE_CONFIG0 +#define CHIP_CONFIG_SUPPORT_PASE_CONFIG0 0 +#endif // CHIP_CONFIG_SUPPORT_PASE_CONFIG0 + +#ifndef CHIP_CONFIG_SUPPORT_PASE_CONFIG1 +#define CHIP_CONFIG_SUPPORT_PASE_CONFIG1 0 +#endif // CHIP_CONFIG_SUPPORT_PASE_CONFIG1 + +#ifndef CHIP_CONFIG_SUPPORT_PASE_CONFIG2 +#define CHIP_CONFIG_SUPPORT_PASE_CONFIG2 0 +#endif // CHIP_CONFIG_SUPPORT_PASE_CONFIG2 + +#ifndef CHIP_CONFIG_SUPPORT_PASE_CONFIG3 +#define CHIP_CONFIG_SUPPORT_PASE_CONFIG3 0 +#endif // CHIP_CONFIG_SUPPORT_PASE_CONFIG3 + +#ifndef CHIP_CONFIG_SUPPORT_PASE_CONFIG4 +#define CHIP_CONFIG_SUPPORT_PASE_CONFIG4 1 +#endif // CHIP_CONFIG_SUPPORT_PASE_CONFIG4 + +#ifndef CHIP_CONFIG_ENABLE_KEY_EXPORT_INITIATOR +#define CHIP_CONFIG_ENABLE_KEY_EXPORT_INITIATOR 0 +#endif // CHIP_CONFIG_ENABLE_KEY_EXPORT_INITIATOR + +#ifndef CHIP_CONFIG_ENABLE_PROVISIONING_BUNDLE_SUPPORT +#define CHIP_CONFIG_ENABLE_PROVISIONING_BUNDLE_SUPPORT 0 +#endif // CHIP_CONFIG_ENABLE_PROVISIONING_BUNDLE_SUPPORT + +// ==================== General Configuration Overrides ==================== + +#ifndef CHIP_CONFIG_MAX_PEER_NODES +#define CHIP_CONFIG_MAX_PEER_NODES 16 +#endif // CHIP_CONFIG_MAX_PEER_NODES + +#ifndef CHIP_CONFIG_MAX_UNSOLICITED_MESSAGE_HANDLERS +#define CHIP_CONFIG_MAX_UNSOLICITED_MESSAGE_HANDLERS 16 +#endif // CHIP_CONFIG_MAX_UNSOLICITED_MESSAGE_HANDLERS + +#ifndef CHIP_CONFIG_MAX_EXCHANGE_CONTEXTS +#define CHIP_CONFIG_MAX_EXCHANGE_CONTEXTS 8 +#endif // CHIP_CONFIG_MAX_EXCHANGE_CONTEXTS + +#ifndef CHIP_CONFIG_RMP_TIMER_DEFAULT_PERIOD_SHIFT +#define CHIP_CONFIG_RMP_TIMER_DEFAULT_PERIOD_SHIFT 6 +#endif // CHIP_CONFIG_RMP_TIMER_DEFAULT_PERIOD_SHIFT + +#ifndef CHIP_LOG_FILTERING +#define CHIP_LOG_FILTERING 0 +#endif // CHIP_LOG_FILTERING + +#ifndef CHIP_CONFIG_BDX_MAX_NUM_TRANSFERS +#define CHIP_CONFIG_BDX_MAX_NUM_TRANSFERS 1 +#endif // CHIP_CONFIG_BDX_MAX_NUM_TRANSFERS + +// ==================== Security Configuration Overrides ==================== + +#ifndef CHIP_CONFIG_MAX_APPLICATION_GROUPS +#define CHIP_CONFIG_MAX_APPLICATION_GROUPS 4 +#endif // CHIP_CONFIG_MAX_APPLICATION_GROUPS + +#ifndef CHIP_CONFIG_DEBUG_CERT_VALIDATION +#define CHIP_CONFIG_DEBUG_CERT_VALIDATION 0 +#endif // CHIP_CONFIG_DEBUG_CERT_VALIDATION + +#ifndef CHIP_CONFIG_ENABLE_CASE_RESPONDER +#define CHIP_CONFIG_ENABLE_CASE_RESPONDER 1 +#endif // CHIP_CONFIG_ENABLE_CASE_RESPONDER + +// ==================== WDM Configuration Overrides ==================== + +#ifndef WDM_MAX_NUM_SUBSCRIPTION_CLIENTS +#define WDM_MAX_NUM_SUBSCRIPTION_CLIENTS 2 +#endif // WDM_MAX_NUM_SUBSCRIPTION_CLIENTS + +#ifndef WDM_MAX_NUM_SUBSCRIPTION_HANDLERS +#define WDM_MAX_NUM_SUBSCRIPTION_HANDLERS 2 +#endif // WDM_MAX_NUM_SUBSCRIPTION_HANDLERS + +#ifndef WDM_PUBLISHER_MAX_NOTIFIES_IN_FLIGHT +#define WDM_PUBLISHER_MAX_NOTIFIES_IN_FLIGHT 2 +#endif // WDM_PUBLISHER_MAX_NOTIFIES_IN_FLIGHT + +// ==================== Other Configuration Overrides ==================== + +#ifndef CHIP_CONFIG_RMP_DEFAULT_MAX_RETRANS +/* + * Increasing the default value to 10 to handle potential scenario where there is latency with the radio used + */ +#define CHIP_CONFIG_RMP_DEFAULT_MAX_RETRANS 10 +#endif diff --git a/src/crypto/CHIPCryptoPALTinyCrypt.cpp b/src/platform/nxp/common/crypto/CHIPCryptoPALTinyCrypt.cpp similarity index 96% rename from src/crypto/CHIPCryptoPALTinyCrypt.cpp rename to src/platform/nxp/common/crypto/CHIPCryptoPALTinyCrypt.cpp index fcce1f65e90a52..b7866f97af1de5 100644 --- a/src/crypto/CHIPCryptoPALTinyCrypt.cpp +++ b/src/platform/nxp/common/crypto/CHIPCryptoPALTinyCrypt.cpp @@ -17,10 +17,10 @@ /** * @file - * mbedTLS based implementation of CHIP crypto primitives + * mbedTLS and Tinycrypt based implementation of CHIP crypto primitives */ -#include "CHIPCryptoPAL.h" +#include "crypto/CHIPCryptoPAL.h" #include @@ -44,10 +44,10 @@ #include #include +#include +#include +#include #include -#include -#include -#include #include #include @@ -58,6 +58,10 @@ #include #include +#if gSecLibUseSha256Alt_d +#include "SecLib.h" +#endif + #include namespace chip { @@ -87,6 +91,12 @@ typedef struct mbedtls_entropy_context mEntropy; } EntropyContext; +typedef struct +{ + uint8_t private_key[NUM_ECC_BYTES]; + uint8_t public_key[2 * NUM_ECC_BYTES]; +} mbedtls_uecc_keypair; + static EntropyContext gsEntropyContext; static void _log_mbedTLS_error(int error_code) @@ -262,15 +272,16 @@ Hash_SHA256_stream::~Hash_SHA256_stream(void) CHIP_ERROR Hash_SHA256_stream::Begin(void) { mbedtls_sha256_context * const context = to_inner_hash_sha256_context(&mContext); - +#if gSecLibUseSha256Alt_d + SHA256_SW_Init(context); +#else #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); - +#endif return CHIP_NO_ERROR; } @@ -278,14 +289,16 @@ CHIP_ERROR Hash_SHA256_stream::AddData(const ByteSpan data) { mbedtls_sha256_context * const context = to_inner_hash_sha256_context(&mContext); +#if gSecLibUseSha256Alt_d + SHA256_SW_Update(context, Uint8::to_const_uchar(data.data()), data.size()); +#else #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); - +#endif return CHIP_NO_ERROR; } @@ -313,13 +326,16 @@ 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 gSecLibUseSha256Alt_d + SHA256_SW_Finish(context, Uint8::to_uchar(out_buffer.data())); +#else #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); +#endif out_buffer = out_buffer.SubSpan(0, kSHA256_Hash_Length); return CHIP_NO_ERROR; @@ -437,6 +453,20 @@ static EntropyContext * get_entropy_context() return &gsEntropyContext; } +static int strong_entropy_func(void * data, unsigned char * output, size_t len) +{ + int result = -1; +#if defined(MBEDTLS_NO_DEFAULT_ENTROPY_SOURCES) + size_t olen = 0; + EntropyContext * const ctxt = get_entropy_context(); + mbedtls_entropy_f_source_ptr trng_get_random = ctxt->mEntropy.source[0].f_source; + result = trng_get_random(NULL, Uint8::to_uchar(output), len, &olen); +#else + result = mbedtls_entropy_func(data, output, len); +#endif + return result; +} + static mbedtls_ctr_drbg_context * get_drbg_context() { EntropyContext * const context = get_entropy_context(); @@ -445,7 +475,7 @@ static mbedtls_ctr_drbg_context * get_drbg_context() if (!context->mDRBGSeeded) { - const int status = mbedtls_ctr_drbg_seed(drbgCtxt, mbedtls_entropy_func, &context->mEntropy, nullptr, 0); + const int status = mbedtls_ctr_drbg_seed(drbgCtxt, strong_entropy_func, &context->mEntropy, nullptr, 0); if (status != 0) { _log_mbedTLS_error(status); @@ -725,53 +755,10 @@ P256Keypair::~P256Keypair() 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_WELL_UNINITIALIZED); - - mbedtls_x509write_csr_set_key(&csr, &pk); - - mbedtls_x509write_csr_set_md_alg(&csr, MBEDTLS_MD_SHA256); - - // TODO: mbedTLS CSR parser fails if the subject name is not set (or if empty). - // CHIP Spec doesn't specify the subject name that can be used. - // Figure out the correct value and update this code. - result = mbedtls_x509write_csr_set_subject_name(&csr, "O=CSR"); - VerifyOrExit(result == 0, error = CHIP_ERROR_INTERNAL); - - result = mbedtls_x509write_csr_der(&csr, out_csr, csr_length, CryptoRNG, nullptr); - VerifyOrExit(result > 0, error = CHIP_ERROR_INTERNAL); - VerifyOrExit(CanCastTo(result), error = CHIP_ERROR_INTERNAL); - - out_length = static_cast(result); - result = 0; - VerifyOrExit(out_length <= csr_length, error = CHIP_ERROR_INTERNAL); - - if (csr_length != out_length) - { - // mbedTLS API writes the CSR at the end of the provided buffer. - // Let's move it to the start of the buffer. - size_t offset = csr_length - out_length; - memmove(out_csr, &out_csr[offset], out_length); - } - - csr_length = out_length; - -exit: - mbedtls_x509write_csr_free(&csr); - - _log_mbedTLS_error(result); - return error; + MutableByteSpan csr(out_csr, csr_length); + CHIP_ERROR err = GenerateCertificateSigningRequest(this, csr); + csr_length = (CHIP_NO_ERROR == err) ? csr.size() : 0; + return err; } CHIP_ERROR VerifyCertificateSigningRequest(const uint8_t * csr_buf, size_t csr_length, P256PublicKey & pubkey) @@ -1518,7 +1505,7 @@ CHIP_ERROR ExtractPubkeyFromX509Cert(const ByteSpan & certificate, Crypto::P256P VerifyOrExit(mbedtls_pk_get_type(&(mbed_cert.CHIP_CRYPTO_PAL_PRIVATE_X509(pk))) == MBEDTLS_PK_ECKEY, error = CHIP_ERROR_INVALID_ARGUMENT); - keypair = mbedtls_pk_uecc(mbed_cert.CHIP_CRYPTO_PAL_PRIVATE_X509(pk)); + keypair = (mbedtls_uecc_keypair *) (mbed_cert.CHIP_CRYPTO_PAL_PRIVATE_X509(pk)).pk_ctx; Uint8::to_uchar(pubkey)[0] = 0x04; // uncompressed type memcpy(Uint8::to_uchar(pubkey) + 1, keypair->public_key, 2 * NUM_ECC_BYTES); diff --git a/src/platform/nxp/k32w/common/CHIPDevicePlatformRamStorageConfig.h b/src/platform/nxp/k32w/common/CHIPDevicePlatformRamStorageConfig.h new file mode 100644 index 00000000000000..62d2490fa20092 --- /dev/null +++ b/src/platform/nxp/k32w/common/CHIPDevicePlatformRamStorageConfig.h @@ -0,0 +1,123 @@ +/* + * + * Copyright (c) 2022 Project CHIP Authors + * All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/** + * @file + * Configuration of RAM storage metadata: key IDs and NVM IDs. + */ + +/* Base key IDs used when creating new keys for RAM storage instances. */ +/** + * @def kKeyId_Factory + * + * Base key id used for factory RAM storage. + */ +#ifndef kKeyId_Factory +#define kKeyId_Factory (uint8_t) 0x01 +#endif + +/** + * @def kKeyId_Config + * + * Base key id used for config RAM storage. + */ +#ifndef kKeyId_Config +#define kKeyId_Config (uint8_t) 0x02 +#endif + +/** + * @def kKeyId_Counter + * + * Base key id used for counter RAM storage. + */ +#ifndef kKeyId_Counter +#define kKeyId_Counter (uint8_t) 0x03 +#endif + +/** + * @def kKeyId_KvsKeys + * + * Base key id used for KVS keys RAM storage. + */ +#ifndef kKeyId_KvsKeys +#define kKeyId_KvsKeys (uint8_t) 0x04 +#endif + +/** + * @def kKeyId_KvsValues + * + * Base key id used for KVS values RAM storage. + */ +#ifndef kKeyId_KvsValues +#define kKeyId_KvsValues (uint8_t) 0x05 +#endif + +/* PDM IDs used when defining RAM storage instances or RAM buffers (OT). */ +/** + * @def kNvmId_Factory + * + * PDM ID used for factory RAM storage. + */ +#ifndef kNvmId_Factory +#define kNvmId_Factory (uint16_t) 0x5001 +#endif + +/** + * @def kNvmId_Config + * + * PDM ID used for config RAM storage. + */ +#ifndef kNvmId_Config +#define kNvmId_Config (uint16_t) 0x5002 +#endif + +/** + * @def kNvmId_Counter + * + * PDM ID used for counter RAM storage. + */ +#ifndef kNvmId_Counter +#define kNvmId_Counter (uint16_t) 0x5003 +#endif + +/** + * @def kNvmId_KvsKeys + * + * PDM ID used for KVS keys RAM storage. + */ +#ifndef kNvmId_KvsKeys +#define kNvmId_KvsKeys (uint16_t) 0x6000 +#endif + +/** + * @def kNvmId_KvsValues + * + * PDM ID used for KVS values RAM storage. + */ +#ifndef kNvmId_KvsValues +#define kNvmId_KvsValues (uint16_t) 0x6001 +#endif + +/** + * @def kNvmId_OTConfigData + * + * PDM ID used for OT RAM buffer. + */ +#ifndef kNvmId_OTConfigData +#define kNvmId_OTConfigData (uint16_t) 0x4F00 +#endif diff --git a/src/platform/nxp/k32w/common/RamStorage.cpp b/src/platform/nxp/k32w/common/RamStorage.cpp index 716fc8dbec20b0..d02537ff6f4be5 100644 --- a/src/platform/nxp/k32w/common/RamStorage.cpp +++ b/src/platform/nxp/k32w/common/RamStorage.cpp @@ -15,44 +15,69 @@ * limitations under the License. */ +#include #include #include -namespace chip::DeviceLayer::Internal { +#include "pdm_ram_storage_glue.h" + +#if PDM_SAVE_IDLE +#include "fsl_os_abstraction.h" +#define mutex_lock(descr, timeout) OSA_MutexLock(descr->header.mutexHandle, timeout) +#define mutex_unlock(descr) OSA_MutexUnlock(descr->header.mutexHandle) +#define mutex_destroy(descr) OSA_MutexDestroy(descr->header.mutexHandle) +#else +#define mutex_lock(...) +#define mutex_unlock(...) +#define mutex_destroy(...) +#endif + +#if PDM_USE_DYNAMIC_MEMORY +#define ot_free otPlatFree +#else +#define ot_free(...) +#endif -RamStorage::Buffer RamStorage::sBuffer = nullptr; +namespace chip::DeviceLayer::Internal { -CHIP_ERROR RamStorage::Init(uint16_t aNvmId, uint16_t aInitialSize) +CHIP_ERROR RamStorage::Init(uint16_t aInitialSize) { - CHIP_ERROR err = CHIP_NO_ERROR; - sBuffer = getRamBuffer(aNvmId, aInitialSize); - if (!sBuffer) - { - err = CHIP_ERROR_NO_MEMORY; - } + CHIP_ERROR err; - return err; + mBuffer = getRamBuffer(mPdmId, aInitialSize); + + return mBuffer ? CHIP_NO_ERROR : CHIP_ERROR_NO_MEMORY; } void RamStorage::FreeBuffer() { - if (sBuffer) + if (mBuffer) { - free(sBuffer); - sBuffer = nullptr; + mutex_lock(mBuffer, osaWaitForever_c); + if (mBuffer->buffer) + { + ot_free(mBuffer->buffer); + mBuffer->buffer = nullptr; + } + mutex_unlock(mBuffer); + mutex_destroy(mBuffer); + ot_free(mBuffer); + mBuffer = nullptr; } } -CHIP_ERROR RamStorage::Read(uint16_t aKey, int aIndex, uint8_t * aValue, uint16_t * aValueLength) +CHIP_ERROR RamStorage::Read(uint16_t aKey, int aIndex, uint8_t * aValue, uint16_t * aValueLength) const { CHIP_ERROR err; rsError status; - status = ramStorageGet(sBuffer, aKey, aIndex, aValue, aValueLength); + mutex_lock(mBuffer, osaWaitForever_c); + status = ramStorageGet(mBuffer, aKey, aIndex, aValue, aValueLength); SuccessOrExit(err = MapStatusToChipError(status)); exit: + mutex_unlock(mBuffer); return err; } @@ -60,26 +85,52 @@ CHIP_ERROR RamStorage::Write(uint16_t aKey, const uint8_t * aValue, uint16_t aVa { CHIP_ERROR err; rsError status = RS_ERROR_NONE; + PDM_teStatus pdmStatus; + mutex_lock(mBuffer, osaWaitForever_c); // Delete all occurrences of "key" and resize buffer if needed // before scheduling writing of new value. - ramStorageDelete(sBuffer, aKey, -1); - status = ramStorageResize(&sBuffer, aKey, aValue, aValueLength); + ramStorageDelete(mBuffer, aKey, -1); +#if PDM_USE_DYNAMIC_MEMORY + status = ramStorageResize(mBuffer, aKey, aValue, aValueLength); SuccessOrExit(err = MapStatusToChipError(status)); - status = ramStorageSet(sBuffer, aKey, aValue, aValueLength); +#endif + status = ramStorageSet(mBuffer, aKey, aValue, aValueLength); SuccessOrExit(err = MapStatusToChipError(status)); + pdmStatus = PDM_SaveRecord(mPdmId, mBuffer); + SuccessOrExit(err = MapPdmStatusToChipError(pdmStatus)); exit: + mutex_unlock(mBuffer); return err; } CHIP_ERROR RamStorage::Delete(uint16_t aKey, int aIndex) { - rsError status = ramStorageDelete(sBuffer, aKey, aIndex); - return MapStatusToChipError(status); + CHIP_ERROR err; + rsError status = RS_ERROR_NONE; + PDM_teStatus pdmStatus; + + mutex_lock(mBuffer, osaWaitForever_c); + status = ramStorageDelete(mBuffer, aKey, aIndex); + SuccessOrExit(err = MapStatusToChipError(status)); + pdmStatus = PDM_SaveRecord(mPdmId, mBuffer); + SuccessOrExit(err = MapPdmStatusToChipError(pdmStatus)); + +exit: + mutex_unlock(mBuffer); + return err; +} + +void RamStorage::OnFactoryReset() +{ + mutex_lock(mBuffer, osaWaitForever_c); + PDM_vDeleteDataRecord(mPdmId); + mutex_unlock(mBuffer); + FreeBuffer(); } -CHIP_ERROR RamStorage::MapStatusToChipError(rsError rsStatus) +CHIP_ERROR RamStorage::MapStatusToChipError(rsError rsStatus) const { CHIP_ERROR err; @@ -99,4 +150,21 @@ CHIP_ERROR RamStorage::MapStatusToChipError(rsError rsStatus) return err; } +CHIP_ERROR RamStorage::MapPdmStatusToChipError(PDM_teStatus status) const +{ + CHIP_ERROR err; + + switch (status) + { + case PDM_E_STATUS_OK: + err = CHIP_NO_ERROR; + break; + default: + err = CHIP_ERROR(ChipError::Range::kPlatform, status); + break; + } + + return err; +} + } // namespace chip::DeviceLayer::Internal diff --git a/src/platform/nxp/k32w/common/RamStorage.h b/src/platform/nxp/k32w/common/RamStorage.h index 414db35d61d878..767f850c250046 100644 --- a/src/platform/nxp/k32w/common/RamStorage.h +++ b/src/platform/nxp/k32w/common/RamStorage.h @@ -19,7 +19,7 @@ #include -#include "pdm_ram_storage_glue.h" +#include "PDM.h" #include "ram_storage.h" namespace chip { @@ -33,20 +33,26 @@ namespace Internal { class RamStorage { public: - using Buffer = ramBufferDescriptor *; + using Buffer = ramBufferDescriptor; - static CHIP_ERROR Init(uint16_t aNvmId, uint16_t aInitialSize); - static void FreeBuffer(); - static Buffer GetBuffer() { return sBuffer; } + static constexpr uint16_t kRamBufferInitialSize = 512; - static CHIP_ERROR Read(uint16_t aKey, int aIndex, uint8_t * aValue, uint16_t * aValueLength); - static CHIP_ERROR Write(uint16_t aKey, const uint8_t * aValue, uint16_t aValueLength); - static CHIP_ERROR Delete(uint16_t aKey, int aIndex); + RamStorage(uint16_t aPdmId) : mPdmId(aPdmId), mBuffer(nullptr) {} + + CHIP_ERROR Init(uint16_t aInitialSize); + void FreeBuffer(); + Buffer * GetBuffer() const { return mBuffer; } + CHIP_ERROR Read(uint16_t aKey, int aIndex, uint8_t * aValue, uint16_t * aValueLength) const; + CHIP_ERROR Write(uint16_t aKey, const uint8_t * aValue, uint16_t aValueLength); + CHIP_ERROR Delete(uint16_t aKey, int aIndex); + void OnFactoryReset(); private: - static CHIP_ERROR MapStatusToChipError(rsError rsStatus); + CHIP_ERROR MapStatusToChipError(rsError rsStatus) const; + CHIP_ERROR MapPdmStatusToChipError(PDM_teStatus status) const; - static Buffer sBuffer; + uint16_t mPdmId; + Buffer * mBuffer; }; } // namespace Internal diff --git a/src/platform/nxp/k32w/common/RamStorageKey.cpp b/src/platform/nxp/k32w/common/RamStorageKey.cpp new file mode 100644 index 00000000000000..131559e9a39c30 --- /dev/null +++ b/src/platform/nxp/k32w/common/RamStorageKey.cpp @@ -0,0 +1,45 @@ +/* + * + * Copyright (c) 2022 Project CHIP Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include +#include + +namespace chip::DeviceLayer::Internal { + +RamStorageKey::RamStorageKey(RamStorage * storage, uint8_t keyId, uint8_t pdmId) +{ + mStorage = storage; + mId = GetPdmId(keyId, pdmId); +} + +CHIP_ERROR RamStorageKey::Read(uint8_t * buf, uint16_t & sizeToRead) const +{ + return mStorage->Read(mId, 0, buf, &sizeToRead); +} + +CHIP_ERROR RamStorageKey::Write(const uint8_t * buf, uint16_t length) +{ + return mStorage->Write(mId, buf, length); +} + +CHIP_ERROR RamStorageKey::Delete() +{ + return mStorage->Delete(mId, -1); +} + +} // namespace chip::DeviceLayer::Internal diff --git a/src/platform/nxp/k32w/common/RamStorageKey.h b/src/platform/nxp/k32w/common/RamStorageKey.h new file mode 100644 index 00000000000000..e1596eeec1ec85 --- /dev/null +++ b/src/platform/nxp/k32w/common/RamStorageKey.h @@ -0,0 +1,42 @@ +/* + * + * Copyright (c) 2022 Project CHIP Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#pragma once + +#include + +namespace chip { +namespace DeviceLayer { +namespace Internal { + +class RamStorageKey +{ +public: + RamStorageKey(RamStorage * storage, uint8_t keyId, uint8_t pdmId); + CHIP_ERROR Read(uint8_t * buf, uint16_t & sizeToRead) const; + CHIP_ERROR Write(const uint8_t * buf, uint16_t length); + CHIP_ERROR Delete(); + + static uint16_t GetPdmId(uint8_t keyId, uint8_t pdmId) { return static_cast(keyId) << 8 | pdmId; } + +private: + RamStorage * mStorage; + uint16_t mId; +}; + +} // namespace Internal +} // namespace DeviceLayer +} // namespace chip diff --git a/src/platform/nxp/k32w/k32w0/BLEManagerImpl.cpp b/src/platform/nxp/k32w/k32w0/BLEManagerImpl.cpp index 2f296f74bcf6c5..29a3e9ee88ef3a 100644 --- a/src/platform/nxp/k32w/k32w0/BLEManagerImpl.cpp +++ b/src/platform/nxp/k32w/k32w0/BLEManagerImpl.cpp @@ -45,6 +45,11 @@ #include "PWR_Configuration.h" #endif +#if CHIP_ENABLE_ADDITIONAL_DATA_ADVERTISING +#include +#include +#endif + /******************************************************************************* * Local data types *******************************************************************************/ @@ -149,6 +154,10 @@ CHIP_ERROR BLEManagerImpl::_Init() BaseType_t bleAppCreated = errCOULD_NOT_ALLOCATE_REQUIRED_MEMORY; uint16_t attChipRxHandle[1] = { (uint16_t) value_chipoble_rx }; +#if CHIP_ENABLE_ADDITIONAL_DATA_ADVERTISING + uint16_t attChipC3Handle[1] = { (uint16_t) value_chipoble_c3 }; +#endif + mServiceMode = ConnectivityManager::kCHIPoBLEServiceMode_Enabled; // Check if BLE stack is initialized @@ -184,7 +193,6 @@ 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 */ @@ -209,6 +217,9 @@ CHIP_ERROR BLEManagerImpl::_Init() #endif GattServer_RegisterHandlesForWriteNotifications(1, attChipRxHandle); +#if CHIP_ENABLE_ADDITIONAL_DATA_ADVERTISING + GattServer_RegisterHandlesForReadNotifications(1, attChipC3Handle); +#endif mFlags.Set(Flags::kK32WBLEStackInitialized); mFlags.Set(Flags::kAdvertisingEnabled, CHIP_DEVICE_CONFIG_CHIPOBLE_ENABLE_ADVERTISING_AUTOSTART ? true : false); @@ -425,11 +436,6 @@ bool BLEManagerImpl::UnsubscribeCharacteristic(BLE_CONNECTION_OBJECT conId, cons return false; } -void NotifyChipConnectionClosed(BLE_CONNECTION_OBJECT connObj) -{ - BLEMgrImpl().blekw_stop_connection_internal(connObj); -} - bool BLEManagerImpl::CloseConnection(BLE_CONNECTION_OBJECT conId) { return blekw_stop_connection_internal(conId); @@ -466,7 +472,8 @@ bool BLEManagerImpl::SendReadResponse(BLE_CONNECTION_OBJECT conId, BLE_READ_REQU void BLEManagerImpl::NotifyChipConnectionClosed(BLE_CONNECTION_OBJECT conId) { - // Nothing to do + BLEMgrImpl().blekw_stop_connection_internal(conId); + BLEMgrImpl().RemoveConnection(conId); } bool BLEManagerImpl::SendIndication(BLE_CONNECTION_OBJECT conId, const ChipBleUUID * svcId, const ChipBleUUID * charId, @@ -810,6 +817,11 @@ CHIP_ERROR BLEManagerImpl::ConfigureAdvertisingData(void) adv_data[1].aData = advPayload; adv.aAdStructures = adv_data; + +#if CHIP_ENABLE_ADDITIONAL_DATA_ADVERTISING + ReturnErrorOnFailure(EncodeAdditionalDataTlv()); +#endif + /**************** Prepare scan response data *******************************************/ scanRsp.cNumAdStructures = BLEKW_SCAN_RSP_MAX_NO; @@ -834,10 +846,11 @@ CHIP_ERROR BLEManagerImpl::ConfigureAdvertisingData(void) { advInterval = CHIP_DEVICE_CONFIG_BLE_SLOW_ADVERTISING_INTERVAL_MAX; } + advInterval = (uint16_t)(advInterval * 0.625F); - adv_params.minInterval = adv_params.maxInterval = (uint16_t)(advInterval / 0.625F); + adv_params.minInterval = adv_params.maxInterval = advInterval; adv_params.advertisingType = gAdvConnectableUndirected_c; - adv_params.ownAddressType = gBleAddrTypePublic_c; + adv_params.ownAddressType = gBleAddrTypeRandom_c; adv_params.peerAddressType = gBleAddrTypePublic_c; memset(adv_params.peerAddress, 0, gcBleDeviceAddressSize_c); adv_params.channelMap = (gapAdvertisingChannelMapFlags_t)(gAdvChanMapFlag37_c | gAdvChanMapFlag38_c | gAdvChanMapFlag39_c); @@ -851,6 +864,7 @@ CHIP_ERROR BLEManagerImpl::ConfigureAdvertisingData(void) else { ChipLogProgress(DeviceLayer, "Advertising error 0x%x!", err); + mFlags.Clear(Flags::kAdvertising); return CHIP_ERROR_INCORRECT_STATE; } @@ -858,6 +872,59 @@ CHIP_ERROR BLEManagerImpl::ConfigureAdvertisingData(void) return chipErr; } +#if CHIP_ENABLE_ADDITIONAL_DATA_ADVERTISING +CHIP_ERROR BLEManagerImpl::EncodeAdditionalDataTlv() +{ + CHIP_ERROR err = CHIP_NO_ERROR; + BitFlags dataFields; + AdditionalDataPayloadGeneratorParams params; + +#if CHIP_ENABLE_ROTATING_DEVICE_ID && defined(CHIP_DEVICE_CONFIG_ROTATING_DEVICE_ID_UNIQUE_ID) + uint8_t rotatingDeviceIdUniqueId[ConfigurationManager::kRotatingDeviceIDUniqueIDLength] = {}; + MutableByteSpan rotatingDeviceIdUniqueIdSpan(rotatingDeviceIdUniqueId); + + err = DeviceLayer::GetDeviceInstanceInfoProvider()->GetRotatingDeviceIdUniqueId(rotatingDeviceIdUniqueIdSpan); + SuccessOrExit(err); + err = ConfigurationMgr().GetLifetimeCounter(params.rotatingDeviceIdLifetimeCounter); + SuccessOrExit(err); + params.rotatingDeviceIdUniqueId = rotatingDeviceIdUniqueIdSpan; + dataFields.Set(AdditionalDataFields::RotatingDeviceId); +#endif /* CHIP_ENABLE_ROTATING_DEVICE_ID && defined(CHIP_DEVICE_CONFIG_ROTATING_DEVICE_ID_UNIQUE_ID) */ + err = + AdditionalDataPayloadGenerator().generateAdditionalDataPayload(params, sInstance.c3AdditionalDataBufferHandle, dataFields); + +exit: + if (err != CHIP_NO_ERROR) + { + ChipLogError(DeviceLayer, "Failed to generate TLV encoded Additional Data (%s)", __func__); + } + + return err; +} + +void BLEManagerImpl::HandleC3ReadRequest(blekw_msg_t * msg) +{ + bleResult_t result; + blekw_att_read_data_t * att_rd_data = (blekw_att_read_data_t *) msg->data.data; + deviceId_t deviceId = att_rd_data->device_id; + uint16_t handle = att_rd_data->handle; + uint16_t length = sInstance.c3AdditionalDataBufferHandle->DataLength(); + const uint8_t * data = (const uint8_t *) sInstance.c3AdditionalDataBufferHandle->Start(); + + result = GattDb_WriteAttribute(handle, length, data); + if (result != gBleSuccess_c) + { + ChipLogError(DeviceLayer, "Failed to write C3 characteristic: %d", result); + } + + result = GattServer_SendAttributeReadStatus(deviceId, handle, gAttErrCodeNoError_c); + if (result != gBleSuccess_c) + { + ChipLogError(DeviceLayer, "Failed to send response to C3 read request: %d", result); + } +} +#endif /* CHIP_ENABLE_ADDITIONAL_DATA_ADVERTISING */ + CHIP_ERROR BLEManagerImpl::StartAdvertising(void) { CHIP_ERROR err = CHIP_NO_ERROR; @@ -1002,6 +1069,14 @@ void BLEManagerImpl::bleAppTask(void * p_arg) { sInstance.HandleWriteEvent(msg); } + else if (msg->type == BLE_KW_MSG_ATT_READ) + { +#if CHIP_ENABLE_ADDITIONAL_DATA_ADVERTISING + blekw_att_read_data_t * att_rd_data = (blekw_att_read_data_t *) msg->data.data; + if (value_chipoble_c3 == att_rd_data->handle) + sInstance.HandleC3ReadRequest(msg); +#endif + } else if (msg->type == BLE_KW_MSG_FORCE_DISCONNECT) { ChipLogProgress(DeviceLayer, "BLE connection timeout: Forcing disconnection."); @@ -1011,6 +1086,7 @@ void BLEManagerImpl::bleAppTask(void * p_arg) { ChipLogProgress(DeviceLayer, "Gap_Disconnect() failed."); } + sInstance.RemoveConnection(g_device_id); } /* Freed the message from the queue */ @@ -1024,6 +1100,12 @@ void BLEManagerImpl::HandleConnectEvent(blekw_msg_t * msg) uint8_t device_id_loc = msg->data.u8; ChipLogProgress(DeviceLayer, "BLE is connected with device: %d.\n", device_id_loc); +#if gClkUseFro32K +#if defined(cPWR_UsePowerDownMode) && (cPWR_UsePowerDownMode) + PWR_DisallowDeviceToSleep(); +#endif +#endif + g_device_id = device_id_loc; blekw_start_connection_timeout(); sInstance.AddConnection(device_id_loc); @@ -1036,6 +1118,12 @@ void BLEManagerImpl::HandleConnectionCloseEvent(blekw_msg_t * msg) uint8_t device_id_loc = msg->data.u8; ChipLogProgress(DeviceLayer, "BLE is disconnected with device: %d.\n", device_id_loc); +#if gClkUseFro32K +#if defined(cPWR_UsePowerDownMode) && (cPWR_UsePowerDownMode) + PWR_AllowDeviceToSleep(); +#endif +#endif + if (sInstance.RemoveConnection(device_id_loc)) { ChipDeviceEvent event; diff --git a/src/platform/nxp/k32w/k32w0/BLEManagerImpl.h b/src/platform/nxp/k32w/k32w0/BLEManagerImpl.h index f6b5a0df6e07d9..f946ef9a9a562c 100644 --- a/src/platform/nxp/k32w/k32w0/BLEManagerImpl.h +++ b/src/platform/nxp/k32w/k32w0/BLEManagerImpl.h @@ -197,6 +197,9 @@ class BLEManagerImpl final : public BLEManager, private BleLayer, private BlePla uint16_t mNumGAPCons; uint8_t mAdvHandle; char mDeviceName[kMaxDeviceNameLength + 1]; +#if CHIP_ENABLE_ADDITIONAL_DATA_ADVERTISING + chip::System::PacketBufferHandle c3AdditionalDataBufferHandle; +#endif void DriveBLEState(void); CHIP_ERROR ConfigureAdvertising(void); @@ -217,6 +220,10 @@ class BLEManagerImpl final : public BLEManager, private BleLayer, private BlePla bool UnsetSubscribed(uint16_t conId); bool IsSubscribed(uint16_t conId); CHIP_ERROR ConfigureAdvertisingData(void); +#if CHIP_ENABLE_ADDITIONAL_DATA_ADVERTISING + CHIP_ERROR EncodeAdditionalDataTlv(); + void HandleC3ReadRequest(blekw_msg_t * msg); +#endif BLEManagerImpl::ble_err_t blekw_send_event(int8_t connection_handle, uint16_t handle, uint8_t * data, uint32_t len); bool RemoveConnection(uint8_t connectionHandle); void AddConnection(uint8_t connectionHandle); diff --git a/src/platform/nxp/k32w/k32w0/BUILD.gn b/src/platform/nxp/k32w/k32w0/BUILD.gn index 753e62917fd8b7..e2f031e25214e3 100644 --- a/src/platform/nxp/k32w/k32w0/BUILD.gn +++ b/src/platform/nxp/k32w/k32w0/BUILD.gn @@ -29,6 +29,8 @@ static_library("k32w0") { "../../../SingletonConfigurationManager.cpp", "../common/RamStorage.cpp", "../common/RamStorage.h", + "../common/RamStorageKey.cpp", + "../common/RamStorageKey.h", "BLEManagerImpl.cpp", "BLEManagerImpl.h", "CHIPDevicePlatformConfig.h", @@ -43,8 +45,6 @@ static_library("k32w0") { "DiagnosticDataProviderImpl.h", "K32W0Config.cpp", "K32W0Config.h", - "K32W0FactoryDataProvider.cpp", - "K32W0FactoryDataProvider.h", "KeyValueStoreManagerImpl.cpp", "KeyValueStoreManagerImpl.h", "Logging.cpp", @@ -63,6 +63,17 @@ static_library("k32w0") { "${chip_root}/src/credentials/examples/ExamplePAI.h", ] + if (chip_with_factory_data == 1) { + sources += [ + "K32W0FactoryDataProvider.cpp", + "K32W0FactoryDataProvider.h", + ] + public += [ + "${chip_root}/src/credentials/CHIPCert.h", + "${chip_root}/src/credentials/CertificationDeclaration.h", + ] + } + if (chip_with_low_power != 0) { sources += [ "LowPowerHooks.cpp" ] } @@ -78,6 +89,23 @@ static_library("k32w0") { public_deps = [ "${chip_root}/src/platform:platform_base" ] + if (chip_crypto == "platform") { + if (chip_crypto_flavor == "tinycrypt") { + sources += [ "${chip_root}/src/platform/nxp/common/crypto/CHIPCryptoPALTinyCrypt.cpp" ] + + public_deps += [ "${mbedtls_root}:mbedtls" ] + } + + if (chip_crypto_flavor == "NXP-Ultrafast-P256") { + sources += [ "${chip_root}/src/platform/nxp/k32w/k32w0/crypto/CHIPCryptoPALNXPUltrafastP256.cpp" ] + + public_deps += [ + "${chip_root}/third_party/nxp/k32w0_sdk:k32w0_sdk", + "${mbedtls_root}:mbedtls", + ] + } + } + if (chip_enable_openthread) { sources += [ "../../../OpenThread/OpenThreadUtils.cpp", diff --git a/src/platform/nxp/k32w/k32w0/CHIPDevicePlatformConfig.h b/src/platform/nxp/k32w/k32w0/CHIPDevicePlatformConfig.h index 1bb919687d6079..99fe94fd38255e 100644 --- a/src/platform/nxp/k32w/k32w0/CHIPDevicePlatformConfig.h +++ b/src/platform/nxp/k32w/k32w0/CHIPDevicePlatformConfig.h @@ -177,3 +177,5 @@ #endif #define CHIP_DEVICE_CONFIG_ENABLE_TEST_SETUP_PARAMS 1 + +#include diff --git a/src/platform/nxp/k32w/k32w0/CHIPPlatformConfig.h b/src/platform/nxp/k32w/k32w0/CHIPPlatformConfig.h index 1599a397d25798..6971c329fa37c6 100644 --- a/src/platform/nxp/k32w/k32w0/CHIPPlatformConfig.h +++ b/src/platform/nxp/k32w/k32w0/CHIPPlatformConfig.h @@ -76,3 +76,5 @@ #ifndef WDM_PUBLISHER_MAX_NOTIFIES_IN_FLIGHT #define WDM_PUBLISHER_MAX_NOTIFIES_IN_FLIGHT 2 #endif // WDM_PUBLISHER_MAX_NOTIFIES_IN_FLIGHT + +#include "platform/nxp/common/CHIPNXPPlatformDefaultConfig.h" diff --git a/src/platform/nxp/k32w/k32w0/ConfigurationManagerImpl.cpp b/src/platform/nxp/k32w/k32w0/ConfigurationManagerImpl.cpp index c236c05d1fa618..b58ecc6be850f7 100644 --- a/src/platform/nxp/k32w/k32w0/ConfigurationManagerImpl.cpp +++ b/src/platform/nxp/k32w/k32w0/ConfigurationManagerImpl.cpp @@ -30,6 +30,7 @@ #include #include #include +#include #include "fsl_power.h" #include "fsl_reset.h" @@ -146,6 +147,31 @@ CHIP_ERROR ConfigurationManagerImpl::StoreBootReason(uint32_t bootReason) return WriteConfigValue(K32WConfig::kCounterKey_BootReason, bootReason); } +CHIP_ERROR ConfigurationManagerImpl::GetUniqueId(char * buf, size_t bufSize) +{ + CHIP_ERROR err; + size_t uniqueIdLen = 0; // without counting null-terminator + err = ReadConfigValueStr(K32WConfig::kConfigKey_UniqueId, buf, bufSize, uniqueIdLen); + + ReturnErrorOnFailure(err); + + ReturnErrorCodeIf(uniqueIdLen >= bufSize, CHIP_ERROR_BUFFER_TOO_SMALL); + ReturnErrorCodeIf(buf[uniqueIdLen] != 0, CHIP_ERROR_INVALID_STRING_LENGTH); + + return err; +} + +CHIP_ERROR ConfigurationManagerImpl::StoreUniqueId(const char * uniqueId, size_t uniqueIdLen) +{ + return WriteConfigValueStr(K32WConfig::kConfigKey_UniqueId, uniqueId, uniqueIdLen); +} + +CHIP_ERROR ConfigurationManagerImpl::GenerateUniqueId(char * buf, size_t bufSize) +{ + uint64_t randomUniqueId = Crypto::GetRandU64(); + return Encoding::BytesToUppercaseHexString(reinterpret_cast(&randomUniqueId), sizeof(uint64_t), buf, bufSize); +} + bool ConfigurationManagerImpl::CanFactoryReset() { // TODO: query the application to determine if factory reset is allowed. @@ -246,10 +272,7 @@ CHIP_ERROR ConfigurationManagerImpl::WriteConfigValueBin(Key key, const uint8_t return K32WConfig::WriteConfigValueBin(key, data, dataLen); } -void ConfigurationManagerImpl::RunConfigUnitTest(void) -{ - K32WConfig::RunConfigUnitTest(); -} +void ConfigurationManagerImpl::RunConfigUnitTest(void) {} void ConfigurationManagerImpl::DoFactoryReset(intptr_t arg) { @@ -257,11 +280,10 @@ void ConfigurationManagerImpl::DoFactoryReset(intptr_t arg) ChipLogProgress(DeviceLayer, "Performing factory reset"); - err = K32WConfig::FactoryResetConfig(); - if (err != CHIP_NO_ERROR) - { - ChipLogError(DeviceLayer, "FactoryResetConfig() failed: %s", ErrorStr(err)); - } + K32WConfig::FactoryResetConfig(); + ChipLogProgress(DeviceLayer, "Erased K32WConfig storage."); + PersistedStorage::KeyValueStoreManagerImpl::FactoryResetStorage(); + ChipLogProgress(DeviceLayer, "Erased KVS storage."); #if CHIP_DEVICE_CONFIG_ENABLE_THREAD diff --git a/src/platform/nxp/k32w/k32w0/ConfigurationManagerImpl.h b/src/platform/nxp/k32w/k32w0/ConfigurationManagerImpl.h index 32a8f315f8f85d..61cd098ae606d3 100644 --- a/src/platform/nxp/k32w/k32w0/ConfigurationManagerImpl.h +++ b/src/platform/nxp/k32w/k32w0/ConfigurationManagerImpl.h @@ -25,8 +25,8 @@ #pragma once -#include "K32W0Config.h" #include +#include namespace chip { namespace DeviceLayer { @@ -55,6 +55,9 @@ class ConfigurationManagerImpl final : public Internal::GenericConfigurationMana CHIP_ERROR StoreTotalOperationalHours(uint32_t totalOperationalHours) override; CHIP_ERROR GetBootReason(uint32_t & bootReasons) override; CHIP_ERROR StoreBootReason(uint32_t bootReasons) override; + CHIP_ERROR GetUniqueId(char * buf, size_t bufSize) override; + CHIP_ERROR StoreUniqueId(const char * uniqueId, size_t uniqueIdLen) override; + CHIP_ERROR GenerateUniqueId(char * buf, size_t bufSize) override; // NOTE: Other public interface methods are implemented by GenericConfigurationManagerImpl<>. diff --git a/src/platform/nxp/k32w/k32w0/K32W0Config.cpp b/src/platform/nxp/k32w/k32w0/K32W0Config.cpp index b921aec6fdeb4f..e1427b32c63813 100644 --- a/src/platform/nxp/k32w/k32w0/K32W0Config.cpp +++ b/src/platform/nxp/k32w/k32w0/K32W0Config.cpp @@ -36,77 +36,68 @@ namespace chip { namespace DeviceLayer { namespace Internal { -osaMutexId_t K32WConfig::pdmMutexHandle = NULL; - -#if CHIP_DEVICE_LAYER_ENABLE_PDM_LOGS -static void PDM_SystemCallback(uint32_t number, PDM_eSystemEventCode code) -{ - uint8_t capacity = PDM_u8GetSegmentCapacity(); - uint8_t occupancy = PDM_u8GetSegmentOccupancy(); - ChipLogProgress(DeviceLayer, "[PDM]Event (number, code): (%lu, %d)", number, code); - ChipLogProgress(DeviceLayer, "[PDM]Capacity: %hhu", capacity); - ChipLogProgress(DeviceLayer, "[PDM]Occupancy: %hhu", occupancy); -} -#endif +RamStorage K32WConfig::sFactoryStorage{ kNvmId_Factory }; +RamStorage K32WConfig::sConfigStorage{ kNvmId_Config }; +RamStorage K32WConfig::sCounterStorage{ kNvmId_Counter }; + +const K32WConfig::Key K32WConfig::kConfigKey_SerialNum{ &K32WConfig::sFactoryStorage, kKeyId_Factory, 0x00 }; +const K32WConfig::Key K32WConfig::kConfigKey_MfrDeviceId{ &K32WConfig::sFactoryStorage, kKeyId_Factory, 0x01 }; +const K32WConfig::Key K32WConfig::kConfigKey_MfrDeviceCert{ &K32WConfig::sFactoryStorage, kKeyId_Factory, 0x02 }; +const K32WConfig::Key K32WConfig::kConfigKey_MfrDevicePrivateKey{ &K32WConfig::sFactoryStorage, kKeyId_Factory, 0x03 }; +const K32WConfig::Key K32WConfig::kConfigKey_ManufacturingDate{ &K32WConfig::sFactoryStorage, kKeyId_Factory, 0x04 }; +const K32WConfig::Key K32WConfig::kConfigKey_SetupPinCode{ &K32WConfig::sFactoryStorage, kKeyId_Factory, 0x05 }; +const K32WConfig::Key K32WConfig::kConfigKey_MfrDeviceICACerts{ &K32WConfig::sFactoryStorage, kKeyId_Factory, 0x06 }; +const K32WConfig::Key K32WConfig::kConfigKey_HardwareVersion{ &K32WConfig::sFactoryStorage, kKeyId_Factory, 0x07 }; +const K32WConfig::Key K32WConfig::kConfigKey_SetupDiscriminator{ &K32WConfig::sFactoryStorage, kKeyId_Factory, 0x08 }; +const K32WConfig::Key K32WConfig::kConfigKey_Spake2pIterationCount{ &K32WConfig::sFactoryStorage, kKeyId_Factory, 0x09 }; +const K32WConfig::Key K32WConfig::kConfigKey_Spake2pSalt{ &K32WConfig::sFactoryStorage, kKeyId_Factory, 0x0A }; +const K32WConfig::Key K32WConfig::kConfigKey_Spake2pVerifier{ &K32WConfig::sFactoryStorage, kKeyId_Factory, 0x0B }; + +const K32WConfig::Key K32WConfig::kConfigKey_ServiceConfig{ &K32WConfig::sConfigStorage, kKeyId_Config, 0x01 }; +const K32WConfig::Key K32WConfig::kConfigKey_PairedAccountId{ &K32WConfig::sConfigStorage, kKeyId_Config, 0x02 }; +const K32WConfig::Key K32WConfig::kConfigKey_ServiceId{ &K32WConfig::sConfigStorage, kKeyId_Config, 0x03 }; +const K32WConfig::Key K32WConfig::kConfigKey_LastUsedEpochKeyId{ &K32WConfig::sConfigStorage, kKeyId_Config, 0x05 }; +const K32WConfig::Key K32WConfig::kConfigKey_FailSafeArmed{ &K32WConfig::sConfigStorage, kKeyId_Config, 0x06 }; +const K32WConfig::Key K32WConfig::kConfigKey_RegulatoryLocation{ &K32WConfig::sConfigStorage, kKeyId_Config, 0x07 }; +const K32WConfig::Key K32WConfig::kConfigKey_CountryCode{ &K32WConfig::sConfigStorage, kKeyId_Config, 0x08 }; +const K32WConfig::Key K32WConfig::kConfigKey_UniqueId{ &K32WConfig::sConfigStorage, kKeyId_Config, 0x0A }; +const K32WConfig::Key K32WConfig::kConfigKey_SoftwareVersion{ &K32WConfig::sConfigStorage, kKeyId_Config, 0x0B }; + +const K32WConfig::Key K32WConfig::kCounterKey_RebootCount{ &K32WConfig::sCounterStorage, kKeyId_Counter, 0x00 }; +const K32WConfig::Key K32WConfig::kCounterKey_UpTime{ &K32WConfig::sCounterStorage, kKeyId_Counter, 0x01 }; +const K32WConfig::Key K32WConfig::kCounterKey_TotalOperationalHours{ &K32WConfig::sCounterStorage, kKeyId_Counter, 0x02 }; +const K32WConfig::Key K32WConfig::kCounterKey_BootReason{ &K32WConfig::sCounterStorage, kKeyId_Counter, 0x03 }; CHIP_ERROR K32WConfig::Init() { CHIP_ERROR err = CHIP_NO_ERROR; - int status; - /* Initialise the Persistent Data Manager */ - pdmMutexHandle = OSA_MutexCreate(); - VerifyOrExit((NULL != pdmMutexHandle), err = CHIP_ERROR_NO_MEMORY); - status = PDM_Init(); - SuccessOrExit(err = MapPdmInitStatusToChipError(status)); -#if CHIP_DEVICE_LAYER_ENABLE_PDM_LOGS - PDM_vRegisterSystemCallback(PDM_SystemCallback); -#endif - - err = RamStorage::Init(kNvmIdChipConfigData, kRamBufferInitialSize); + err = sFactoryStorage.Init(RamStorage::kRamBufferInitialSize); + SuccessOrExit(err); + err = sConfigStorage.Init(RamStorage::kRamBufferInitialSize); + SuccessOrExit(err); + err = sCounterStorage.Init(RamStorage::kRamBufferInitialSize); + SuccessOrExit(err); exit: if (err != CHIP_NO_ERROR) { - if (pdmMutexHandle) - { - OSA_MutexDestroy(pdmMutexHandle); - } - - RamStorage::FreeBuffer(); + sFactoryStorage.FreeBuffer(); + sConfigStorage.FreeBuffer(); + sCounterStorage.FreeBuffer(); } 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::ReadConfigValueStr(Key key, char * buf, size_t bufSize, size_t & outLen) { CHIP_ERROR err; uint16_t sizeToRead = bufSize; - VerifyOrExit(ValidConfigKey(key), err = CHIP_DEVICE_ERROR_CONFIG_NOT_FOUND); - err = RamStorage::Read(key, 0, (uint8_t *) buf, &sizeToRead); + err = key.Read((uint8_t *) buf, sizeToRead); SuccessOrExit(err); outLen = sizeToRead; - exit: return err; } @@ -118,7 +109,7 @@ CHIP_ERROR K32WConfig::ReadConfigValueBin(Key key, uint8_t * buf, size_t bufSize CHIP_ERROR K32WConfig::ReadConfigValueCounter(uint8_t counterIdx, uint32_t & val) { - Key key = kMinConfigKey_ChipCounter + counterIdx; + Key key{ &sCounterStorage, kKeyId_Counter, counterIdx }; return ReadConfigValue(key, val); } @@ -129,29 +120,7 @@ CHIP_ERROR K32WConfig::WriteConfigValueStr(Key key, const char * str) CHIP_ERROR K32WConfig::WriteConfigValueStr(Key key, const char * str, size_t strLen) { - CHIP_ERROR err; - PDM_teStatus status; - RamStorage::Buffer buffer; - - MutexLock(pdmMutexHandle, osaWaitForever_c); - VerifyOrExit(ValidConfigKey(key), err = CHIP_DEVICE_ERROR_CONFIG_NOT_FOUND); - - if (!str) - { - err = RamStorage::Delete(key, -1); - } - else - { - err = RamStorage::Write(key, (uint8_t *) str, strLen); - SuccessOrExit(err); - buffer = RamStorage::GetBuffer(); - status = PDM_eSaveRecordDataInIdleTask(kNvmIdChipConfigData, buffer, buffer->ramBufferLen + kRamDescHeaderSize); - SuccessOrExit(err = MapPdmStatusToChipError(status)); - } - -exit: - MutexUnlock(pdmMutexHandle); - return err; + return key.Write((uint8_t *) str, strLen); } CHIP_ERROR K32WConfig::WriteConfigValueBin(Key key, const uint8_t * data, size_t dataLen) @@ -161,110 +130,32 @@ CHIP_ERROR K32WConfig::WriteConfigValueBin(Key key, const uint8_t * data, size_t CHIP_ERROR K32WConfig::WriteConfigValueCounter(uint8_t counterIdx, uint32_t val) { - Key key = kMinConfigKey_ChipCounter + counterIdx; + Key key{ &sCounterStorage, kKeyId_Counter, counterIdx }; return WriteConfigValue(key, val); } CHIP_ERROR K32WConfig::ClearConfigValue(Key key) { - CHIP_ERROR err = CHIP_NO_ERROR; - PDM_teStatus status; - RamStorage::Buffer buffer; - - MutexLock(pdmMutexHandle, osaWaitForever_c); - VerifyOrExit(ValidConfigKey(key), err = CHIP_DEVICE_ERROR_CONFIG_NOT_FOUND); // Verify key id. - err = RamStorage::Delete(key, -1); - SuccessOrExit(err); - - buffer = RamStorage::GetBuffer(); - status = PDM_eSaveRecordDataInIdleTask(kNvmIdChipConfigData, buffer, buffer->ramBufferLen + kRamDescHeaderSize); - SuccessOrExit(err = MapPdmStatusToChipError(status)); - -exit: - MutexUnlock(pdmMutexHandle); - return err; + return key.Delete(); } bool K32WConfig::ConfigValueExists(Key key) { CHIP_ERROR err; uint16_t sizeToRead; - bool found = false; - - if (ValidConfigKey(key)) - { - err = RamStorage::Read(key, 0, NULL, &sizeToRead); - found = (err == CHIP_NO_ERROR && sizeToRead != 0); - } + err = key.Read(NULL, sizeToRead); - return found; + return (err == CHIP_NO_ERROR && sizeToRead != 0); } CHIP_ERROR K32WConfig::FactoryResetConfig(void) { - CHIP_ERROR err = CHIP_NO_ERROR; - PDM_teStatus status; - RamStorage::Buffer buffer; - - MutexLock(pdmMutexHandle, osaWaitForever_c); - FactoryResetConfigInternal(kMinConfigKey_ChipCounter, kMaxConfigKey_ChipCounter); - FactoryResetConfigInternal(kMinConfigKey_ChipConfig, kMaxConfigKey_ChipConfig); - FactoryResetConfigInternal(kMinConfigKey_KVSKey, kMaxConfigKey_KVSKey); - FactoryResetConfigInternal(kMinConfigKey_KVSValue, kMaxConfigKey_KVSValue); - - buffer = RamStorage::GetBuffer(); - status = PDM_eSaveRecordData(kNvmIdChipConfigData, buffer, buffer->ramBufferLen + kRamDescHeaderSize); - SuccessOrExit(err = MapPdmStatusToChipError(status)); - -exit: - RamStorage::FreeBuffer(); - MutexUnlock(pdmMutexHandle); - return err; -} - -void K32WConfig::FactoryResetConfigInternal(Key firstKey, Key lastKey) -{ - for (Key key = firstKey; key <= lastKey; key++) - { - RamStorage::Delete(key, -1); - } -} - -CHIP_ERROR K32WConfig::MapPdmStatusToChipError(PDM_teStatus status) -{ - CHIP_ERROR err; + sConfigStorage.OnFactoryReset(); + sCounterStorage.OnFactoryReset(); - switch (status) - { - case PDM_E_STATUS_OK: - err = CHIP_NO_ERROR; - break; - default: - err = CHIP_ERROR(ChipError::Range::kPlatform, status); - break; - } - - return err; + return CHIP_NO_ERROR; } -CHIP_ERROR K32WConfig::MapPdmInitStatusToChipError(int status) -{ - return (status == 0) ? CHIP_NO_ERROR : CHIP_ERROR(ChipError::Range::kPlatform, status); -} - -bool K32WConfig::ValidConfigKey(Key key) -{ - // Returns true if the key is in the valid CHIP Config PDM key range. - if ((key >= kMinConfigKey_ChipFactory) && (key <= kMaxConfigKey_KVSValue)) - { - return true; - } - - return false; -} - -void K32WConfig::RunConfigUnitTest() {} - } // namespace Internal } // namespace DeviceLayer } // namespace chip diff --git a/src/platform/nxp/k32w/k32w0/K32W0Config.h b/src/platform/nxp/k32w/k32w0/K32W0Config.h index 26ff2a41b3adc9..6e2ec0f850d6be 100644 --- a/src/platform/nxp/k32w/k32w0/K32W0Config.h +++ b/src/platform/nxp/k32w/k32w0/K32W0Config.h @@ -19,27 +19,14 @@ #pragma once #include - #include - -#include "PDM.h" -#include "fsl_os_abstraction.h" -#include "pdm_ram_storage_glue.h" -#include "ram_storage.h" #include +#include namespace chip { namespace DeviceLayer { namespace Internal { -constexpr uint16_t kNvmIdChipConfigData = 0x5000; -constexpr uint16_t kRamBufferInitialSize = 3072; - -constexpr inline uint16_t K32WConfigKey(uint8_t chipId, uint8_t pdmId) -{ - return static_cast(chipId) << 8 | pdmId; -} - /** * * This implementation uses the NXP Persistent Data Manager (PDM) library as the @@ -53,64 +40,46 @@ constexpr inline uint16_t K32WConfigKey(uint8_t chipId, uint8_t pdmId) class K32WConfig { public: - // PDM ids used by the CHIP Device Layer - static constexpr uint8_t kPDMId_ChipFactory = 0x01; /**< PDM id for settings containing persistent config values set at - * manufacturing time. Retained during factory reset. */ - static constexpr uint8_t kPDMId_ChipConfig = 0x02; /**< PDM id for settings containing dynamic config values set at runtime. - * Cleared during factory reset. */ - static constexpr uint8_t kPDMId_ChipCounter = 0x03; /**< PDM id for settings containing dynamic counter values set at runtime. - * Retained during factory reset. */ - static constexpr uint8_t kPDMId_KVSKey = 0x04; /**< PDM id for settings containing KVS keys set at runtime. - * Cleared during factory reset. */ - static constexpr uint8_t kPDMId_KVSValue = 0x05; /**< PDM id for settings containing KVS values set at runtime. - * Cleared during factory reset. */ - - using Key = uint32_t; + using Key = RamStorageKey; + + /* Storage for factory data settings. Retained during factory reset. */ + static RamStorage sFactoryStorage; + /* Storage for dynamic runtime config values. Cleared during factory reset. */ + static RamStorage sConfigStorage; + /* Storage for dynamic counter values. Cleared during factory reset. */ + static RamStorage sCounterStorage; // Key definitions for well-known configuration values. // Factory Config Keys - static constexpr Key kConfigKey_SerialNum = K32WConfigKey(kPDMId_ChipFactory, 0x00); - static constexpr Key kConfigKey_MfrDeviceId = K32WConfigKey(kPDMId_ChipFactory, 0x01); - static constexpr Key kConfigKey_MfrDeviceCert = K32WConfigKey(kPDMId_ChipFactory, 0x02); - static constexpr Key kConfigKey_MfrDevicePrivateKey = K32WConfigKey(kPDMId_ChipFactory, 0x03); - static constexpr Key kConfigKey_ManufacturingDate = K32WConfigKey(kPDMId_ChipFactory, 0x04); - static constexpr Key kConfigKey_SetupPinCode = K32WConfigKey(kPDMId_ChipFactory, 0x05); - static constexpr Key kConfigKey_MfrDeviceICACerts = K32WConfigKey(kPDMId_ChipFactory, 0x06); - static constexpr Key kConfigKey_HardwareVersion = K32WConfigKey(kPDMId_ChipFactory, 0x07); - static constexpr Key kConfigKey_SetupDiscriminator = K32WConfigKey(kPDMId_ChipFactory, 0x08); - static constexpr Key kConfigKey_Spake2pIterationCount = K32WConfigKey(kPDMId_ChipFactory, 0x09); - static constexpr Key kConfigKey_Spake2pSalt = K32WConfigKey(kPDMId_ChipFactory, 0x0A); - static constexpr Key kConfigKey_Spake2pVerifier = K32WConfigKey(kPDMId_ChipFactory, 0x0B); + static const Key kConfigKey_SerialNum; + static const Key kConfigKey_MfrDeviceId; + static const Key kConfigKey_MfrDeviceCert; + static const Key kConfigKey_MfrDevicePrivateKey; + static const Key kConfigKey_ManufacturingDate; + static const Key kConfigKey_SetupPinCode; + static const Key kConfigKey_MfrDeviceICACerts; + static const Key kConfigKey_HardwareVersion; + static const Key kConfigKey_SetupDiscriminator; + static const Key kConfigKey_Spake2pIterationCount; + static const Key kConfigKey_Spake2pSalt; + static const Key kConfigKey_Spake2pVerifier; // CHIP Config Keys - static constexpr Key kConfigKey_ServiceConfig = K32WConfigKey(kPDMId_ChipConfig, 0x01); - static constexpr Key kConfigKey_PairedAccountId = K32WConfigKey(kPDMId_ChipConfig, 0x02); - static constexpr Key kConfigKey_ServiceId = K32WConfigKey(kPDMId_ChipConfig, 0x03); - static constexpr Key kConfigKey_LastUsedEpochKeyId = K32WConfigKey(kPDMId_ChipConfig, 0x05); - static constexpr Key kConfigKey_FailSafeArmed = K32WConfigKey(kPDMId_ChipConfig, 0x06); - static constexpr Key kConfigKey_RegulatoryLocation = K32WConfigKey(kPDMId_ChipConfig, 0x07); - static constexpr Key kConfigKey_CountryCode = K32WConfigKey(kPDMId_ChipConfig, 0x08); - static constexpr Key kConfigKey_UniqueId = K32WConfigKey(kPDMId_ChipConfig, 0x0A); - static constexpr Key kConfigKey_SoftwareVersion = K32WConfigKey(kPDMId_ChipConfig, 0x0B); - static constexpr Key kConfigKey_FirstRunOfOTAImage = K32WConfigKey(kPDMId_ChipConfig, 0x0C); + static const Key kConfigKey_ServiceConfig; + static const Key kConfigKey_PairedAccountId; + static const Key kConfigKey_ServiceId; + static const Key kConfigKey_LastUsedEpochKeyId; + static const Key kConfigKey_FailSafeArmed; + static const Key kConfigKey_RegulatoryLocation; + static const Key kConfigKey_CountryCode; + static const Key kConfigKey_UniqueId; + static const Key kConfigKey_SoftwareVersion; // CHIP Counter Keys - static constexpr Key kCounterKey_RebootCount = K32WConfigKey(kPDMId_ChipCounter, 0x00); - static constexpr Key kCounterKey_UpTime = K32WConfigKey(kPDMId_ChipCounter, 0x01); - static constexpr Key kCounterKey_TotalOperationalHours = K32WConfigKey(kPDMId_ChipCounter, 0x02); - static constexpr Key kCounterKey_BootReason = K32WConfigKey(kPDMId_ChipCounter, 0x03); - - // Set key id limits for each group. - static constexpr Key kMinConfigKey_ChipFactory = K32WConfigKey(kPDMId_ChipFactory, 0x00); - static constexpr Key kMaxConfigKey_ChipFactory = K32WConfigKey(kPDMId_ChipFactory, 0xFF); - static constexpr Key kMinConfigKey_ChipConfig = K32WConfigKey(kPDMId_ChipConfig, 0x00); - static constexpr Key kMaxConfigKey_ChipConfig = K32WConfigKey(kPDMId_ChipConfig, 0xFF); - static constexpr Key kMinConfigKey_ChipCounter = K32WConfigKey(kPDMId_ChipCounter, 0x00); - static constexpr Key kMaxConfigKey_ChipCounter = K32WConfigKey(kPDMId_ChipCounter, 0xFF); // Allows 32 Counters to be created. - static constexpr Key kMinConfigKey_KVSKey = K32WConfigKey(kPDMId_KVSKey, 0x00); - static constexpr Key kMaxConfigKey_KVSKey = K32WConfigKey(kPDMId_KVSKey, 0xFF); - static constexpr Key kMinConfigKey_KVSValue = K32WConfigKey(kPDMId_KVSValue, 0x00); - static constexpr Key kMaxConfigKey_KVSValue = K32WConfigKey(kPDMId_KVSValue, 0xFF); + static const Key kCounterKey_RebootCount; + static const Key kCounterKey_UpTime; + static const Key kCounterKey_TotalOperationalHours; + static const Key kCounterKey_BootReason; static CHIP_ERROR Init(void); @@ -132,50 +101,15 @@ class K32WConfig static CHIP_ERROR ClearConfigValue(Key key); static bool ConfigValueExists(Key key); static CHIP_ERROR FactoryResetConfig(void); - static bool ValidConfigKey(Key key); - - 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); - -private: - static CHIP_ERROR MapPdmStatusToChipError(PDM_teStatus status); - static CHIP_ERROR MapPdmInitStatusToChipError(int status); - static void FactoryResetConfigInternal(Key firstKey, Key lastKey); }; -/** - * Extract a PDM id from a Key value. - */ -inline constexpr uint8_t K32WConfig::GetPDMId(Key key) -{ - return static_cast(key >> 8); -} - -/** - * Extract an NVM record key from a Key value. - */ -inline constexpr uint8_t K32WConfig::GetRecordKey(Key key) -{ - return static_cast(key); -} - template CHIP_ERROR K32WConfig::ReadConfigValue(Key key, TValue & val) { CHIP_ERROR err; uint16_t valLen = sizeof(val); - VerifyOrExit(ValidConfigKey(key), err = CHIP_DEVICE_ERROR_CONFIG_NOT_FOUND); - err = RamStorage::Read(key, 0, (uint8_t *) &val, &valLen); + err = key.Read((uint8_t *) &val, valLen); SuccessOrExit(err); exit: @@ -185,46 +119,7 @@ CHIP_ERROR K32WConfig::ReadConfigValue(Key key, TValue & val) template CHIP_ERROR K32WConfig::WriteConfigValue(Key key, TValue val) { - CHIP_ERROR err; - PDM_teStatus status; - RamStorage::Buffer buffer; - - MutexLock(pdmMutexHandle, osaWaitForever_c); - VerifyOrExit(ValidConfigKey(key), err = CHIP_DEVICE_ERROR_CONFIG_NOT_FOUND); - err = RamStorage::Write(key, (uint8_t *) &val, sizeof(TValue)); - SuccessOrExit(err); - - buffer = RamStorage::GetBuffer(); - status = PDM_eSaveRecordDataInIdleTask(kNvmIdChipConfigData, buffer, buffer->ramBufferLen + kRamDescHeaderSize); - SuccessOrExit(err = MapPdmStatusToChipError(status)); - -exit: - MutexUnlock(pdmMutexHandle); - return err; -} - -template -CHIP_ERROR K32WConfig::WriteConfigValueSync(Key key, TValue val) -{ - CHIP_ERROR err; - PDM_teStatus status; - RamStorage::Buffer buffer; - - MutexLock(pdmMutexHandle, osaWaitForever_c); - VerifyOrExit(ValidConfigKey(key), err = CHIP_DEVICE_ERROR_CONFIG_NOT_FOUND); - err = RamStorage::Write(key, (uint8_t *) &val, sizeof(TValue)); - SuccessOrExit(err); - // Interrupts are disabled to ensure there is no context switch during the actual - // writing, thus avoiding race conditions. - OSA_InterruptDisable(); - buffer = RamStorage::GetBuffer(); - status = PDM_eSaveRecordData(kNvmIdChipConfigData, buffer, buffer->ramBufferLen + kRamDescHeaderSize); - OSA_InterruptEnable(); - SuccessOrExit(err = MapPdmStatusToChipError(status)); - -exit: - MutexUnlock(pdmMutexHandle); - return err; + return key.Write((uint8_t *) &val, sizeof(TValue)); } } // namespace Internal diff --git a/src/platform/nxp/k32w/k32w0/K32W0FactoryDataProvider.cpp b/src/platform/nxp/k32w/k32w0/K32W0FactoryDataProvider.cpp index 8c34cc139452e9..a7ed496e0da2c7 100644 --- a/src/platform/nxp/k32w/k32w0/K32W0FactoryDataProvider.cpp +++ b/src/platform/nxp/k32w/k32w0/K32W0FactoryDataProvider.cpp @@ -22,33 +22,46 @@ #endif #include "OtaUtils.h" +#include "SecLib.h" #include "fsl_flash.h" +#include +#include #include #include #include #include #include +#include #include "K32W0FactoryDataProvider.h" +#include + /* Grab symbol for the base address from the linker file. */ extern uint32_t __FACTORY_DATA_START[]; extern uint32_t __FACTORY_DATA_SIZE[]; namespace chip { -namespace { +namespace DeviceLayer { + +static constexpr size_t kSpake2pSerializedVerifier_MaxBase64Len = + BASE64_ENCODED_LEN(chip::Crypto::kSpake2p_VerifierSerialized_Length) + 1; +static constexpr size_t kSpake2pSalt_MaxBase64Len = BASE64_ENCODED_LEN(chip::Crypto::kSpake2p_Max_PBKDF_Salt_Length) + 1; +static constexpr size_t kMaxKeyLen = 32; +static constexpr size_t kHashLen = 4; +static constexpr size_t kDataSizeLen = 4; +static constexpr size_t kHashId = 0xCE47BA5E; -CHIP_ERROR LoadKeypairFromRaw(ByteSpan privateKey, ByteSpan publicKey, Crypto::P256Keypair & keypair) +static uint32_t factoryDataActualSize = 0; +static uint32_t factoryDataStartAddress = 0; + +typedef otaUtilsResult_t (*OtaUtils_EEPROM_ReadData)(uint16_t nbBytes, uint32_t address, uint8_t * pInbuf); + +static uint8_t ReadDataMemCpy(uint16_t num, uint32_t src, uint8_t * dst) { - Crypto::P256SerializedKeypair serialized_keypair; - ReturnErrorOnFailure(serialized_keypair.SetLength(privateKey.size() + publicKey.size())); - memcpy(serialized_keypair.Bytes(), publicKey.data(), publicKey.size()); - memcpy(serialized_keypair.Bytes() + publicKey.size(), privateKey.data(), privateKey.size()); - return keypair.Deserialize(serialized_keypair); + memcpy(dst, (void *) (src), num); + return 0; } -} // namespace - -namespace DeviceLayer { K32W0FactoryDataProvider & K32W0FactoryDataProvider::GetDefaultInstance() { @@ -56,36 +69,94 @@ K32W0FactoryDataProvider & K32W0FactoryDataProvider::GetDefaultInstance() return sInstance; } -static constexpr size_t kSpake2pSerializedVerifier_MaxBase64Len = - BASE64_ENCODED_LEN(chip::Crypto::kSpake2p_VerifierSerialized_Length) + 1; -static constexpr size_t kSpake2pSalt_MaxBase64Len = BASE64_ENCODED_LEN(chip::Crypto::kSpake2p_Max_PBKDF_Salt_Length) + 1; -static constexpr size_t kMaxCertLen = 600; -static constexpr size_t kMaxKeyLen = 32; +K32W0FactoryDataProvider::K32W0FactoryDataProvider() +{ + maxLengths[FactoryDataId::kVerifierId] = kSpake2pSerializedVerifier_MaxBase64Len; + maxLengths[FactoryDataId::kSaltId] = kSpake2pSalt_MaxBase64Len; + maxLengths[FactoryDataId::kIcId] = sizeof(uint32_t); + maxLengths[FactoryDataId::kDacPrivateKeyId] = kMaxKeyLen; + maxLengths[FactoryDataId::kDacCertificateId] = Credentials::kMaxDERCertLength; + maxLengths[FactoryDataId::kPaiCertificateId] = Credentials::kMaxDERCertLength; + maxLengths[FactoryDataId::kDiscriminatorId] = sizeof(uint32_t); + maxLengths[FactoryDataId::kSetupPasscodeId] = sizeof(uint32_t); + maxLengths[FactoryDataId::kVidId] = sizeof(uint16_t); + maxLengths[FactoryDataId::kPidId] = sizeof(uint16_t); + maxLengths[FactoryDataId::kCertDeclarationId] = Credentials::kMaxCMSSignedCDMessage; + maxLengths[FactoryDataId::kVendorNameId] = ConfigurationManager::kMaxVendorNameLength; + maxLengths[FactoryDataId::kProductNameId] = ConfigurationManager::kMaxProductNameLength; + maxLengths[FactoryDataId::kSerialNumberId] = ConfigurationManager::kMaxSerialNumberLength; + maxLengths[FactoryDataId::kManufacturingDateId] = ConfigurationManager::kMaxManufacturingDateLength; + maxLengths[FactoryDataId::kHardwareVersionId] = sizeof(uint16_t); + maxLengths[FactoryDataId::kHardwareVersionStrId] = ConfigurationManager::kMaxHardwareVersionStringLength; + maxLengths[FactoryDataId::kUniqueId] = ConfigurationManager::kMaxUniqueIDLength; +} + +CHIP_ERROR K32W0FactoryDataProvider::Init() +{ + uint8_t sha256Output[SHA256_HASH_SIZE] = { 0 }; + uint32_t start = (uint32_t) __FACTORY_DATA_START; + uint32_t sum = 0; + uint32_t size; + uint32_t hashId; + uint8_t hashReadFromFlash[kHashLen]; + OtaUtils_EEPROM_ReadData pFunctionEepromRead = (OtaUtils_EEPROM_ReadData) ReadDataMemCpy; -static constexpr size_t kVerifierId = 1; -static constexpr size_t kSaltId = 2; -static constexpr size_t kIcId = 3; -static constexpr size_t kDacPrivateKeyId = 4; -static constexpr size_t kDacCertificateId = 5; -static constexpr size_t kPaiCertificateId = 6; -static constexpr size_t kDiscriminatorId = 7; + ReturnErrorOnFailure(SetCustomIds()); -static constexpr size_t kMaxId = kDiscriminatorId; + for (uint8_t i = 1; i < K32W0FactoryDataProvider::kNumberOfIds; i++) + { + sum += maxLengths[i]; + } -static uint16_t maxLengths[kMaxId + 1]; + if (sum > (uint32_t) __FACTORY_DATA_SIZE) + { + ChipLogError(DeviceLayer, "Max size of factory data: %" PRIu32 " is bigger than reserved factory data size: %" PRIu32, sum, + (uint32_t) __FACTORY_DATA_SIZE); + } -typedef otaUtilsResult_t (*OtaUtils_EEPROM_ReadData)(uint16_t nbBytes, uint32_t address, uint8_t * pInbuf); + /* Before trying to verify the hash, make sure there is a hash there by checking its tag */ + if (gOtaUtilsSuccess_c != + OtaUtils_ReadFromInternalFlash((uint16_t) sizeof(hashId), start, (uint8_t *) &hashId, NULL, pFunctionEepromRead)) + { + return CHIP_ERROR_INTERNAL; + } -static uint8_t ReadDataMemCpy(uint16_t num, uint32_t src, uint8_t * dst) -{ - memcpy(dst, (void *) (src), num); - return 0; + if (hashId != kHashId) + { + return CHIP_ERROR_NOT_FOUND; + } + + /* Read length of factory data from internal flash and 4 byte from computed SHA256 hash over factory data */ + start += sizeof(kHashId); + + if (gOtaUtilsSuccess_c != + OtaUtils_ReadFromInternalFlash((uint16_t) sizeof(size), start, (uint8_t *) &size, NULL, pFunctionEepromRead) || + gOtaUtilsSuccess_c != + OtaUtils_ReadFromInternalFlash((uint16_t) sizeof(hashReadFromFlash), start + kHashLen, &hashReadFromFlash[0], NULL, + pFunctionEepromRead)) + { + return CHIP_ERROR_INTERNAL; + } + + start += (kHashLen + kDataSizeLen); + + /* Calculate SHA256 on the factory data and compare with stored value */ + SHA256_Hash((uint8_t *) start, size, sha256Output); + + if (memcmp(&sha256Output[0], &hashReadFromFlash[0], kHashLen) != 0) + { + return CHIP_ERROR_NOT_FOUND; + } + + /* Set factory data start address after hash id, hash and hash size */ + factoryDataStartAddress = start; + + return CHIP_NO_ERROR; } -CHIP_ERROR SearchForId(uint8_t searchedType, uint8_t * pBuf, size_t bufLength, uint16_t & length) +CHIP_ERROR K32W0FactoryDataProvider::SearchForId(uint8_t searchedType, uint8_t * pBuf, size_t bufLength, uint16_t & length) { CHIP_ERROR err = CHIP_ERROR_NOT_FOUND; - uint32_t factoryDataStartAddress = (uint32_t) __FACTORY_DATA_START; uint32_t addr = factoryDataStartAddress; OtaUtils_EEPROM_ReadData pFunctionEepromRead = (OtaUtils_EEPROM_ReadData) ReadDataMemCpy; uint8_t type = 0; @@ -97,13 +168,14 @@ CHIP_ERROR SearchForId(uint8_t searchedType, uint8_t * pBuf, size_t bufLength, u OtaUtils_ReadFromInternalFlash((uint16_t) sizeof(length), addr + 1, (uint8_t *) &length, NULL, pFunctionEepromRead)) break; - if ((type > kMaxId) || (length > maxLengths[type])) - { - break; - } - if (searchedType == type) { + if ((type >= K32W0FactoryDataProvider::kNumberOfIds) || (length > maxLengths[type])) + { + ChipLogError(DeviceLayer, "Failed validity check for factory data with: id=%d, length=%d", type, length); + break; + } + if (bufLength < length) { err = CHIP_ERROR_BUFFER_TOO_SMALL; @@ -127,25 +199,19 @@ CHIP_ERROR SearchForId(uint8_t searchedType, uint8_t * pBuf, size_t bufLength, u return err; } -CHIP_ERROR K32W0FactoryDataProvider::Init() +CHIP_ERROR K32W0FactoryDataProvider::SetCustomIds() { - - maxLengths[kVerifierId] = kSpake2pSerializedVerifier_MaxBase64Len; - maxLengths[kSaltId] = kSpake2pSalt_MaxBase64Len; - maxLengths[kIcId] = 4; - maxLengths[kDacPrivateKeyId] = kMaxKeyLen; - maxLengths[kDacCertificateId] = kMaxCertLen; - maxLengths[kPaiCertificateId] = kMaxCertLen; - maxLengths[kDiscriminatorId] = 4; - + ChipLogError(DeviceLayer, "SetCustomIds() is not implemented for default FactoryDataProvider"); return CHIP_NO_ERROR; } CHIP_ERROR K32W0FactoryDataProvider::GetCertificationDeclaration(MutableByteSpan & outBuffer) { - constexpr uint8_t kCdForAllExamples[] = CHIP_DEVICE_CONFIG_CERTIFICATION_DECLARATION; + uint16_t declarationSize = 0; + ReturnErrorOnFailure(SearchForId(FactoryDataId::kCertDeclarationId, outBuffer.data(), outBuffer.size(), declarationSize)); + outBuffer.reduce_size(declarationSize); - return CopySpanToMutableSpan(ByteSpan{ kCdForAllExamples }, outBuffer); + return CHIP_NO_ERROR; } CHIP_ERROR K32W0FactoryDataProvider::GetFirmwareInformation(MutableByteSpan & out_firmware_info_buffer) @@ -156,7 +222,7 @@ CHIP_ERROR K32W0FactoryDataProvider::GetFirmwareInformation(MutableByteSpan & ou CHIP_ERROR K32W0FactoryDataProvider::GetDeviceAttestationCert(MutableByteSpan & outBuffer) { uint16_t certificateSize = 0; - ReturnErrorOnFailure(SearchForId(kDacCertificateId, outBuffer.data(), outBuffer.size(), certificateSize)); + ReturnErrorOnFailure(SearchForId(FactoryDataId::kDacCertificateId, outBuffer.data(), outBuffer.size(), certificateSize)); outBuffer.reduce_size(certificateSize); return CHIP_NO_ERROR; } @@ -164,7 +230,7 @@ CHIP_ERROR K32W0FactoryDataProvider::GetDeviceAttestationCert(MutableByteSpan & CHIP_ERROR K32W0FactoryDataProvider::GetProductAttestationIntermediateCert(MutableByteSpan & outBuffer) { uint16_t certificateSize = 0; - ReturnErrorOnFailure(SearchForId(kPaiCertificateId, outBuffer.data(), outBuffer.size(), certificateSize)); + ReturnErrorOnFailure(SearchForId(FactoryDataId::kPaiCertificateId, outBuffer.data(), outBuffer.size(), certificateSize)); outBuffer.reduce_size(certificateSize); return CHIP_NO_ERROR; } @@ -173,34 +239,24 @@ CHIP_ERROR K32W0FactoryDataProvider::SignWithDeviceAttestationKey(const ByteSpan { Crypto::P256ECDSASignature signature; Crypto::P256Keypair keypair; + Crypto::P256SerializedKeypair serializedKeypair; + VerifyOrReturnError(IsSpanUsable(outSignBuffer), CHIP_ERROR_INVALID_ARGUMENT); VerifyOrReturnError(IsSpanUsable(messageToSign), CHIP_ERROR_INVALID_ARGUMENT); VerifyOrReturnError(outSignBuffer.size() >= signature.Capacity(), CHIP_ERROR_BUFFER_TOO_SMALL); - // In a non-exemplary implementation, the public key is not needed here. It is used here merely because - // Crypto::P256Keypair is only (currently) constructable from raw keys if both private/public keys are present. - Crypto::P256PublicKey dacPublicKey; - uint8_t certBuf[kMaxCertLen]; - MutableByteSpan dacCertSpan(certBuf); - uint16_t certificateSize = 0; - CHIP_ERROR err = CHIP_NO_ERROR; - - err = SearchForId(kDacCertificateId, dacCertSpan.data(), dacCertSpan.size(), certificateSize); - ReturnErrorOnFailure(err); - dacCertSpan.reduce_size(certificateSize); - /* Extract Public Key of DAC certificate from itself */ - err = Crypto::ExtractPubkeyFromX509Cert(dacCertSpan, dacPublicKey); - ReturnErrorOnFailure(err); - /* Get private key of DAC certificate from reserved section */ uint8_t keyBuf[kMaxKeyLen]; MutableByteSpan dacPrivateKeySpan(keyBuf); uint16_t keySize = 0; - ReturnErrorOnFailure(SearchForId(kDacPrivateKeyId, dacPrivateKeySpan.data(), dacPrivateKeySpan.size(), keySize)); + ReturnErrorOnFailure(SearchForId(FactoryDataId::kDacPrivateKeyId, dacPrivateKeySpan.data(), dacPrivateKeySpan.size(), keySize)); dacPrivateKeySpan.reduce_size(keySize); - ReturnErrorOnFailure(LoadKeypairFromRaw(ByteSpan(dacPrivateKeySpan.data(), dacPrivateKeySpan.size()), - ByteSpan(dacPublicKey.Bytes(), dacPublicKey.Length()), keypair)); + /* Only the private key is used when signing */ + ReturnErrorOnFailure(serializedKeypair.SetLength(Crypto::kP256_PublicKey_Length + dacPrivateKeySpan.size())); + memcpy(serializedKeypair.Bytes() + Crypto::kP256_PublicKey_Length, dacPrivateKeySpan.data(), dacPrivateKeySpan.size()); + + ReturnErrorOnFailure(keypair.Deserialize(serializedKeypair)); ReturnErrorOnFailure(keypair.ECDSA_sign_msg(messageToSign.data(), messageToSign.size(), signature)); return CopySpanToMutableSpan(ByteSpan{ signature.ConstBytes(), signature.Length() }, outSignBuffer); @@ -211,7 +267,7 @@ CHIP_ERROR K32W0FactoryDataProvider::GetSetupDiscriminator(uint16_t & setupDiscr uint32_t discriminator = 0; uint16_t temp = 0; - ReturnErrorOnFailure(SearchForId(kDiscriminatorId, (uint8_t *) &discriminator, sizeof(discriminator), temp)); + ReturnErrorOnFailure(SearchForId(FactoryDataId::kDiscriminatorId, (uint8_t *) &discriminator, sizeof(discriminator), temp)); setupDiscriminator = (uint16_t)(discriminator & 0x0000FFFF); return CHIP_NO_ERROR; @@ -225,8 +281,7 @@ CHIP_ERROR K32W0FactoryDataProvider::SetSetupDiscriminator(uint16_t setupDiscrim CHIP_ERROR K32W0FactoryDataProvider::GetSpake2pIterationCount(uint32_t & iterationCount) { uint16_t temp = 0; - - return SearchForId(kIcId, (uint8_t *) &iterationCount, sizeof(iterationCount), temp); + ReturnErrorOnFailure(SearchForId(FactoryDataId::kIcId, (uint8_t *) &iterationCount, sizeof(iterationCount), temp)); return CHIP_NO_ERROR; } @@ -236,7 +291,7 @@ CHIP_ERROR K32W0FactoryDataProvider::GetSpake2pSalt(MutableByteSpan & saltBuf) char saltB64[kSpake2pSalt_MaxBase64Len] = { 0 }; uint16_t saltB64Len = 0; - ReturnErrorOnFailure(SearchForId(kSaltId, (uint8_t *) (&saltB64[0]), sizeof(saltB64), saltB64Len)); + ReturnErrorOnFailure(SearchForId(FactoryDataId::kSaltId, (uint8_t *) (&saltB64[0]), sizeof(saltB64), saltB64Len)); size_t saltLen = chip::Base64Decode32(saltB64, saltB64Len, reinterpret_cast(saltB64)); ReturnErrorCodeIf(saltLen > saltBuf.size(), CHIP_ERROR_BUFFER_TOO_SMALL); @@ -250,7 +305,7 @@ CHIP_ERROR K32W0FactoryDataProvider::GetSpake2pVerifier(MutableByteSpan & verifi { char verifierB64[kSpake2pSerializedVerifier_MaxBase64Len] = { 0 }; uint16_t verifierB64Len = 0; - ReturnErrorOnFailure(SearchForId(kVerifierId, (uint8_t *) &verifierB64[0], sizeof(verifierB64), verifierB64Len)); + ReturnErrorOnFailure(SearchForId(FactoryDataId::kVerifierId, (uint8_t *) &verifierB64[0], sizeof(verifierB64), verifierB64Len)); verifierLen = chip::Base64Decode32(verifierB64, verifierB64Len, reinterpret_cast(verifierB64)); ReturnErrorCodeIf(verifierLen > verifierBuf.size(), CHIP_ERROR_BUFFER_TOO_SMALL); @@ -262,7 +317,10 @@ CHIP_ERROR K32W0FactoryDataProvider::GetSpake2pVerifier(MutableByteSpan & verifi CHIP_ERROR K32W0FactoryDataProvider::GetSetupPasscode(uint32_t & setupPasscode) { - return CHIP_ERROR_NOT_IMPLEMENTED; + uint16_t length = 0; + ReturnErrorOnFailure(SearchForId(FactoryDataId::kSetupPasscodeId, (uint8_t *) &setupPasscode, sizeof(setupPasscode), length)); + + return CHIP_NO_ERROR; } CHIP_ERROR K32W0FactoryDataProvider::SetSetupPasscode(uint32_t setupPasscode) @@ -270,26 +328,37 @@ CHIP_ERROR K32W0FactoryDataProvider::SetSetupPasscode(uint32_t setupPasscode) return CHIP_ERROR_NOT_IMPLEMENTED; } -#if CHIP_DEVICE_CONFIG_ENABLE_DEVICE_INSTANCE_INFO_PROVIDER CHIP_ERROR K32W0FactoryDataProvider::GetVendorName(char * buf, size_t bufSize) { - return CHIP_ERROR_NOT_IMPLEMENTED; + uint16_t length = 0; + ReturnErrorOnFailure(SearchForId(FactoryDataId::kVendorNameId, (uint8_t *) buf, bufSize, length)); + buf[length] = '\0'; + + return CHIP_NO_ERROR; } CHIP_ERROR K32W0FactoryDataProvider::GetVendorId(uint16_t & vendorId) { - vendorId = static_cast(CHIP_DEVICE_CONFIG_DEVICE_VENDOR_ID); + uint16_t length = 0; + ReturnErrorOnFailure(SearchForId(FactoryDataId::kVidId, (uint8_t *) &vendorId, sizeof(vendorId), length)); + return CHIP_NO_ERROR; } CHIP_ERROR K32W0FactoryDataProvider::GetProductName(char * buf, size_t bufSize) { - return CHIP_ERROR_NOT_IMPLEMENTED; + uint16_t length = 0; + ReturnErrorOnFailure(SearchForId(FactoryDataId::kProductNameId, (uint8_t *) buf, bufSize, length)); + buf[length] = '\0'; + + return CHIP_NO_ERROR; } CHIP_ERROR K32W0FactoryDataProvider::GetProductId(uint16_t & productId) { - productId = static_cast(CHIP_DEVICE_CONFIG_DEVICE_PRODUCT_ID); + uint16_t length = 0; + ReturnErrorOnFailure(SearchForId(FactoryDataId::kPidId, (uint8_t *) &productId, sizeof(productId), length)); + return CHIP_NO_ERROR; } @@ -310,31 +379,75 @@ CHIP_ERROR K32W0FactoryDataProvider::GetProductLabel(char * buf, size_t bufSize) CHIP_ERROR K32W0FactoryDataProvider::GetSerialNumber(char * buf, size_t bufSize) { - return CHIP_ERROR_NOT_IMPLEMENTED; + uint16_t length = 0; + ReturnErrorOnFailure(SearchForId(FactoryDataId::kSerialNumberId, (uint8_t *) buf, bufSize, length)); + buf[length] = '\0'; + + return CHIP_NO_ERROR; } CHIP_ERROR K32W0FactoryDataProvider::GetManufacturingDate(uint16_t & year, uint8_t & month, uint8_t & day) { - return CHIP_ERROR_NOT_IMPLEMENTED; + uint16_t length = 0; + uint8_t date[ConfigurationManager::kMaxManufacturingDateLength]; + + ReturnErrorOnFailure( + SearchForId(FactoryDataId::kManufacturingDateId, date, ConfigurationManager::kMaxManufacturingDateLength, length)); + date[length] = '\0'; + + if (length == 10 && isdigit(date[0]) && isdigit(date[1]) && isdigit(date[2]) && isdigit(date[3]) && date[4] == '-' && + isdigit(date[5]) && isdigit(date[6]) && date[7] == '-' && isdigit(date[8]) && isdigit(date[9])) + { + year = 1000 * (date[0] - '0') + 100 * (date[1] - '0') + 10 * (date[2] - '0') + date[3] - '0'; + month = 10 * (date[5] - '0') + date[6] - '0'; + day = 10 * (date[8] - '0') + date[9] - '0'; + } + else + { + ChipLogError(DeviceLayer, "Manufacturing date is not formatted correctly: YYYY-MM-DD."); + return CHIP_ERROR_INVALID_ARGUMENT; + } + + return CHIP_NO_ERROR; } CHIP_ERROR K32W0FactoryDataProvider::GetHardwareVersion(uint16_t & hardwareVersion) { - return CHIP_ERROR_NOT_IMPLEMENTED; + uint16_t length = 0; + ReturnErrorOnFailure( + SearchForId(FactoryDataId::kHardwareVersionId, (uint8_t *) &hardwareVersion, sizeof(hardwareVersion), length)); + + return CHIP_NO_ERROR; } CHIP_ERROR K32W0FactoryDataProvider::GetHardwareVersionString(char * buf, size_t bufSize) { - return CHIP_ERROR_NOT_IMPLEMENTED; + uint16_t length = 0; + ReturnErrorOnFailure(SearchForId(FactoryDataId::kHardwareVersionStrId, (uint8_t *) buf, bufSize, length)); + buf[length] = '\0'; + + return CHIP_NO_ERROR; } CHIP_ERROR K32W0FactoryDataProvider::GetRotatingDeviceIdUniqueId(MutableByteSpan & uniqueIdSpan) { + ChipError err = CHIP_ERROR_WRONG_KEY_TYPE; #if CHIP_ENABLE_ROTATING_DEVICE_ID && defined(CHIP_DEVICE_CONFIG_ROTATING_DEVICE_ID_UNIQUE_ID) + char uniqueId[ConfigurationManager::kMaxUniqueIDLength] = { 0 }; + uint16_t uniqueIdLen = 0; + ReturnErrorOnFailure(SearchForId(FactoryDataId::kUniqueId, (uint8_t *) (&uniqueId[0]), sizeof(uniqueId), uniqueIdLen)); + static_assert(ConfigurationManager::kRotatingDeviceIDUniqueIDLength >= ConfigurationManager::kMinRotatingDeviceIDUniqueIDLength, + "Length of unique ID for rotating device ID is smaller than minimum."); + + ReturnErrorCodeIf(uniqueIdLen > uniqueIdSpan.size(), CHIP_ERROR_BUFFER_TOO_SMALL); + ReturnErrorCodeIf(uniqueIdLen != ConfigurationManager::kRotatingDeviceIDUniqueIDLength, CHIP_ERROR_BUFFER_TOO_SMALL); + memcpy(uniqueIdSpan.data(), uniqueId, uniqueIdLen); + uniqueIdSpan.reduce_size(uniqueIdLen); + return CHIP_NO_ERROR; #endif - return CHIP_ERROR_NOT_IMPLEMENTED; + return err; } -#endif /* CHIP_DEVICE_CONFIG_ENABLE_DEVICE_INSTANCE_INFO_PROVIDER */ + } // namespace DeviceLayer } // namespace chip diff --git a/src/platform/nxp/k32w/k32w0/K32W0FactoryDataProvider.h b/src/platform/nxp/k32w/k32w0/K32W0FactoryDataProvider.h index caecd89a743fdd..14b5d2d806b58e 100644 --- a/src/platform/nxp/k32w/k32w0/K32W0FactoryDataProvider.h +++ b/src/platform/nxp/k32w/k32w0/K32W0FactoryDataProvider.h @@ -21,6 +21,8 @@ #include #include "CHIPPlatformConfig.h" +#include "K32W0Config.h" +#include namespace chip { namespace DeviceLayer { @@ -30,19 +32,54 @@ namespace DeviceLayer { * and Device Instance Info. */ -class K32W0FactoryDataProvider : public CommissionableDataProvider, +class K32W0FactoryDataProvider : public DeviceInstanceInfoProvider, + public CommissionableDataProvider, public Credentials::DeviceAttestationCredentialsProvider -#if CHIP_DEVICE_CONFIG_ENABLE_DEVICE_INSTANCE_INFO_PROVIDER - , - public DeviceInstanceInfoProvider -#endif // CHIP_DEVICE_CONFIG_ENABLE_DEVICE_INSTANCE_INFO_PROVIDER { public: + // Default factory data IDs + enum FactoryDataId + { + kVerifierId = 1, + kSaltId, + kIcId, + kDacPrivateKeyId, + kDacCertificateId, + kPaiCertificateId, + kDiscriminatorId, + kSetupPasscodeId, + kVidId, + kPidId, + kCertDeclarationId, + kVendorNameId, + kProductNameId, + kSerialNumberId, + kManufacturingDateId, + kHardwareVersionId, + kHardwareVersionStrId, + kUniqueId, + kMaxId + }; + +#if CHIP_DEVICE_CONFIG_USE_CUSTOM_PROVIDER +#if !CHIP_DEVICE_CONFIG_CUSTOM_PROVIDER_NUMBER_IDS +#error "CHIP_DEVICE_CONFIG_CUSTOM_PROVIDER_NUMBER_IDS must be > 0 if custom provider is enabled." +#endif + static constexpr uint16_t kNumberOfIds = FactoryDataId::kMaxId + CHIP_DEVICE_CONFIG_CUSTOM_PROVIDER_NUMBER_IDS; +#else + static constexpr uint16_t kNumberOfIds = FactoryDataId::kMaxId; +#endif + static K32W0FactoryDataProvider & GetDefaultInstance(); - K32W0FactoryDataProvider() {} + K32W0FactoryDataProvider(); CHIP_ERROR Init(); + CHIP_ERROR SearchForId(uint8_t searchedType, uint8_t * pBuf, size_t bufLength, uint16_t & length); + + // Custom factory data providers must implement this method in order to define + // their own custom IDs. + virtual CHIP_ERROR SetCustomIds(); // ===== Members functions that implement the CommissionableDataProvider CHIP_ERROR GetSetupDiscriminator(uint16_t & setupDiscriminator) override; @@ -60,7 +97,6 @@ class K32W0FactoryDataProvider : public CommissionableDataProvider, CHIP_ERROR GetProductAttestationIntermediateCert(MutableByteSpan & outBuffer) override; CHIP_ERROR SignWithDeviceAttestationKey(const ByteSpan & messageToSign, MutableByteSpan & outSignBuffer) override; -#if CHIP_DEVICE_CONFIG_ENABLE_DEVICE_INSTANCE_INFO_PROVIDER // ===== Members functions that implement the GenericDeviceInstanceInfoProvider CHIP_ERROR GetVendorName(char * buf, size_t bufSize) override; CHIP_ERROR GetVendorId(uint16_t & vendorId) override; @@ -73,9 +109,10 @@ class K32W0FactoryDataProvider : public CommissionableDataProvider, CHIP_ERROR GetSerialNumber(char * buf, size_t bufSize) override; CHIP_ERROR GetManufacturingDate(uint16_t & year, uint8_t & month, uint8_t & day) override; CHIP_ERROR GetHardwareVersion(uint16_t & hardwareVersion) override; - CHIP_ERROR GetRotatingDeviceIdUniqueId(MutableByteSpan & uniqueIdSpan) override; -#endif // CHIP_DEVICE_CONFIG_ENABLE_DEVICE_INSTANCE_INFO_PROVIDER + +protected: + uint16_t maxLengths[kNumberOfIds]; }; } // namespace DeviceLayer diff --git a/src/platform/nxp/k32w/k32w0/KeyValueStoreManagerImpl.cpp b/src/platform/nxp/k32w/k32w0/KeyValueStoreManagerImpl.cpp index 29a06f4ee917fd..46ad467ca470ba 100644 --- a/src/platform/nxp/k32w/k32w0/KeyValueStoreManagerImpl.cpp +++ b/src/platform/nxp/k32w/k32w0/KeyValueStoreManagerImpl.cpp @@ -25,39 +25,37 @@ #include #include +#include +#include #include -#include +#include #include -#include "PDM.h" - -#include - namespace chip { namespace DeviceLayer { namespace PersistedStorage { -/* TODO: adjust these values */ constexpr size_t kMaxNumberOfKeys = 150; constexpr size_t kMaxKeyValueBytes = 255; +Internal::RamStorage KeyValueStoreManagerImpl::sKeysStorage = { kNvmId_KvsKeys }; +Internal::RamStorage KeyValueStoreManagerImpl::sValuesStorage = { kNvmId_KvsValues }; + KeyValueStoreManagerImpl KeyValueStoreManagerImpl::sInstance; uint16_t GetStringKeyId(const char * key, uint16_t * freeId) { CHIP_ERROR err = CHIP_ERROR_PERSISTED_STORAGE_VALUE_NOT_FOUND; uint8_t keyId = 0; - uint8_t pdmIdKvsKey = chip::DeviceLayer::Internal::K32WConfig::kPDMId_KVSKey; bool bFreeIdxFound = false; char keyString[kMaxKeyValueBytes] = { 0 }; - size_t keyStringSize = 0; uint16_t pdmInternalId; for (keyId = 0; keyId < kMaxNumberOfKeys; keyId++) { - pdmInternalId = chip::DeviceLayer::Internal::K32WConfigKey(pdmIdKvsKey, keyId); - err = - chip::DeviceLayer::Internal::K32WConfig::ReadConfigValueStr(pdmInternalId, keyString, kMaxKeyValueBytes, keyStringSize); + uint16_t keyStringSize = kMaxKeyValueBytes; + pdmInternalId = Internal::RamStorageKey::GetPdmId(kKeyId_KvsKeys, keyId); + err = KeyValueStoreManagerImpl::sKeysStorage.Read(pdmInternalId, 0, (uint8_t *) keyString, &keyStringSize); if (err == CHIP_NO_ERROR) { @@ -76,14 +74,30 @@ uint16_t GetStringKeyId(const char * key, uint16_t * freeId) return keyId; } +CHIP_ERROR KeyValueStoreManagerImpl::Init() +{ + CHIP_ERROR err = CHIP_NO_ERROR; + err = sKeysStorage.Init(Internal::RamStorage::kRamBufferInitialSize); + if (err != CHIP_NO_ERROR) + { + ChipLogProgress(DeviceLayer, "Cannot init KVS keys storage with id: %d. Error: %s", kNvmId_KvsKeys, ErrorStr(err)); + } + err = sValuesStorage.Init(Internal::RamStorage::kRamBufferInitialSize); + if (err != CHIP_NO_ERROR) + { + ChipLogProgress(DeviceLayer, "Cannot init KVS values storage with id: %d. Error: %s", kNvmId_KvsValues, ErrorStr(err)); + } + + return err; +} + CHIP_ERROR KeyValueStoreManagerImpl::_Get(const char * key, void * value, size_t value_size, size_t * read_bytes_size, size_t offset_bytes) { CHIP_ERROR err = CHIP_ERROR_PERSISTED_STORAGE_VALUE_NOT_FOUND; - uint8_t pdmIdKvsValue = chip::DeviceLayer::Internal::K32WConfig::kPDMId_KVSValue; - size_t read_bytes = 0; uint8_t keyId = 0; uint16_t pdmInternalId = 0; + uint16_t valueSize = value_size; VerifyOrExit((key != NULL) && (value != NULL), err = CHIP_ERROR_INVALID_ARGUMENT); @@ -92,10 +106,10 @@ CHIP_ERROR KeyValueStoreManagerImpl::_Get(const char * key, void * value, size_t if (keyId < kMaxNumberOfKeys) { // This is the ID of the actual data - pdmInternalId = chip::DeviceLayer::Internal::K32WConfigKey(pdmIdKvsValue, keyId); + pdmInternalId = Internal::RamStorageKey::GetPdmId(kKeyId_KvsValues, 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; + err = KeyValueStoreManagerImpl::sValuesStorage.Read(pdmInternalId, 0, (uint8_t *) value, &valueSize); + *read_bytes_size = valueSize; } else { @@ -111,8 +125,6 @@ CHIP_ERROR KeyValueStoreManagerImpl::_Put(const char * key, const void * value, { CHIP_ERROR err = CHIP_ERROR_INVALID_ARGUMENT; bool_t putKey = false; - uint8_t pdmIdKvsKey = chip::DeviceLayer::Internal::K32WConfig::kPDMId_KVSKey; - uint8_t pdmIdKvsValue = chip::DeviceLayer::Internal::K32WConfig::kPDMId_KVSValue; uint16_t pdmInternalId = 0; uint16_t freeKeyId; uint8_t keyId; @@ -128,21 +140,21 @@ CHIP_ERROR KeyValueStoreManagerImpl::_Put(const char * key, const void * value, keyId = freeKeyId; } - pdmInternalId = chip::DeviceLayer::Internal::K32WConfigKey(pdmIdKvsValue, keyId); + pdmInternalId = Internal::RamStorageKey::GetPdmId(kKeyId_KvsValues, keyId); ChipLogProgress(DeviceLayer, "KVS, save in flash the value of the Matter key [%s] with PDM id: %i", key, pdmInternalId); - err = chip::DeviceLayer::Internal::K32WConfig::WriteConfigValueBin(pdmInternalId, (uint8_t *) value, value_size); + err = sValuesStorage.Write(pdmInternalId, (uint8_t *) value, value_size); /* save the 'key' in flash such that it can be retrieved later on */ if (err == CHIP_NO_ERROR) { - if (true == putKey) + if (putKey) { - pdmInternalId = chip::DeviceLayer::Internal::K32WConfigKey(pdmIdKvsKey, keyId); - ChipLogProgress(DeviceLayer, "KVS, save in flash the Matter key [%s] with PDM id: %i", key, pdmInternalId); - - err = chip::DeviceLayer::Internal::K32WConfig::WriteConfigValueStr(pdmInternalId, key, strlen(key) + 1); + pdmInternalId = Internal::RamStorageKey::GetPdmId(kKeyId_KvsKeys, keyId); + ChipLogProgress(DeviceLayer, "KVS, save in flash the Matter key [%s] with PDM id: %i and length %d", key, pdmInternalId, + strlen(key) + 1); + err = sKeysStorage.Write(pdmInternalId, (uint8_t *) key, strlen(key) + 1); if (err != CHIP_NO_ERROR) { ChipLogProgress(DeviceLayer, "KVS, Error while saving in flash the Matter key [%s] with PDM id: %i", key, @@ -164,32 +176,28 @@ CHIP_ERROR KeyValueStoreManagerImpl::_Put(const char * key, const void * value, CHIP_ERROR KeyValueStoreManagerImpl::_Delete(const char * key) { CHIP_ERROR err = CHIP_ERROR_PERSISTED_STORAGE_VALUE_NOT_FOUND; - uint8_t pdmIdKvsKey = chip::DeviceLayer::Internal::K32WConfig::kPDMId_KVSKey; - uint8_t pdmIdKvsValue = chip::DeviceLayer::Internal::K32WConfig::kPDMId_KVSValue; uint8_t keyId = 0; uint16_t pdmInternalId = 0; VerifyOrExit((key != NULL), err = CHIP_ERROR_INVALID_ARGUMENT); keyId = GetStringKeyId(key, NULL); - if (keyId < kMaxNumberOfKeys) { // entry exists so we can remove it - pdmInternalId = chip::DeviceLayer::Internal::K32WConfigKey(pdmIdKvsKey, keyId); + pdmInternalId = Internal::RamStorageKey::GetPdmId(kKeyId_KvsKeys, keyId); ChipLogProgress(DeviceLayer, "KVS, delete from flash the Matter key [%s] with PDM id: %i", key, pdmInternalId); - err = chip::DeviceLayer::Internal::K32WConfig::ClearConfigValue(pdmInternalId); + err = sKeysStorage.Delete(pdmInternalId, -1); /* also delete the 'key string' from flash */ if (err == CHIP_NO_ERROR) { - pdmInternalId = chip::DeviceLayer::Internal::K32WConfigKey(pdmIdKvsValue, keyId); + pdmInternalId = Internal::RamStorageKey::GetPdmId(kKeyId_KvsValues, keyId); ChipLogProgress(DeviceLayer, "KVS, delete from flash the value of the Matter key [%s] with PDM id: %i", key, pdmInternalId); - err = chip::DeviceLayer::Internal::K32WConfig::ClearConfigValue(pdmInternalId); - + err = sValuesStorage.Delete(pdmInternalId, -1); if (err != CHIP_NO_ERROR) { ChipLogProgress(DeviceLayer, @@ -208,6 +216,12 @@ CHIP_ERROR KeyValueStoreManagerImpl::_Delete(const char * key) return err; } +void KeyValueStoreManagerImpl::FactoryResetStorage(void) +{ + sKeysStorage.OnFactoryReset(); + sValuesStorage.OnFactoryReset(); +} + void KeyValueStoreManagerImpl::ConvertError(CHIP_ERROR & err) { if (err == CHIP_DEVICE_ERROR_CONFIG_NOT_FOUND) diff --git a/src/platform/nxp/k32w/k32w0/KeyValueStoreManagerImpl.h b/src/platform/nxp/k32w/k32w0/KeyValueStoreManagerImpl.h index df942779fe4bc2..db9036eb3586e2 100644 --- a/src/platform/nxp/k32w/k32w0/KeyValueStoreManagerImpl.h +++ b/src/platform/nxp/k32w/k32w0/KeyValueStoreManagerImpl.h @@ -24,23 +24,29 @@ #pragma once +#include + namespace chip { namespace DeviceLayer { namespace PersistedStorage { class KeyValueStoreManagerImpl final : public KeyValueStoreManager { +public: + /* Storage for KVS keys. Cleared during factory reset. */ + static Internal::RamStorage sKeysStorage; + /* Storage for KVS values. Cleared during factory reset. */ + static Internal::RamStorage sValuesStorage; + // Allow the KeyValueStoreManager interface class to delegate method calls to // the implementation methods provided by this class. friend class KeyValueStoreManager; -public: - // NOTE: Currently this platform does not support partial and offset reads - // these will return CHIP_ERROR_NOT_IMPLEMENTED. - CHIP_ERROR _Get(const char * key, void * value, size_t value_size, size_t * read_bytes_size, size_t offset); + static CHIP_ERROR Init(); + static void FactoryResetStorage(); + CHIP_ERROR _Get(const char * key, void * value, size_t value_size, size_t * read_bytes_size, size_t offset); CHIP_ERROR _Delete(const char * key); - CHIP_ERROR _Put(const char * key, const void * value, size_t value_size); private: diff --git a/src/platform/nxp/k32w/k32w0/LowPowerHooks.cpp b/src/platform/nxp/k32w/k32w0/LowPowerHooks.cpp index 1946feff8ad41f..eb980e179882b1 100644 --- a/src/platform/nxp/k32w/k32w0/LowPowerHooks.cpp +++ b/src/platform/nxp/k32w/k32w0/LowPowerHooks.cpp @@ -37,9 +37,6 @@ #include // nogncheck #include "app_config.h" -#include "fsl_gpio.h" -#include "fsl_iocon.h" -#include "gpio_pins.h" using namespace ::chip; using namespace ::chip::Inet; @@ -53,16 +50,16 @@ extern "C" void BOARD_SetClockForPowerMode(void); extern "C" void stopM2(); extern "C" void sched_enable(); extern "C" uint64_t otPlatTimeGet(void); +extern "C" void vOptimizeConsumption(void); -static void dm_switch_wakeupCallBack(void); -static void dm_switch_preSleepCallBack(void); +WEAK void dm_switch_wakeupCallBack(void); +WEAK void dm_switch_preSleepCallBack(void); +WEAK void vOptimizeConsumption(void); static void ThreadExitSleep(); static void BOARD_SetClockForWakeup(void); typedef struct { - bool_t bleAppRunning; - bool_t bleAppStopInprogress; bool_t threadInitialized; uint32_t threadWarmBootInitTime; } sDualModeAppStates; @@ -74,7 +71,7 @@ static sDualModeAppStates dualModeStates; /* 15.4 warm time must be > 0, so this value will be * updated when 15.4 is initialized for the first time */ -constexpr uint16_t kThreadWarmNotInitializedValue = 0; +constexpr uint16_t kThreadWarmNotInitializedValue = 1000; /* 1 ms */ extern "C" void otTaskletsSignalPending(otInstance * p_instance); @@ -126,7 +123,7 @@ extern "C" bleResult_t App_PostCallbackMessage(appCallbackHandler_t handler, app return gBleSuccess_c; } -static void dm_switch_wakeupCallBack(void) +WEAK void dm_switch_wakeupCallBack(void) { BOARD_SetClockForWakeup(); SHA_ClkInit(SHA_INSTANCE); @@ -143,6 +140,10 @@ static void dm_switch_wakeupCallBack(void) KBD_PrepareExitLowPower(); +#if gAdcUsed_d + BOARD_ADCWakeupInit(); +#endif + PWR_WakeupReason_t wakeReason = PWR_GetWakeupReason(); if (wakeReason.Bits.FromBLE_LLTimer == 1) { @@ -162,73 +163,47 @@ static void dm_switch_wakeupCallBack(void) K32W_LOG("woken up from TMR"); #endif } - dm_lp_wakeup(); -} - -void vOptimizeConsumption(uint32_t u32PIOvalue, uint32_t u32SkipIO) -{ - uint8_t u8KeepFro32k, u8KeepIOclk, u8KeepXtal32M; - - u8KeepFro32k = u32SkipIO >> 31; - u8KeepIOclk = (u32SkipIO >> 30) & 0x1; - u8KeepXtal32M = (u32SkipIO >> 29) & 0x1; - const gpio_pin_config_t pin_config = { .pinDirection = kGPIO_DigitalInput, .outputLogic = 1U }; - - if (u32PIOvalue != 0) - { - for (int i = 0; i < 22; i++) - { - - if (((u32SkipIO >> i) & 0x1) != 1) - { - /* configure GPIOs to Input mode */ - GPIO_PinInit(GPIO, 0, i, &pin_config); - IOCON_PinMuxSet(IOCON, 0, i, u32PIOvalue); - } - } - } - - if (u8KeepIOclk == 0) + else if (wakeReason.Bits.FromWakeTimer == 1) { - CLOCK_DisableClock(kCLOCK_Iocon); - CLOCK_DisableClock(kCLOCK_InputMux); - CLOCK_DisableClock(kCLOCK_Gpio0); +#if ENABLE_LOW_POWER_LOGS + K32W_LOG("woken up from Wake Timer"); +#endif } - - if (u8KeepXtal32M == 0) + else { - CLOCK_DisableClock(kCLOCK_Xtal32M); // Crystal 32MHz +#if ENABLE_LOW_POWER_LOGS + K32W_LOG("woken up from unknown source"); +#endif } + dm_lp_wakeup(); +} - // Keep the 32K clock - if (u8KeepFro32k == 0) - { - CLOCK_DisableClock(kCLOCK_Fro32k); - } +WEAK void vOptimizeConsumption(void) +{ + /* Intentionally left empty, user needs to redefine it at application level */ } -static void dm_switch_preSleepCallBack(void) +WEAK void dm_switch_preSleepCallBack(void) { #if ENABLE_LOW_POWER_LOGS K32W_LOG("dm_switch_preSleepCallBack"); #endif + /* Inform the low power dual mode module that we will sleep. + It disables the MAC scheduler. + Disabling the scheduler must be done before calling vMMAC_Disable() + so it works correctly */ + dm_lp_preSleep(); + if (dualModeStates.threadInitialized) { - /* stop the internal MAC Scheduler timer */ - stopM2(); - /* disable the MAC scheduler */ - sched_disable(); otPlatRadioDisable(NULL); setThreadInitialized(FALSE); } - /* Inform the low power dual mode module that we will sleep */ - dm_lp_preSleep(); EEPROM_DeInit(); - /* BUTTON2 change contact, BUTTON4 start adv/factoryreset */ - vOptimizeConsumption((IOCON_FUNC0 | (0x2 << 3) | IOCON_ANALOG_EN), - (1 << IOCON_USER_BUTTON1_PIN) | (1 << IOCON_USER_BUTTON2_PIN)); + + vOptimizeConsumption(); /* disable SHA clock */ SHA_ClkDeinit(SHA_INSTANCE); @@ -244,12 +219,6 @@ 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) { uint64_t tick1 = 0; @@ -261,53 +230,56 @@ void dm_switch_init15_4AfterWakeUp(void) tick1 = otPlatTimeGet(); } - if (!dualModeStates.threadInitialized && ConnectivityMgr().IsThreadEnabled()) - { - OSA_InstallIntHandler(ZIGBEE_MAC_IRQn, vMMAC_IntHandlerBbc); - OSA_InstallIntHandler(ZIGBEE_MODEM_IRQn, vMMAC_IntHandlerPhy); + OSA_InstallIntHandler(ZIGBEE_MAC_IRQn, vMMAC_IntHandlerBbc); + OSA_InstallIntHandler(ZIGBEE_MODEM_IRQn, vMMAC_IntHandlerPhy); + + /* Radio must be re-enabled after waking up from sleep. + The module is completely disabled in power down mode. + 15.4 is set as active by default */ + otPlatRadioEnable(NULL); - /* Radio must be re-enabled after waking up from sleep. - * The module is completely disabled in power down mode */ - otPlatRadioEnable(NULL); - sched_enable(); + /* set the correct state */ + vDynRequestState(E_DYN_SLAVE, E_DYN_STATE_INACTIVE); /* 15.4 */ + vDynRequestState(E_DYN_MASTER, E_DYN_STATE_ACTIVE); /* BLE */ - if (dualModeStates.threadWarmBootInitTime == kThreadWarmNotInitializedValue) - { - dualModeStates.threadWarmBootInitTime = (uint32_t)(otPlatTimeGet() - tick1); + sched_enable(); - /* Add a margin of 1 ms */ - dualModeStates.threadWarmBootInitTime += 1000; + if (dualModeStates.threadWarmBootInitTime == kThreadWarmNotInitializedValue) + { + dualModeStates.threadWarmBootInitTime = (uint32_t)(otPlatTimeGet() - tick1); + + /* Add a margin of 0.5 ms */ + dualModeStates.threadWarmBootInitTime += 500; #if ENABLE_LOW_POWER_LOGS - K32W_LOG("Calibration: %d", dualModeStates.threadWarmBootInitTime); + K32W_LOG("Calibration: %d", dualModeStates.threadWarmBootInitTime); #endif - } + } - setThreadInitialized(TRUE); + setThreadInitialized(TRUE); - /* wake up the Thread stack and check if any processing needs to be done */ - otTaskletsSignalPending(NULL); - } + /* wake up the Thread stack and check if any processing needs to be done. + We're called form ISR context */ + otSysEventSignalPending(); } extern "C" void App_NotifyWakeup(void) { if ((!dualModeStates.threadInitialized)) { - /* Notify the dual mode low power mode */ - (void) App_PostCallbackMessage(dm_lp_processEvent, (void *) e15_4WakeUpEnded); + dm_lp_processEvent((void *) e15_4WakeUpEnded); } } extern "C" void App_AllowDeviceToSleep() { - PWR_PreventEnterLowPower(false); + PWR_AllowDeviceToSleep(); } extern "C" void App_DisallowDeviceToSleep() { - PWR_PreventEnterLowPower(true); + PWR_DisallowDeviceToSleep(); } static void BOARD_SetClockForWakeup(void) diff --git a/src/platform/nxp/k32w/k32w0/OTAImageProcessorImpl.cpp b/src/platform/nxp/k32w/k32w0/OTAImageProcessorImpl.cpp index 79dc3ff663fdc7..a64098a3df6c2c 100644 --- a/src/platform/nxp/k32w/k32w0/OTAImageProcessorImpl.cpp +++ b/src/platform/nxp/k32w/k32w0/OTAImageProcessorImpl.cpp @@ -80,18 +80,6 @@ CHIP_ERROR OTAImageProcessorImpl::ProcessBlock(ByteSpan & block) return CHIP_NO_ERROR; } -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(); - } -} - void OTAImageProcessorImpl::HandlePrepareDownload(intptr_t context) { auto * imageProcessor = reinterpret_cast(context); @@ -122,7 +110,6 @@ CHIP_ERROR OTAImageProcessorImpl::ProcessHeader(ByteSpan & block) ReturnErrorCodeIf(error == CHIP_ERROR_BUFFER_TOO_SMALL, CHIP_NO_ERROR); ReturnErrorOnFailure(error); mParams.totalFileBytes = header.mPayloadSize; - mSoftwareVersion = header.mSoftwareVersion; mHeaderParser.Clear(); return CHIP_NO_ERROR; @@ -193,13 +180,14 @@ void OTAImageProcessorImpl::HandleProcessBlock(intptr_t context) if (error != CHIP_NO_ERROR) { - ChipLogError(SoftwareUpdate, "Failed to process OTA image header"); - imageProcessor->mDownloader->EndDownload(error); + ChipLogError(SoftwareUpdate, "Failed to process OTA image header: cancel image update."); + GetRequestorInstance()->CancelImageUpdate(); return; } + uint32_t param = reinterpret_cast(imageProcessor); /* Will start an erase of 4K if necessary */ - if (gOtaSuccess_c == OTA_MakeHeadRoomForNextBlock(imageProcessor->mBlock.size(), HandleBlockEraseComplete, 0)) + if (gOtaSuccess_c == OTA_MakeHeadRoomForNextBlock(imageProcessor->mBlock.size(), HandleBlockEraseComplete, param)) { if (gOtaSuccess_c == OTA_PushImageChunk(imageProcessor->mBlock.data(), (uint16_t) imageProcessor->mBlock.size(), NULL, NULL)) @@ -212,21 +200,34 @@ void OTAImageProcessorImpl::HandleProcessBlock(intptr_t context) bool OTAImageProcessorImpl::IsFirstImageRun() { - bool firstRun = false; - - if (CHIP_NO_ERROR == K32WConfig::ReadConfigValue(K32WConfig::kConfigKey_FirstRunOfOTAImage, firstRun)) + OTARequestorInterface * requestor = chip::GetRequestorInstance(); + if (requestor == nullptr) { - return firstRun; + return false; } - return false; + return requestor->GetCurrentUpdateState() == OTARequestorInterface::OTAUpdateStateEnum::kApplying; } CHIP_ERROR OTAImageProcessorImpl::ConfirmCurrentImage() { - bool firstRun = false; + OTARequestorInterface * requestor = chip::GetRequestorInstance(); + if (requestor == nullptr) + { + return CHIP_ERROR_INTERNAL; + } + + uint32_t currentVersion; + uint32_t targetVersion = requestor->GetTargetVersion(); + ReturnErrorOnFailure(DeviceLayer::ConfigurationMgr().GetSoftwareVersion(currentVersion)); + if (currentVersion != targetVersion) + { + ChipLogError(SoftwareUpdate, "Current sw version %" PRIu32 " is different than the expected sw version = %" PRIu32, + currentVersion, targetVersion); + return CHIP_ERROR_INCORRECT_STATE; + } - return K32WConfig::WriteConfigValue(K32WConfig::kConfigKey_FirstRunOfOTAImage, firstRun); + return CHIP_NO_ERROR; } CHIP_ERROR OTAImageProcessorImpl::SetBlock(ByteSpan & block) @@ -281,24 +282,18 @@ void OTAImageProcessorImpl::HandleApply(intptr_t context) OTA_CommitImage(NULL); if (OTA_ImageAuthenticate() == gOtaImageAuthPass_c) { - if (CHIP_NO_ERROR == K32WConfig::WriteConfigValueSync(K32WConfig::kConfigKey_FirstRunOfOTAImage, firstRun)) - { - ChipLogProgress(SoftwareUpdate, "OTA image authentication success. Device will reboot with the new image!"); - // Set the necessary information to inform the SSBL that a new image is available - // and trigger the actual device reboot after some time, to take into account - // queued actions, e.g. sending events to a subscription - SystemLayer().StartTimer( - chip::System::Clock::Milliseconds32(CHIP_DEVICE_LAYER_OTA_REBOOT_DELAY), - [](chip::System::Layer *, void *) { OTA_SetNewImageFlag(); }, nullptr); - } - else - { - ChipLogProgress(SoftwareUpdate, "Failed to write kConfigKey_FirstRunOfOTAImage key."); - } + ChipLogProgress(SoftwareUpdate, "OTA image authentication success. Device will reboot with the new image!"); + // Set the necessary information to inform the SSBL that a new image is available + // and trigger the actual device reboot after some time, to take into account + // queued actions, e.g. sending events to a subscription + SystemLayer().StartTimer( + chip::System::Clock::Milliseconds32(CHIP_DEVICE_LAYER_OTA_REBOOT_DELAY), + [](chip::System::Layer *, void *) { OTA_SetNewImageFlag(); }, nullptr); } else { - ChipLogError(SoftwareUpdate, "Image authentication error."); + ChipLogError(SoftwareUpdate, "Image authentication error: cancel image update."); + GetRequestorInstance()->CancelImageUpdate(); } } @@ -313,19 +308,16 @@ CHIP_ERROR OTAImageProcessorImpl::ReleaseBlock() return CHIP_NO_ERROR; } -void OTAImageProcessorImpl::HandleBlockEraseComplete(uint32_t) +void OTAImageProcessorImpl::HandleBlockEraseComplete(uint32_t context) { - CHIP_ERROR error = CHIP_NO_ERROR; - - ChipDeviceEvent otaChange; - otaChange.Type = DeviceEventType::kOtaStateChanged; - otaChange.OtaStateChanged.newState = kOtaSpaceAvailable; - error = PlatformMgr().PostEvent(&otaChange); - - if (error != CHIP_NO_ERROR) - { - ChipLogError(SoftwareUpdate, "Error while posting OtaChange event"); - } + CHIP_ERROR error = CHIP_NO_ERROR; + auto * imageProcessor = reinterpret_cast(context); + SystemLayer().ScheduleLambda([imageProcessor] { + if (imageProcessor->mDownloader) + { + imageProcessor->mDownloader->FetchNextData(); + } + }); } } // namespace chip diff --git a/src/platform/nxp/k32w/k32w0/OTAImageProcessorImpl.h b/src/platform/nxp/k32w/k32w0/OTAImageProcessorImpl.h index e431f538c5e984..4462169189a3c6 100644 --- a/src/platform/nxp/k32w/k32w0/OTAImageProcessorImpl.h +++ b/src/platform/nxp/k32w/k32w0/OTAImageProcessorImpl.h @@ -36,7 +36,6 @@ class OTAImageProcessorImpl : public OTAImageProcessorInterface CHIP_ERROR ProcessBlock(ByteSpan & block) override; bool IsFirstImageRun() override; CHIP_ERROR ConfirmCurrentImage() override; - void TriggerNewRequestForData(); void SetOTADownloader(OTADownloader * downloader) { mDownloader = downloader; } void SetOTAImageFile(const char * imageFile) { mImageFile = imageFile; } @@ -48,7 +47,7 @@ class OTAImageProcessorImpl : public OTAImageProcessorInterface static void HandleApply(intptr_t context); static void HandleAbort(intptr_t context); static void HandleProcessBlock(intptr_t context); - static void HandleBlockEraseComplete(uint32_t); + static void HandleBlockEraseComplete(uint32_t context); /** * Called to allocate memory for mBlock if necessary and set it to block @@ -64,7 +63,6 @@ class OTAImageProcessorImpl : public OTAImageProcessorInterface OTAImageHeaderParser mHeaderParser; MutableByteSpan mBlock; const char * mImageFile = nullptr; - uint32_t mSoftwareVersion; }; } // namespace chip diff --git a/src/platform/nxp/k32w/k32w0/PlatformManagerImpl.cpp b/src/platform/nxp/k32w/k32w0/PlatformManagerImpl.cpp index 8ac58946b3c21d..05e53f40bd044a 100644 --- a/src/platform/nxp/k32w/k32w0/PlatformManagerImpl.cpp +++ b/src/platform/nxp/k32w/k32w0/PlatformManagerImpl.cpp @@ -30,6 +30,7 @@ #include #include #include +#include #if CHIP_SYSTEM_CONFIG_USE_LWIP #include @@ -42,9 +43,11 @@ #include #include "MemManager.h" +#include "PDM.h" #include "RNG_Interface.h" #include "SecLib.h" #include "TimersManager.h" +#include "board.h" #include "fsl_sha.h" #include "k32w0-chip-mbedtls-config.h" @@ -90,6 +93,10 @@ CHIP_ERROR PlatformManagerImpl::InitBoardFwk(void) /* Used for OT initializations */ otSysInit(1, argv); +#if gAdcUsed_d + BOARD_ADCWakeupInit(); +#endif + #if defined(cPWR_UsePowerDownMode) && (cPWR_UsePowerDownMode) /* Low Power Init */ InitLowPower(); @@ -124,15 +131,42 @@ int PlatformManagerImpl::uECC_RNG_Function(uint8_t * dest, unsigned int size) } #endif +#if CHIP_DEVICE_LAYER_ENABLE_PDM_LOGS +static void PDM_SystemCallback(uint32_t number, PDM_eSystemEventCode code) +{ + uint8_t capacity = PDM_u8GetSegmentCapacity(); + uint8_t occupancy = PDM_u8GetSegmentOccupancy(); + ChipLogProgress(DeviceLayer, "[PDM]Event (number, code): (%lu, %d)", number, code); + ChipLogProgress(DeviceLayer, "[PDM]Capacity: %hhu", capacity); + ChipLogProgress(DeviceLayer, "[PDM]Occupancy: %hhu", occupancy); +} +#endif + +static CHIP_ERROR MapPdmInitStatusToChipError(int status) +{ + return (status == 0) ? CHIP_NO_ERROR : CHIP_ERROR(ChipError::Range::kPlatform, status); +} + CHIP_ERROR PlatformManagerImpl::_InitChipStack(void) { uint32_t chipType; CHIP_ERROR err = CHIP_NO_ERROR; + int status; + + /* Initialise the Persistent Data Manager */ + status = PDM_Init(); + SuccessOrExit(err = MapPdmInitStatusToChipError(status)); +#if CHIP_DEVICE_LAYER_ENABLE_PDM_LOGS + PDM_vRegisterSystemCallback(PDM_SystemCallback); +#endif // Initialize the configuration system. err = Internal::K32WConfig::Init(); SuccessOrExit(err); + err = PersistedStorage::KeyValueStoreManagerImpl::Init(); + SuccessOrExit(err); + chipType = Chip_GetType(); if ((chipType != CHIP_K32W061) && (chipType != CHIP_K32W041) && (chipType != CHIP_K32W041A) && (chipType != CHIP_K32W041AM)) { diff --git a/src/platform/nxp/k32w/k32w0/crypto/CHIPCryptoPALNXPUltrafastP256.cpp b/src/platform/nxp/k32w/k32w0/crypto/CHIPCryptoPALNXPUltrafastP256.cpp new file mode 100644 index 00000000000000..9c706e396575ee --- /dev/null +++ b/src/platform/nxp/k32w/k32w0/crypto/CHIPCryptoPALNXPUltrafastP256.cpp @@ -0,0 +1,1651 @@ +/* + * + * 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 and NXP Ultrafast P256 based implementation of CHIP crypto primitives + */ + +#include "crypto/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 "SecLib_ecp256.h" + +#include +#include +#include +#include +#include +#include +#include +#include + +#if gSecLibUseSha256Alt_d +#include "SecLib.h" +#endif + +#include + +namespace chip { +namespace Crypto { + +#define MAX_ERROR_STR_LEN 128 +#define NUM_BYTES_IN_SHA256_HASH 32 + +// In mbedTLS 3.0.0 direct access to structure fields was replaced with using MBEDTLS_PRIVATE macro. +#if (MBEDTLS_VERSION_NUMBER >= 0x03000000) +#define CHIP_CRYPTO_PAL_PRIVATE(x) MBEDTLS_PRIVATE(x) +#else +#define CHIP_CRYPTO_PAL_PRIVATE(x) x +#endif + +#if (MBEDTLS_VERSION_NUMBER >= 0x03000000 && MBEDTLS_VERSION_NUMBER < 0x03010000) +#define CHIP_CRYPTO_PAL_PRIVATE_X509(x) MBEDTLS_PRIVATE(x) +#else +#define CHIP_CRYPTO_PAL_PRIVATE_X509(x) x +#endif + +typedef struct +{ + bool mInitialized; + bool mDRBGSeeded; + mbedtls_ctr_drbg_context mDRBGCtxt; + mbedtls_entropy_context mEntropy; +} EntropyContext; + +static EntropyContext gsEntropyContext; + +static void _log_mbedTLS_error(int error_code) +{ + if (error_code != 0) + { +#if defined(MBEDTLS_ERROR_C) + char error_str[MAX_ERROR_STR_LEN]; + mbedtls_strerror(error_code, error_str, sizeof(error_str)); + ChipLogError(Crypto, "mbedTLS error: %s", error_str); +#else + // Error codes defined in 16-bit negative hex numbers. Ease lookup by printing likewise + ChipLogError(Crypto, "mbedTLS error: -0x%04X", -static_cast(error_code)); +#endif + } +} + +static bool _isValidTagLength(size_t tag_length) +{ + if (tag_length == 8 || tag_length == 12 || tag_length == 16) + { + return true; + } + return false; +} + +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() +{ + mbedtls_sha256_context * context = to_inner_hash_sha256_context(&mContext); + mbedtls_sha256_init(context); +} + +Hash_SHA256_stream::~Hash_SHA256_stream() +{ + mbedtls_sha256_context * context = to_inner_hash_sha256_context(&mContext); + mbedtls_sha256_free(context); + Clear(); +} + +CHIP_ERROR Hash_SHA256_stream::Begin() +{ + mbedtls_sha256_context * const context = to_inner_hash_sha256_context(&mContext); +#if gSecLibUseSha256Alt_d + SHA256_SW_Init(context); +#else +#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); +#endif + 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 gSecLibUseSha256Alt_d + SHA256_SW_Update(context, Uint8::to_const_uchar(data.data()), data.size()); +#else +#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); +#endif + 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 gSecLibUseSha256Alt_d + SHA256_SW_Finish(context, Uint8::to_uchar(out_buffer.data())); +#else +#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); +#endif + out_buffer = out_buffer.SubSpan(0, kSHA256_Hash_Length); + + return CHIP_NO_ERROR; +} + +void Hash_SHA256_stream::Clear() +{ + 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 int strong_entropy_func(void * data, unsigned char * output, size_t len) +{ + int result = -1; +#if defined(MBEDTLS_NO_DEFAULT_ENTROPY_SOURCES) + size_t olen = 0; + EntropyContext * const ctxt = get_entropy_context(); + mbedtls_entropy_f_source_ptr trng_get_random = ctxt->mEntropy.source[0].f_source; + result = trng_get_random(NULL, Uint8::to_uchar(output), len, &olen); +#else + result = mbedtls_entropy_func(data, output, len); +#endif + return result; +} + +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, strong_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 ecp256KeyPair_t * to_keypair(P256KeypairContext * context) +{ + return SafePointerCast(context); +} + +static inline const ecp256KeyPair_t * 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 +{ +#if defined(MBEDTLS_ECDSA_C) + VerifyOrReturnError(mInitialized, CHIP_ERROR_WELL_UNINITIALIZED); + VerifyOrReturnError((msg != nullptr) && (msg_length > 0), CHIP_ERROR_INVALID_ARGUMENT); + + uint8_t digest[kSHA256_Hash_Length]; + memset(&digest[0], 0, sizeof(digest)); + ReturnErrorOnFailure(Hash_SHA256(msg, msg_length, &digest[0])); + + CHIP_ERROR error = CHIP_NO_ERROR; + + secEcdsaStatus_t result = gSecEcdsaInvalidState_c; + const ecp256KeyPair_t * keypair = to_const_keypair(&mKeypair); + + result = ECDSA_SignFromHash(out_signature.Bytes(), digest, sizeof(digest), keypair->private_key.raw_8bit); + VerifyOrExit(result == gSecEcdsaSuccess_c, error = CHIP_ERROR_INTERNAL); + VerifyOrExit(out_signature.SetLength(kP256_ECDSA_Signature_Length_Raw) == CHIP_NO_ERROR, error = CHIP_ERROR_INTERNAL); + +exit: + keypair = nullptr; + _log_mbedTLS_error(result); + return error; +#else + return CHIP_ERROR_NOT_IMPLEMENTED; +#endif +} + +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; + + secEcdsaStatus_t result = gSecEcdsaFailure_c; + + const uint8_t * public_key = *this; + + // Fully padded raw uncompressed points expected, first byte is always 0x04 i.e uncompressed + result = ECDSA_VerifySignature(public_key + 1, hash, hash_length, Uint8::to_const_uchar(signature.ConstBytes())); + VerifyOrExit(result == gSecEcdsaSuccess_c, error = CHIP_ERROR_INVALID_SIGNATURE); + +exit: + _log_mbedTLS_error(result); + return error; +} + +CHIP_ERROR P256Keypair::ECDH_derive_secret(const P256PublicKey & remote_public_key, P256ECDHDerivedSecret & out_secret) const +{ + CHIP_ERROR error = CHIP_NO_ERROR; + +#if defined(MBEDTLS_ECDH_C) + secEcdhStatus_t result = gSecEcdhSuccess_c; + size_t secret_length = (out_secret.Length() == 0) ? out_secret.Capacity() : out_secret.Length(); + + const ecp256KeyPair_t * keypair = to_const_keypair(&mKeypair); + + VerifyOrExit(mInitialized, error = CHIP_ERROR_INCORRECT_STATE); + result = Ecdh_ComputeSharedSecret((const uint8_t *) &keypair->private_key, (const uint8_t *) remote_public_key.ConstBytes() + 1, + out_secret.Bytes()); + VerifyOrExit(result == gSecEcdhSuccess_c, 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(ECPKeyTarget key_target) +{ + CHIP_ERROR error = CHIP_NO_ERROR; + int result; + Clear(); + + secEcp256Status_t st; + ecp256KeyPair_t * keypair; + keypair = to_keypair(&mKeypair); + if ((st = ECP256_GenerateKeyPair(&keypair->public_key, &keypair->private_key)) != gSecEcp256Success_c) + { + result = st; + } + else + { + result = 0; + Uint8::to_uchar(mPublicKey)[0] = 0x04; + memcpy(Uint8::to_uchar(mPublicKey) + 1, keypair->public_key.raw, sizeof(ecp256Point_t)); + } + keypair = nullptr; + mInitialized = true; +exit: + _log_mbedTLS_error(result); + return error; +} + +CHIP_ERROR P256Keypair::Serialize(P256SerializedKeypair & output) const +{ + size_t len = output.Length() == 0 ? output.Capacity() : output.Length(); + Encoding::BufferWriter bbuf(output.Bytes(), len); + uint8_t privkey[kP256_PrivateKey_Length]; + CHIP_ERROR error = CHIP_NO_ERROR; + int result = 0; + + bbuf.Put(mPublicKey, mPublicKey.Length()); + + const ecp256KeyPair_t * keypair = to_const_keypair(&mKeypair); + + 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.raw_8bit, 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(); + + ecp256KeyPair_t * keypair = to_keypair(&mKeypair); + ecp_p256_copy(keypair->public_key.raw, input.Bytes() + 1); + ecp_coordinate_copy(keypair->private_key.raw_8bit, input.Bytes() + mPublicKey.Length()); + + VerifyOrExit(input.Length() == mPublicKey.Length() + kP256_PrivateKey_Length, error = CHIP_ERROR_INVALID_ARGUMENT); + bbuf.Put(input.Bytes(), mPublicKey.Length()); + VerifyOrExit(bbuf.Fit(), error = CHIP_ERROR_NO_MEMORY); + + keypair = nullptr; + mInitialized = true; +exit: + _log_mbedTLS_error(result); + return error; +} + +void P256Keypair::Clear() +{ + if (mInitialized) + { + ecp256KeyPair_t * keypair = to_keypair(&mKeypair); + memset(keypair, 0, sizeof(ecp256KeyPair_t)); + mInitialized = false; + } +} + +P256Keypair::~P256Keypair() +{ + Clear(); +} + +CHIP_ERROR P256Keypair::NewCertificateSigningRequest(uint8_t * out_csr, size_t & csr_length) const +{ + MutableByteSpan csr(out_csr, csr_length); + CHIP_ERROR err = GenerateCertificateSigningRequest(this, csr); + csr_length = (CHIP_NO_ERROR == err) ? csr.size() : 0; + return err; +} + +CHIP_ERROR VerifyCertificateSigningRequest(const uint8_t * csr_buf, size_t csr_length, P256PublicKey & pubkey) +{ +#if defined(MBEDTLS_X509_CSR_PARSE_C) + ReturnErrorOnFailure(VerifyCertificateSigningRequestFormat(csr_buf, csr_length)); + + // TODO: For some embedded targets, mbedTLS library doesn't have mbedtls_x509_csr_parse_der, and mbedtls_x509_csr_parse_free. + // Taking a step back, embedded targets likely will not process CSR requests. Adding this action item to reevaluate + // this if there's a need for this processing for embedded targets. + CHIP_ERROR error = CHIP_NO_ERROR; + size_t pubkey_size = 0; + + mbedtls_ecp_keypair * keypair = nullptr; + + P256ECDSASignature signature; + MutableByteSpan out_raw_sig_span(signature.Bytes(), signature.Capacity()); + + mbedtls_x509_csr csr; + mbedtls_x509_csr_init(&csr); + + int result = mbedtls_x509_csr_parse_der(&csr, csr_buf, csr_length); + VerifyOrExit(result == 0, error = CHIP_ERROR_INTERNAL); + + // Verify the signature algorithm and public key type + VerifyOrExit(csr.CHIP_CRYPTO_PAL_PRIVATE(sig_md) == MBEDTLS_MD_SHA256, error = CHIP_ERROR_UNSUPPORTED_SIGNATURE_TYPE); + VerifyOrExit(csr.CHIP_CRYPTO_PAL_PRIVATE(sig_pk) == MBEDTLS_PK_ECDSA, error = CHIP_ERROR_WRONG_KEY_TYPE); + + keypair = mbedtls_pk_ec(csr.CHIP_CRYPTO_PAL_PRIVATE_X509(pk)); + + // Copy the public key from the CSR + result = mbedtls_ecp_point_write_binary(&keypair->CHIP_CRYPTO_PAL_PRIVATE(grp), &keypair->CHIP_CRYPTO_PAL_PRIVATE(Q), + MBEDTLS_ECP_PF_UNCOMPRESSED, &pubkey_size, Uint8::to_uchar(pubkey), pubkey.Length()); + + VerifyOrExit(result == 0, error = CHIP_ERROR_INTERNAL); + VerifyOrExit(pubkey_size == pubkey.Length(), error = CHIP_ERROR_INTERNAL); + + // Convert DER signature to raw signature + error = EcdsaAsn1SignatureToRaw(kP256_FE_Length, + ByteSpan{ csr.CHIP_CRYPTO_PAL_PRIVATE(sig).CHIP_CRYPTO_PAL_PRIVATE_X509(p), + csr.CHIP_CRYPTO_PAL_PRIVATE(sig).CHIP_CRYPTO_PAL_PRIVATE_X509(len) }, + out_raw_sig_span); + + VerifyOrExit(error == CHIP_NO_ERROR, error = CHIP_ERROR_INVALID_ARGUMENT); + VerifyOrExit(out_raw_sig_span.size() == (kP256_FE_Length * 2), error = CHIP_ERROR_INTERNAL); + signature.SetLength(out_raw_sig_span.size()); + + // Verify the signature using the public key + error = pubkey.ECDSA_validate_msg_signature(csr.CHIP_CRYPTO_PAL_PRIVATE_X509(cri).CHIP_CRYPTO_PAL_PRIVATE_X509(p), + csr.CHIP_CRYPTO_PAL_PRIVATE_X509(cri).CHIP_CRYPTO_PAL_PRIVATE_X509(len), signature); + + SuccessOrExit(error); + +exit: + mbedtls_x509_csr_free(&csr); + _log_mbedTLS_error(result); + return error; +#else + ChipLogError(Crypto, "MBEDTLS_X509_CSR_PARSE_C is not enabled. CSR cannot be parsed"); + return CHIP_ERROR_UNSUPPORTED_CHIP_FEATURE; +#endif +} + +typedef struct Spake2p_Context +{ + const mbedtls_md_info_t * md_info; + ecp256Point_t M; + ecp256Point_t N; + ecp256Point_t X; + ecp256Point_t Y; + ecp256Point_t L; + ecp256Point_t Z; + ecp256Point_t V; + ecp256Point_t G; + + big_int256_t w0; // big_int320_t not any more + big_int256_t w1; + big_int256_t xy; + big_int256_t tempbn; + +} Spake2p_Context; + +static inline Spake2p_Context * to_inner_spake2p_context(Spake2pOpaqueContext * context) +{ + return SafePointerCast(context); +} + +CHIP_ERROR Spake2p_P256_SHA256_HKDF_HMAC::InitInternal() +{ + CHIP_ERROR error = CHIP_NO_ERROR; + int result = 0; + + Spake2p_Context * context = to_inner_spake2p_context(&mSpake2pContext); + + memset(context, 0, sizeof(Spake2p_Context)); + + context->md_info = mbedtls_md_info_from_type(MBEDTLS_MD_SHA256); + VerifyOrExit(context->md_info != nullptr, error = CHIP_ERROR_INTERNAL); + + ECP256_GetGPoint(&context->G); + + M = &context->M; + N = &context->N; + X = &context->X; + Y = &context->Y; + L = &context->L; + V = &context->V; + Z = &context->Z; + G = &context->G; + + // memset(&context->w0, 0, sizeof(big_int320_t)); + w0 = &context->w0; + w1 = &context->w1; + xy = &context->xy; + tempbn = &context->tempbn; + + return error; + +exit: + _log_mbedTLS_error(result); + Clear(); + return error; +} + +void Spake2p_P256_SHA256_HKDF_HMAC::Clear() +{ + VerifyOrReturn(state != CHIP_SPAKE2P_STATE::PREINIT); + + 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; + + ECP256_FieldLoad((uint32_t *) fe, in, in_len); + + return error; +} + +CHIP_ERROR Spake2p_P256_SHA256_HKDF_HMAC::FEWrite(const void * fe, uint8_t * out, size_t out_len) +{ + ECP256_FieldLoad((uint32_t *) out, (uint8_t *) fe, out_len); + + return CHIP_NO_ERROR; +} + +CHIP_ERROR Spake2p_P256_SHA256_HKDF_HMAC::FEGenerate(void * fe) +{ + CHIP_ERROR error = CHIP_NO_ERROR; + secEcp256Status_t result; + ecp256Point_t PublicKey; + ecp256Coordinate_t PrivateKey; + + result = ECP256_GenerateKeyPair(&PublicKey, &PrivateKey); + + Spake2p_Context * context = to_inner_spake2p_context(&mSpake2pContext); + + VerifyOrExit(result == gSecEcp256Success_c, error = CHIP_ERROR_INTERNAL); + + ecp_coordinate_copy((uint8_t *) fe, (const uint8_t *) &PrivateKey); + +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; + secEcp256Status_t result; + + result = ECP256_ScalarMultiplicationModN((uint32_t *) fer, (const uint32_t *) fe1, (const uint32_t *) fe2); + VerifyOrExit(result == gSecEcp256Success_c, error = CHIP_ERROR_INTERNAL); +exit: + _log_mbedTLS_error(result); + + return error; +} + +CHIP_ERROR Spake2p_P256_SHA256_HKDF_HMAC::PointLoad(const uint8_t * in, size_t in_len, void * R) +{ + ECP256_PointLoad((ecp256Point_t *) R, in, false); + + 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); + out[0] = 0x04; + ecp_p256_copy(out + 1, (const uint8_t *) R); + + return CHIP_NO_ERROR; +} + +CHIP_ERROR Spake2p_P256_SHA256_HKDF_HMAC::PointMul(void * R, const void * P1, const void * fe1) +{ + CHIP_ERROR error = CHIP_NO_ERROR; + int ret; + + ret = ECP256_PointMult((ecp256Point_t *) R, (const uint8_t *) P1, (const uint8_t *) fe1); + if (ret != gSecEcp256Success_c) + { + error = CHIP_ERROR_INTERNAL; + } + + return error; +} + +CHIP_ERROR Spake2p_P256_SHA256_HKDF_HMAC::PointAddMul(void * R, const void * P1, const void * fe1, const void * P2, + const void * fe2) +{ + CHIP_ERROR status; + + status = CHIP_ERROR_INTERNAL; + + if (ECP256_DoublePointMulAdd(R, P1, fe1, P2, fe2) == gSecEcp256Success_c) + { + status = CHIP_NO_ERROR; + } + + return status; +} + +CHIP_ERROR Spake2p_P256_SHA256_HKDF_HMAC::PointInvert(void * R) +{ + CHIP_ERROR status = CHIP_NO_ERROR; + + if (ECP256_PointInvert((uint32_t *) R, (const uint32_t *) R) != gSecEcp256Success_c) + { + status = CHIP_ERROR_INTERNAL; + } + else + { + status = CHIP_NO_ERROR; + } + + return status; +} + +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; + + secEcp256Status_t result; + uint8_t * p; + uint32_t W1[ECP256_COORDINATE_WLEN]; + do + { + result = ECP256_ModularReductionN(W1, w1in, w1in_len); + if (result != gSecEcp256Success_c) + break; + ecp256Point_t gen_point; + result = ECP256_GeneratePublicKey((uint8_t *) &gen_point, (uint8_t *) &W1); + if (result != gSecEcp256Success_c) + break; + p = Lout; + *p++ = 0x04; /* uncompressed format */ + memcpy(p, (uint8_t *) &gen_point, ECP256_COORDINATE_LEN * 2); + } while (0); + +exit: + _log_mbedTLS_error(result); + return error; +} + +CHIP_ERROR Spake2p_P256_SHA256_HKDF_HMAC::PointIsValid(void * R) +{ + CHIP_ERROR status = CHIP_ERROR_INTERNAL; + do + { + if (!ECP256_PointValid((ecp256Point_t *) R)) + { + break; + } + status = CHIP_NO_ERROR; + } while (0); + return status; +} + +namespace { + +#if defined(MBEDTLS_X509_CRT_PARSE_C) +bool IsTimeGreaterThanEqual(const mbedtls_x509_time * const timeA, const mbedtls_x509_time * const timeB) +{ + + // checks if two values are different and if yes, then returns first > second. +#define RETURN_STRICTLY_GREATER_IF_DIFFERENT(component) \ + { \ + auto valueA = timeA->CHIP_CRYPTO_PAL_PRIVATE_X509(component); \ + auto valueB = timeB->CHIP_CRYPTO_PAL_PRIVATE_X509(component); \ + \ + if (valueA != valueB) \ + { \ + return valueA > valueB; \ + } \ + } + + RETURN_STRICTLY_GREATER_IF_DIFFERENT(year); + RETURN_STRICTLY_GREATER_IF_DIFFERENT(mon); + RETURN_STRICTLY_GREATER_IF_DIFFERENT(day); + RETURN_STRICTLY_GREATER_IF_DIFFERENT(hour); + RETURN_STRICTLY_GREATER_IF_DIFFERENT(min); + RETURN_STRICTLY_GREATER_IF_DIFFERENT(sec); + + // all above are equal + return true; +} + +CHIP_ERROR IsCertificateValidAtIssuance(const mbedtls_x509_crt * candidateCertificate, const mbedtls_x509_crt * issuerCertificate) +{ + mbedtls_x509_time candidateNotBeforeTime = candidateCertificate->CHIP_CRYPTO_PAL_PRIVATE_X509(valid_from); + mbedtls_x509_time issuerNotBeforeTime = issuerCertificate->CHIP_CRYPTO_PAL_PRIVATE_X509(valid_from); + mbedtls_x509_time issuerNotAfterTime = issuerCertificate->CHIP_CRYPTO_PAL_PRIVATE_X509(valid_to); + + // check if candidateCertificate is issued at or after issuerCertificate's notBefore timestamp + VerifyOrReturnError(IsTimeGreaterThanEqual(&candidateNotBeforeTime, &issuerNotBeforeTime), CHIP_ERROR_CERT_EXPIRED); + + // check if candidateCertificate is issued at or before issuerCertificate's notAfter timestamp + VerifyOrReturnError(IsTimeGreaterThanEqual(&issuerNotAfterTime, &candidateNotBeforeTime), CHIP_ERROR_CERT_EXPIRED); + + return CHIP_NO_ERROR; +} + +int CallbackForCustomValidityCheck(void * data, mbedtls_x509_crt * crt, int depth, uint32_t * flags) +{ + mbedtls_x509_crt * leafCert = reinterpret_cast(data); + mbedtls_x509_crt * issuerCert = crt; + + // Ignore any time validy error performed by the standard mbedTLS code. + *flags &= ~(static_cast(MBEDTLS_X509_BADCERT_EXPIRED | MBEDTLS_X509_BADCERT_FUTURE)); + + // Verify that the leaf certificate has a notBefore time valid within the validity period of the issuerCertificate. + // Note that this callback is invoked for each certificate in the chain. + if (IsCertificateValidAtIssuance(leafCert, issuerCert) != CHIP_NO_ERROR) + { + return MBEDTLS_ERR_X509_INVALID_DATE; + } + + return 0; +} + +constexpr uint8_t sOID_AttributeType_CommonName[] = { 0x55, 0x04, 0x03 }; +constexpr uint8_t sOID_AttributeType_MatterVendorId[] = { 0x2B, 0x06, 0x01, 0x04, 0x01, 0x82, 0xA2, 0x7C, 0x02, 0x01 }; +constexpr uint8_t sOID_AttributeType_MatterProductId[] = { 0x2B, 0x06, 0x01, 0x04, 0x01, 0x82, 0xA2, 0x7C, 0x02, 0x02 }; +constexpr uint8_t sOID_SigAlgo_ECDSAWithSHA256[] = { 0x2A, 0x86, 0x48, 0xCE, 0x3D, 0x04, 0x03, 0x02 }; +constexpr uint8_t sOID_Extension_BasicConstraints[] = { 0x55, 0x1D, 0x13 }; +constexpr uint8_t sOID_Extension_KeyUsage[] = { 0x55, 0x1D, 0x0F }; +constexpr uint8_t sOID_Extension_SubjectKeyIdentifier[] = { 0x55, 0x1D, 0x0E }; +constexpr uint8_t sOID_Extension_AuthorityKeyIdentifier[] = { 0x55, 0x1D, 0x23 }; + +/** + * Compares an mbedtls_asn1_buf structure (oidBuf) to a reference OID represented as uint8_t array (oid). + */ +#define OID_CMP(oid, oidBuf) \ + ((MBEDTLS_ASN1_OID == (oidBuf).CHIP_CRYPTO_PAL_PRIVATE_X509(tag)) && \ + (sizeof(oid) == (oidBuf).CHIP_CRYPTO_PAL_PRIVATE_X509(len)) && \ + (memcmp((oid), (oidBuf).CHIP_CRYPTO_PAL_PRIVATE_X509(p), (oidBuf).CHIP_CRYPTO_PAL_PRIVATE_X509(len)) == 0)) + +#endif // defined(MBEDTLS_X509_CRT_PARSE_C) + +} // anonymous namespace + +CHIP_ERROR VerifyAttestationCertificateFormat(const ByteSpan & cert, AttestationCertType certType) +{ +#if defined(MBEDTLS_X509_CRT_PARSE_C) + CHIP_ERROR error = CHIP_NO_ERROR; + int result = 0; + mbedtls_x509_crt mbed_cert; + unsigned char * p = nullptr; + const unsigned char * end = nullptr; + size_t len = 0; + bool extBasicPresent = false; + bool extKeyUsagePresent = false; + + VerifyOrReturnError(!cert.empty(), CHIP_ERROR_INVALID_ARGUMENT); + + mbedtls_x509_crt_init(&mbed_cert); + + result = mbedtls_x509_crt_parse(&mbed_cert, Uint8::to_const_uchar(cert.data()), cert.size()); + VerifyOrExit(result == 0, error = CHIP_ERROR_INTERNAL); + + // "version" value is 1 higher than the actual encoded value. + VerifyOrExit(mbed_cert.CHIP_CRYPTO_PAL_PRIVATE_X509(version) - 1 == 2, error = CHIP_ERROR_INTERNAL); + + // Verify signature algorithms is ECDSA with SHA256. + VerifyOrExit(OID_CMP(sOID_SigAlgo_ECDSAWithSHA256, mbed_cert.CHIP_CRYPTO_PAL_PRIVATE_X509(sig_oid)), + error = CHIP_ERROR_INTERNAL); + + // Verify public key presence and format. + { + Crypto::P256PublicKey pubkey; + SuccessOrExit(error = ExtractPubkeyFromX509Cert(cert, pubkey)); + } + + p = mbed_cert.CHIP_CRYPTO_PAL_PRIVATE_X509(v3_ext).CHIP_CRYPTO_PAL_PRIVATE_X509(p); + end = p + mbed_cert.CHIP_CRYPTO_PAL_PRIVATE_X509(v3_ext).CHIP_CRYPTO_PAL_PRIVATE_X509(len); + result = mbedtls_asn1_get_tag(&p, end, &len, MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE); + VerifyOrExit(result == 0, error = CHIP_ERROR_INTERNAL); + + while (p < end) + { + mbedtls_x509_buf extOID = { 0, 0, nullptr }; + int extCritical = 0; + + result = mbedtls_asn1_get_tag(&p, end, &len, MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE); + VerifyOrExit(result == 0, error = CHIP_ERROR_INTERNAL); + + /* Get extension ID */ + result = mbedtls_asn1_get_tag(&p, end, &len, MBEDTLS_ASN1_OID); + VerifyOrExit(result == 0, error = CHIP_ERROR_INTERNAL); + + extOID.CHIP_CRYPTO_PAL_PRIVATE_X509(tag) = MBEDTLS_ASN1_OID; + extOID.CHIP_CRYPTO_PAL_PRIVATE_X509(len) = len; + extOID.CHIP_CRYPTO_PAL_PRIVATE_X509(p) = p; + p += len; + + /* Get optional critical */ + result = mbedtls_asn1_get_bool(&p, end, &extCritical); + VerifyOrExit(result == 0 || result == MBEDTLS_ERR_ASN1_UNEXPECTED_TAG, error = CHIP_ERROR_INTERNAL); + + /* Data should be octet string type */ + result = mbedtls_asn1_get_tag(&p, end, &len, MBEDTLS_ASN1_OCTET_STRING); + VerifyOrExit(result == 0, error = CHIP_ERROR_INTERNAL); + + if (OID_CMP(sOID_Extension_BasicConstraints, extOID)) + { + int isCA = 0; + int pathLen = -1; + unsigned char * seqStart = p; + + VerifyOrExit(extCritical, error = CHIP_ERROR_INTERNAL); + extBasicPresent = true; + + result = mbedtls_asn1_get_tag(&p, end, &len, MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE); + VerifyOrExit(result == 0, error = CHIP_ERROR_INTERNAL); + if (len > 0) + { + result = mbedtls_asn1_get_bool(&p, end, &isCA); + VerifyOrExit(result == 0 || result == MBEDTLS_ERR_ASN1_UNEXPECTED_TAG, error = CHIP_ERROR_INTERNAL); + + if (p != seqStart + len) + { + result = mbedtls_asn1_get_int(&p, end, &pathLen); + VerifyOrExit(result == 0, error = CHIP_ERROR_INTERNAL); + } + } + + if (certType == AttestationCertType::kDAC) + { + VerifyOrExit(!isCA && pathLen == -1, error = CHIP_ERROR_INTERNAL); + } + else if (certType == AttestationCertType::kPAI) + { + VerifyOrExit(isCA && pathLen == 0, error = CHIP_ERROR_INTERNAL); + } + else + { + VerifyOrExit(isCA && (pathLen == -1 || pathLen == 0 || pathLen == 1), error = CHIP_ERROR_INTERNAL); + } + } + else if (OID_CMP(sOID_Extension_KeyUsage, extOID)) + { + mbedtls_x509_bitstring bs = { 0, 0, nullptr }; + unsigned int keyUsage = 0; + + VerifyOrExit(extCritical, error = CHIP_ERROR_INTERNAL); + extKeyUsagePresent = true; + + result = mbedtls_asn1_get_bitstring(&p, p + len, &bs); + VerifyOrExit(result == 0, error = CHIP_ERROR_INTERNAL); + + for (size_t i = 0; i < bs.CHIP_CRYPTO_PAL_PRIVATE_X509(len) && i < sizeof(unsigned int); i++) + { + keyUsage |= static_cast(bs.CHIP_CRYPTO_PAL_PRIVATE_X509(p)[i]) << (8 * i); + } + + if (certType == AttestationCertType::kDAC) + { + // SHALL only have the digitalSignature bit set. + VerifyOrExit(keyUsage == MBEDTLS_X509_KU_DIGITAL_SIGNATURE, error = CHIP_ERROR_INTERNAL); + } + else + { + bool keyCertSignFlag = keyUsage & MBEDTLS_X509_KU_KEY_CERT_SIGN; + bool crlSignFlag = keyUsage & MBEDTLS_X509_KU_CRL_SIGN; + bool otherFlags = + keyUsage & ~(MBEDTLS_X509_KU_CRL_SIGN | MBEDTLS_X509_KU_KEY_CERT_SIGN | MBEDTLS_X509_KU_DIGITAL_SIGNATURE); + VerifyOrExit(keyCertSignFlag && crlSignFlag && !otherFlags, error = CHIP_ERROR_INTERNAL); + } + } + else + { + p += len; + } + } + + // Verify basic and key usage extensions are present. + VerifyOrExit(extBasicPresent && extKeyUsagePresent, error = CHIP_ERROR_INTERNAL); + + // Verify that SKID and AKID extensions are present. + { + uint8_t kidBuf[kSubjectKeyIdentifierLength]; + MutableByteSpan kid(kidBuf); + SuccessOrExit(error = ExtractSKIDFromX509Cert(cert, kid)); + if (certType == AttestationCertType::kDAC || certType == AttestationCertType::kPAI) + { + // Mandatory extension for DAC and PAI certs. + SuccessOrExit(error = ExtractAKIDFromX509Cert(cert, kid)); + } + } + +exit: + _log_mbedTLS_error(result); + mbedtls_x509_crt_free(&mbed_cert); + +#else + (void) cert; + (void) certType; + CHIP_ERROR error = CHIP_ERROR_NOT_IMPLEMENTED; +#endif // defined(MBEDTLS_X509_CRT_PARSE_C) + + return error; +} + +CHIP_ERROR ValidateCertificateChain(const uint8_t * rootCertificate, size_t rootCertificateLen, const uint8_t * caCertificate, + size_t caCertificateLen, const uint8_t * leafCertificate, size_t leafCertificateLen, + CertificateChainValidationResult & result) +{ +#if defined(MBEDTLS_X509_CRT_PARSE_C) + CHIP_ERROR error = CHIP_NO_ERROR; + mbedtls_x509_crt certChain; + mbedtls_x509_crt rootCert; + int mbedResult; + uint32_t flags = 0; + + result = CertificateChainValidationResult::kInternalFrameworkError; + + VerifyOrReturnError(rootCertificate != nullptr && rootCertificateLen != 0, + (result = CertificateChainValidationResult::kRootArgumentInvalid, CHIP_ERROR_INVALID_ARGUMENT)); + VerifyOrReturnError(leafCertificate != nullptr && leafCertificateLen != 0, + (result = CertificateChainValidationResult::kLeafArgumentInvalid, CHIP_ERROR_INVALID_ARGUMENT)); + + mbedtls_x509_crt_init(&certChain); + mbedtls_x509_crt_init(&rootCert); + + /* Start of chain */ + mbedResult = mbedtls_x509_crt_parse(&certChain, Uint8::to_const_uchar(leafCertificate), leafCertificateLen); + VerifyOrExit(mbedResult == 0, (result = CertificateChainValidationResult::kLeafFormatInvalid, error = CHIP_ERROR_INTERNAL)); + + /* Add the intermediate to the chain, if present */ + if (caCertificate != nullptr && caCertificateLen > 0) + { + mbedResult = mbedtls_x509_crt_parse(&certChain, Uint8::to_const_uchar(caCertificate), caCertificateLen); + VerifyOrExit(mbedResult == 0, (result = CertificateChainValidationResult::kICAFormatInvalid, error = CHIP_ERROR_INTERNAL)); + } + + /* Parse the root cert */ + mbedResult = mbedtls_x509_crt_parse(&rootCert, Uint8::to_const_uchar(rootCertificate), rootCertificateLen); + VerifyOrExit(mbedResult == 0, (result = CertificateChainValidationResult::kRootFormatInvalid, error = CHIP_ERROR_INTERNAL)); + + /* Verify the chain against the root */ + mbedResult = + mbedtls_x509_crt_verify(&certChain, &rootCert, nullptr, nullptr, &flags, CallbackForCustomValidityCheck, &certChain); + + switch (mbedResult) + { + case 0: + VerifyOrExit(flags == 0, (result = CertificateChainValidationResult::kInternalFrameworkError, error = CHIP_ERROR_INTERNAL)); + result = CertificateChainValidationResult::kSuccess; + break; + case MBEDTLS_ERR_X509_INVALID_DATE: + case MBEDTLS_ERR_X509_CERT_VERIFY_FAILED: + result = CertificateChainValidationResult::kChainInvalid; + error = CHIP_ERROR_CERT_NOT_TRUSTED; + break; + default: + 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; +} + +CHIP_ERROR IsCertificateValidAtIssuance(const ByteSpan & candidateCertificate, const ByteSpan & issuerCertificate) +{ +#if defined(MBEDTLS_X509_CRT_PARSE_C) + CHIP_ERROR error = CHIP_NO_ERROR; + mbedtls_x509_crt mbedCandidateCertificate; + mbedtls_x509_crt mbedIssuerCertificate; + int result; + + VerifyOrReturnError(!candidateCertificate.empty() && !issuerCertificate.empty(), CHIP_ERROR_INVALID_ARGUMENT); + + mbedtls_x509_crt_init(&mbedCandidateCertificate); + mbedtls_x509_crt_init(&mbedIssuerCertificate); + + result = mbedtls_x509_crt_parse(&mbedCandidateCertificate, Uint8::to_const_uchar(candidateCertificate.data()), + candidateCertificate.size()); + VerifyOrExit(result == 0, error = CHIP_ERROR_INTERNAL); + + result = + mbedtls_x509_crt_parse(&mbedIssuerCertificate, Uint8::to_const_uchar(issuerCertificate.data()), issuerCertificate.size()); + VerifyOrExit(result == 0, error = CHIP_ERROR_INTERNAL); + + // Verify that the candidateCertificate has a notBefore time valid within the validity period of the issuerCertificate. + SuccessOrExit(error = IsCertificateValidAtIssuance(&mbedCandidateCertificate, &mbedIssuerCertificate)); + +exit: + _log_mbedTLS_error(result); + mbedtls_x509_crt_free(&mbedCandidateCertificate); + mbedtls_x509_crt_free(&mbedIssuerCertificate); + +#else + (void) candidateCertificate; + (void) issuerCertificate; + CHIP_ERROR error = CHIP_ERROR_NOT_IMPLEMENTED; +#endif // defined(MBEDTLS_X509_CRT_PARSE_C) + + return error; +} + +CHIP_ERROR IsCertificateValidAtCurrentTime(const ByteSpan & certificate) +{ +#if defined(MBEDTLS_X509_CRT_PARSE_C) + CHIP_ERROR error = CHIP_NO_ERROR; + mbedtls_x509_crt mbedCertificate; + int result; + + VerifyOrReturnError(!certificate.empty(), CHIP_ERROR_INVALID_ARGUMENT); + + mbedtls_x509_crt_init(&mbedCertificate); + + result = mbedtls_x509_crt_parse(&mbedCertificate, Uint8::to_const_uchar(certificate.data()), certificate.size()); + VerifyOrExit(result == 0, error = CHIP_ERROR_INTERNAL); + + // check if certificate's notBefore timestamp is earlier than or equal to current time. + result = mbedtls_x509_time_is_past(&mbedCertificate.CHIP_CRYPTO_PAL_PRIVATE_X509(valid_from)); + VerifyOrExit(result == 1, error = CHIP_ERROR_CERT_EXPIRED); + + // check if certificate's notAfter timestamp is later than current time. + result = mbedtls_x509_time_is_future(&mbedCertificate.CHIP_CRYPTO_PAL_PRIVATE_X509(valid_to)); + VerifyOrExit(result == 1, error = CHIP_ERROR_CERT_EXPIRED); + +exit: + _log_mbedTLS_error(result); + mbedtls_x509_crt_free(&mbedCertificate); + +#else + (void) certificate; + CHIP_ERROR error = CHIP_ERROR_NOT_IMPLEMENTED; +#endif // defined(MBEDTLS_X509_CRT_PARSE_C) + + return error; +} + +CHIP_ERROR ExtractPubkeyFromX509Cert(const ByteSpan & certificate, Crypto::P256PublicKey & pubkey) +{ +#if defined(MBEDTLS_X509_CRT_PARSE_C) + CHIP_ERROR error = CHIP_NO_ERROR; + mbedtls_x509_crt mbed_cert; + ecp256KeyPair_t * 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 = (ecp256KeyPair_t *) (mbed_cert.CHIP_CRYPTO_PAL_PRIVATE_X509(pk)).pk_ctx; + Uint8::to_uchar(pubkey)[0] = 0x04; // uncompressed type + memcpy(Uint8::to_uchar(pubkey) + 1, keypair->public_key.raw, 2 * ECP256_COORDINATE_LEN); + + VerifyOrExit(result == 0, error = CHIP_ERROR_INTERNAL); + +exit: + _log_mbedTLS_error(result); + mbedtls_x509_crt_free(&mbed_cert); + +#else + (void) certificate; + (void) pubkey; + CHIP_ERROR error = CHIP_ERROR_NOT_IMPLEMENTED; +#endif // defined(MBEDTLS_X509_CRT_PARSE_C) + + return error; +} +namespace { + +CHIP_ERROR ExtractKIDFromX509Cert(bool extractSKID, const ByteSpan & certificate, MutableByteSpan & kid) +{ +#if defined(MBEDTLS_X509_CRT_PARSE_C) + CHIP_ERROR error = CHIP_ERROR_NOT_FOUND; + mbedtls_x509_crt mbed_cert; + unsigned char * p = nullptr; + const unsigned char * end = nullptr; + size_t len = 0; + + mbedtls_x509_crt_init(&mbed_cert); + + int result = mbedtls_x509_crt_parse(&mbed_cert, Uint8::to_const_uchar(certificate.data()), certificate.size()); + VerifyOrExit(result == 0, error = CHIP_ERROR_INTERNAL); + + // TODO: The mbedTLS team is working on supporting SKID and AKID extensions processing. + // Once it is supported, this code should be updated. + + p = mbed_cert.CHIP_CRYPTO_PAL_PRIVATE_X509(v3_ext).CHIP_CRYPTO_PAL_PRIVATE_X509(p); + end = mbed_cert.CHIP_CRYPTO_PAL_PRIVATE_X509(v3_ext).CHIP_CRYPTO_PAL_PRIVATE_X509(p) + + mbed_cert.CHIP_CRYPTO_PAL_PRIVATE_X509(v3_ext).CHIP_CRYPTO_PAL_PRIVATE_X509(len); + result = mbedtls_asn1_get_tag(&p, end, &len, MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE); + VerifyOrExit(result == 0, error = CHIP_ERROR_WRONG_CERT_TYPE); + + while (p < end) + { + result = mbedtls_asn1_get_tag(&p, end, &len, MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE); + VerifyOrExit(result == 0, error = CHIP_ERROR_WRONG_CERT_TYPE); + result = mbedtls_asn1_get_tag(&p, end, &len, MBEDTLS_ASN1_OID); + VerifyOrExit(result == 0, error = CHIP_ERROR_WRONG_CERT_TYPE); + + mbedtls_x509_buf extOID = { MBEDTLS_ASN1_OID, len, p }; + bool extractCurrentExtSKID = extractSKID && OID_CMP(sOID_Extension_SubjectKeyIdentifier, extOID); + bool extractCurrentExtAKID = !extractSKID && OID_CMP(sOID_Extension_AuthorityKeyIdentifier, extOID); + p += len; + + int is_critical = 0; + result = mbedtls_asn1_get_bool(&p, end, &is_critical); + VerifyOrExit(result == 0 || result == MBEDTLS_ERR_ASN1_UNEXPECTED_TAG, error = CHIP_ERROR_WRONG_CERT_TYPE); + + result = mbedtls_asn1_get_tag(&p, end, &len, MBEDTLS_ASN1_OCTET_STRING); + VerifyOrExit(result == 0, error = CHIP_ERROR_WRONG_CERT_TYPE); + + if (extractCurrentExtSKID || extractCurrentExtAKID) + { + if (extractCurrentExtSKID) + { + result = mbedtls_asn1_get_tag(&p, end, &len, MBEDTLS_ASN1_OCTET_STRING); + VerifyOrExit(result == 0, error = CHIP_ERROR_WRONG_CERT_TYPE); + } + else + { + result = mbedtls_asn1_get_tag(&p, end, &len, MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE); + VerifyOrExit(result == 0, error = CHIP_ERROR_WRONG_CERT_TYPE); + result = mbedtls_asn1_get_tag(&p, end, &len, MBEDTLS_ASN1_CONTEXT_SPECIFIC); + VerifyOrExit(result == 0, error = CHIP_ERROR_WRONG_CERT_TYPE); + // Other optional fields, authorityCertIssuer and authorityCertSerialNumber, + // will be skipped if present. + } + VerifyOrExit(len == kSubjectKeyIdentifierLength, error = CHIP_ERROR_WRONG_CERT_TYPE); + VerifyOrExit(len <= kid.size(), error = CHIP_ERROR_BUFFER_TOO_SMALL); + memcpy(kid.data(), p, len); + if (kid.size() > len) + { + kid.reduce_size(len); + } + ExitNow(error = CHIP_NO_ERROR); + break; + } + p += len; + } + +exit: + _log_mbedTLS_error(result); + mbedtls_x509_crt_free(&mbed_cert); + +#else + (void) certificate; + (void) kid; + CHIP_ERROR error = CHIP_ERROR_NOT_IMPLEMENTED; +#endif // defined(MBEDTLS_X509_CRT_PARSE_C) + + return error; +} + +} // namespace + +CHIP_ERROR ExtractSKIDFromX509Cert(const ByteSpan & certificate, MutableByteSpan & skid) +{ + return ExtractKIDFromX509Cert(true, certificate, skid); +} + +CHIP_ERROR ExtractAKIDFromX509Cert(const ByteSpan & certificate, MutableByteSpan & akid) +{ + return ExtractKIDFromX509Cert(false, certificate, akid); +} + +CHIP_ERROR ExtractVIDPIDFromX509Cert(const ByteSpan & certificate, AttestationCertVidPid & vidpid) +{ +#if defined(MBEDTLS_X509_CRT_PARSE_C) + CHIP_ERROR error = CHIP_NO_ERROR; + mbedtls_x509_crt mbed_cert; + mbedtls_asn1_named_data * dnIterator = nullptr; + AttestationCertVidPid vidpidFromCN; + + mbedtls_x509_crt_init(&mbed_cert); + + int result = mbedtls_x509_crt_parse(&mbed_cert, Uint8::to_const_uchar(certificate.data()), certificate.size()); + VerifyOrExit(result == 0, error = CHIP_ERROR_INTERNAL); + + for (dnIterator = &mbed_cert.CHIP_CRYPTO_PAL_PRIVATE_X509(subject); dnIterator != nullptr; + dnIterator = dnIterator->CHIP_CRYPTO_PAL_PRIVATE_X509(next)) + { + DNAttrType attrType = DNAttrType::kUnspecified; + if (OID_CMP(sOID_AttributeType_CommonName, dnIterator->CHIP_CRYPTO_PAL_PRIVATE_X509(oid))) + { + attrType = DNAttrType::kCommonName; + } + else if (OID_CMP(sOID_AttributeType_MatterVendorId, dnIterator->CHIP_CRYPTO_PAL_PRIVATE_X509(oid))) + { + attrType = DNAttrType::kMatterVID; + } + else if (OID_CMP(sOID_AttributeType_MatterProductId, dnIterator->CHIP_CRYPTO_PAL_PRIVATE_X509(oid))) + { + attrType = DNAttrType::kMatterPID; + } + + size_t val_len = dnIterator->CHIP_CRYPTO_PAL_PRIVATE_X509(val).CHIP_CRYPTO_PAL_PRIVATE_X509(len); + uint8_t * val_p = dnIterator->CHIP_CRYPTO_PAL_PRIVATE_X509(val).CHIP_CRYPTO_PAL_PRIVATE_X509(p); + error = ExtractVIDPIDFromAttributeString(attrType, ByteSpan(val_p, val_len), vidpid, vidpidFromCN); + SuccessOrExit(error); + } + + // If Matter Attributes were not found use values extracted from the CN Attribute, + // which might be uninitialized as well. + if (!vidpid.Initialized()) + { + vidpid = vidpidFromCN; + } + +exit: + _log_mbedTLS_error(result); + mbedtls_x509_crt_free(&mbed_cert); + +#else + (void) certificate; + (void) vidpid; + CHIP_ERROR error = CHIP_ERROR_NOT_IMPLEMENTED; +#endif // defined(MBEDTLS_X509_CRT_PARSE_C) + + return error; +} + +} // namespace Crypto +} // namespace chip diff --git a/src/platform/nxp/k32w/k32w0/gatt_db.h b/src/platform/nxp/k32w/k32w0/gatt_db.h index be0976ff1bffbb..666d4b3f09fc23 100644 --- a/src/platform/nxp/k32w/k32w0/gatt_db.h +++ b/src/platform/nxp/k32w/k32w0/gatt_db.h @@ -5,7 +5,7 @@ CCCD(cccd_service_changed) PRIMARY_SERVICE(service_gap, gBleSig_GenericAccessProfile_d) CHARACTERISTIC(char_device_name, gBleSig_GapDeviceName_d, (gGattCharPropRead_c)) -VALUE(value_device_name, gBleSig_GapDeviceName_d, (gPermissionFlagReadable_c), 16, "NXP_ELOCK_DEMO") +VALUE(value_device_name, gBleSig_GapDeviceName_d, (gPermissionFlagReadable_c), 18, "NXP_PLATFORM_DEMO") CHARACTERISTIC(char_appearance, gBleSig_GapAppearance_d, (gGattCharPropRead_c)) VALUE(value_appearance, gBleSig_GapAppearance_d, (gPermissionFlagReadable_c), 2, 0x00, 0x00) @@ -15,10 +15,13 @@ VALUE_UUID128_VARLEN(value_chipoble_rx, uuid_chipoble_rx, (gPermissionFlagWritab CHARACTERISTIC_UUID128(chipoble_tx, uuid_chipoble_tx, (gGattCharPropIndicate_c | gGattCharPropRead_c)) VALUE_UUID128_VARLEN(value_chipoble_tx, uuid_chipoble_tx, (gPermissionFlagReadable_c), gAttMaxMtu_c - 3, gAttMaxMtu_c - 3, 0x00) CCCD(cccd_chipoble_tx) +CHARACTERISTIC_UUID128(chipoble_c3, uuid_chipoble_c3, (gGattCharPropRead_c)) +VALUE_UUID128_VARLEN(value_chipoble_c3, uuid_chipoble_c3, (gPermissionFlagReadable_c), gAttMaxReadDataSize_d(gAttMaxValueLength_c), + gAttMaxReadDataSize_d(gAttMaxValueLength_c), 0x00) PRIMARY_SERVICE(service_device_info, gBleSig_DeviceInformationService_d) CHARACTERISTIC(char_model_no, gBleSig_ModelNumberString_d, (gGattCharPropRead_c)) -VALUE(value_model_no, gBleSig_ModelNumberString_d, (gPermissionFlagReadable_c), 15, "Chip ELock Demo") +VALUE(value_model_no, gBleSig_ModelNumberString_d, (gPermissionFlagReadable_c), 16, "Chip K32W0 Demo") CHARACTERISTIC(char_serial_no, gBleSig_SerialNumberString_d, (gGattCharPropRead_c)) VALUE(value_serial_no, gBleSig_SerialNumberString_d, (gPermissionFlagReadable_c), 7, "BLESN01") CHARACTERISTIC(char_fw_rev, gBleSig_FirmwareRevisionString_d, (gGattCharPropRead_c)) diff --git a/src/platform/nxp/k32w/k32w0/gatt_uuid128.h b/src/platform/nxp/k32w/k32w0/gatt_uuid128.h index 442de5a2814186..938968b1943ce2 100644 --- a/src/platform/nxp/k32w/k32w0/gatt_uuid128.h +++ b/src/platform/nxp/k32w/k32w0/gatt_uuid128.h @@ -23,3 +23,4 @@ UUID128(uuid_chipoble_tx, 0x12, 0x9D, 0x9F, 0x42, 0x9C, 0x4F, 0x9F, 0x95, 0x59, 0x45, 0x3D, 0x26, 0xF5, 0x2E, 0xEE, 0x18) UUID128(uuid_chipoble_rx, 0x11, 0x9D, 0x9F, 0x42, 0x9C, 0x4F, 0x9F, 0x95, 0x59, 0x45, 0x3D, 0x26, 0xF5, 0x2E, 0xEE, 0x18) +UUID128(uuid_chipoble_c3, 0x04, 0x8f, 0x21, 0x83, 0x8a, 0x74, 0x7d, 0xb8, 0xf2, 0x45, 0x72, 0x87, 0x38, 0x02, 0x63, 0x64) diff --git a/src/platform/nxp/k32w/k32w0/k32w0-chip-mbedtls-config.h b/src/platform/nxp/k32w/k32w0/k32w0-chip-mbedtls-config.h index 1e795ddc8e5d12..e24aad2f9e0200 100644 --- a/src/platform/nxp/k32w/k32w0/k32w0-chip-mbedtls-config.h +++ b/src/platform/nxp/k32w/k32w0/k32w0-chip-mbedtls-config.h @@ -121,9 +121,9 @@ #if defined(FSL_FEATURE_SOC_SHA_COUNT) && (FSL_FEATURE_SOC_SHA_COUNT > 0) #include "fsl_sha.h" -#define SHA_INSTANCE SHA0 /* SHA base register.*/ -#define MBEDTLS_FREESCALE_LPC_SHA1 /* Enable use of LPC SHA.*/ -//#define MBEDTLS_FREESCALE_LPC_SHA256 /* Enable use of LPC SHA256.*/ +#define SHA_INSTANCE SHA0 /* SHA base register.*/ +#define MBEDTLS_FREESCALE_LPC_SHA1 /* Enable use of LPC SHA.*/ +#define MBEDTLS_FREESCALE_LPC_SHA256 /* Enable use of LPC SHA256.*/ #endif diff --git a/third_party/nxp/k32w0_sdk/BUILD.gn b/third_party/nxp/k32w0_sdk/BUILD.gn index c6cff80b87c915..efc1d786420239 100644 --- a/third_party/nxp/k32w0_sdk/BUILD.gn +++ b/third_party/nxp/k32w0_sdk/BUILD.gn @@ -30,13 +30,6 @@ 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=", @@ -68,7 +61,7 @@ config("mbedtls_k32w0_config") { ] } - if (chip_crypto == "tinycrypt") { + if (chip_crypto == "platform" && chip_crypto_flavor == "tinycrypt") { defines += [ "MBEDTLS_USE_TINYCRYPT", "MBEDTLS_OPTIMIZE_TINYCRYPT_ASM", @@ -77,22 +70,25 @@ config("mbedtls_k32w0_config") { include_dirs = [ chip_root ] - if (chip_crypto == "tinycrypt") { - include_dirs += [ "${mbedtls_repo}/repo/include/tinycrypt" ] + if (chip_crypto == "platform" && chip_crypto_flavor == "tinycrypt") { + include_dirs += [ + "${chip_root}/third_party/openthread/ot-nxp/third_party/tinycrypt/inc", + ] } } mbedtls_target("mbedtls") { sources = [ - "${chip_root}/src/platform/nxp/k32w/k32w0/crypto/ksdk_mbedtls.c", "${k32w0_sdk_root}/middleware/mbedtls/port/ksdk/aes_alt.c", + "${k32w0_sdk_root}/middleware/mbedtls/port/matter/ksdk_mbedtls.c", ] - if (chip_crypto == "tinycrypt") { + if (chip_crypto == "platform" && chip_crypto_flavor == "tinycrypt") { sources += [ - "${mbedtls_repo}/repo/tinycrypt/ecc.c", - "${mbedtls_repo}/repo/tinycrypt/ecc_dh.c", - "${mbedtls_repo}/repo/tinycrypt/ecc_dsa.c", + "${chip_root}/third_party/openthread/ot-nxp/third_party/tinycrypt/src/ecc.c", + "${chip_root}/third_party/openthread/ot-nxp/third_party/tinycrypt/src/ecc_dh.c", + "${chip_root}/third_party/openthread/ot-nxp/third_party/tinycrypt/src/ecc_dsa.c", + "${chip_root}/third_party/openthread/ot-nxp/third_party/tinycrypt/src/tinycrypt_util.c", ] } diff --git a/third_party/nxp/k32w0_sdk/k32w0_sdk.gni b/third_party/nxp/k32w0_sdk/k32w0_sdk.gni index 0f48c70daffeaf..88c0769a9d47ed 100644 --- a/third_party/nxp/k32w0_sdk/k32w0_sdk.gni +++ b/third_party/nxp/k32w0_sdk/k32w0_sdk.gni @@ -20,6 +20,7 @@ import("//build_overrides/openthread.gni") import("${build_root}/config/compiler/compiler.gni") import("${chip_root}/src/crypto/crypto.gni") +import("${chip_root}/src/lib/core/core.gni") import("${chip_root}/src/platform/nxp/k32w/k32w0/args.gni") declare_args() { @@ -38,10 +39,20 @@ declare_args() { chip_with_ntag = 1 chip_with_high_power = 0 chip_with_factory_data = 0 + use_fro_32k = 0 + use_custom_factory_provider = 0 + chip_crypto_flavor = "NXP-Ultrafast-P256" + chip_reduce_ssbl_size = false } assert(k32w0_sdk_root != "", "k32w0_sdk_root must be specified") +if (chip_crypto == "platform") { + assert(chip_crypto_flavor == "tinycrypt" || + chip_crypto_flavor == "NXP-Ultrafast-P256", + "choose tinycrypt or NXP-Ultrafast-P256 as crypto platform") +} + # Defines an k32w SDK build target. # # Parameters: @@ -66,12 +77,17 @@ template("k32w0_sdk") { "Please disable low power if expansion board, openthread CLI or SE is needed!") assert(chip_with_low_power == 0 || - (invoker.chip_detail_logging == false && - invoker.chip_progress_logging == false && - invoker.chip_automation_logging == false && - invoker.chip_error_logging == false), + (chip_logging == false && + (invoker.chip_detail_logging == false && + invoker.chip_progress_logging == false && + invoker.chip_automation_logging == false && + invoker.chip_error_logging == false)), "Please disable all logs when low power is enabled!") + assert( + use_custom_factory_provider == 0 || chip_with_factory_data == 1, + "Please set chip_with_factory_data=1 if using custom factory provider.") + if (build_for_k32w041am == 1 || build_for_k32w041a == 1 || build_for_k32w041 == 1) { build_for_k32w061 = 0 @@ -117,7 +133,14 @@ template("k32w0_sdk") { print("device:", device) print("board:", board) print("ntag:", chip_with_ntag) - print("high power:", chip_with_high_power) + print("increased TX power:", chip_with_high_power) + print("FRO32k: ", use_fro_32k) + print("low power: ", chip_with_low_power) + + if (chip_crypto == "platform") { + print("ECC crypto lib: ", chip_crypto_flavor) + } + device_lowercase = string_replace(board, "dk6", "") sdk_target_name = target_name @@ -133,6 +156,15 @@ template("k32w0_sdk") { # we will add them to cflags below instead. _sdk_include_dirs = [] + # Directories specified with -isystem options are scanned in left-to-right order. + # sha256_alt.h is present in both these paths, but the one from port/matter will + # be selected, which is intended. Both paths are needed, because some header + # files are not overwritten (e.g. aes_alt.h). + _sdk_include_dirs += [ + "${k32w0_sdk_root}/middleware/mbedtls/port/matter", + "${k32w0_sdk_root}/middleware/mbedtls/port/ksdk", + ] + if (chip_with_DK6) { if (chip_with_low_power != 0) { _sdk_include_dirs += [ "${k32w0_sdk_root}/boards/${board}/wireless_examples/openthread/lped/bm" ] @@ -164,7 +196,6 @@ template("k32w0_sdk") { "${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/wireless/ble_controller/interface", "${k32w0_sdk_root}/middleware/wireless/bluetooth/application/common", "${k32w0_sdk_root}/middleware/wireless/bluetooth/application/common/gatt_db", @@ -209,10 +240,16 @@ template("k32w0_sdk") { "${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", ] + if (chip_crypto == "platform" && + chip_crypto_flavor == "NXP-Ultrafast-P256") { + libs += [ "${k32w0_sdk_root}/middleware/wireless/framework/SecLib/lib_crypto_m4_dspext.a" ] + } else { + libs += [ "${k32w0_sdk_root}/middleware/wireless/framework/SecLib/lib_crypto_m4.a" ] + } + defines = [ "gPWR_CpuClk_48MHz=1", "gMainThreadPriority_c=5", @@ -238,6 +275,8 @@ template("k32w0_sdk") { "gOtaVerifyWrite_d=0", "gExternalFlashIsCiphered_d=1", "PDM_USE_DYNAMIC_MEMORY=1", + "PDM_SAVE_IDLE=1", + "PDM_ENCRYPTION=1", "gBootData_None_c=1", "PROGRAM_PAGE_SZ=256", "configFRTOS_MEMORY_SCHEME=4", @@ -265,8 +304,21 @@ template("k32w0_sdk") { "HEAP_SIZE=gTotalHeapSize_c", "gLoggingActive_d=0", "gLogRingPlacementOffset_c=0xF000", + "gSecLibUseSha256Alt_d=1", + "gOTA_UseSecLibAes=1", ] + if (chip_crypto == "platform" && + chip_crypto_flavor == "NXP-Ultrafast-P256") { + defines += [ "EC_P256_DSPEXT=1" ] + } + + if (use_fro_32k == 1) { + defines += [ "gClkUseFro32K=1" ] + } else { + defines += [ "gClkUseFro32K=0" ] + } + if (chip_mdns == "platform") { defines += [ "OPENTHREAD_CONFIG_SRP_CLIENT_ENABLE=1", @@ -323,10 +375,8 @@ template("k32w0_sdk") { "cPWR_UsePowerDownMode=1", "cPWR_FullPowerDownMode=1", "DBG_PostStepTickAssess=0", - "gApp_SystemClockCalibration=1", "gPWR_FreqScalingWFI=0", "mAppUseTickLessMode_c=1", - "App_SuppressTickInStopMode=0", "cPWR_DiscardRunningTimerForPowerDown=1", "K32W_LOG_ENABLED=0", "gUartDebugConsole_d=0", @@ -466,6 +516,7 @@ template("k32w0_sdk") { "${k32w0_sdk_root}/middleware/wireless/framework/RNG/Source/RNG.c", "${k32w0_sdk_root}/middleware/wireless/framework/Reset/Reset.c", "${k32w0_sdk_root}/middleware/wireless/framework/SecLib/SecLib.c", + "${k32w0_sdk_root}/middleware/wireless/framework/SecLib/SecLib_ecp256_sw.c", "${k32w0_sdk_root}/middleware/wireless/framework/SerialManager/Source/SerialManager.c", "${k32w0_sdk_root}/middleware/wireless/framework/SerialManager/Source/UART_Serial_Adapter.c", "${k32w0_sdk_root}/middleware/wireless/framework/TimersManager/Source/TMR_Adapter.c", diff --git a/third_party/nxp/k32w0_sdk/sdk_fixes/OtaUtils_h.patch b/third_party/nxp/k32w0_sdk/sdk_fixes/OtaUtils_h.patch deleted file mode 100644 index 35e998bc6e68ca..00000000000000 --- a/third_party/nxp/k32w0_sdk/sdk_fixes/OtaUtils_h.patch +++ /dev/null @@ -1,24 +0,0 @@ ---- a/OtaUtils.h -+++ b/OtaUtils.h -@@ -77,6 +77,10 @@ typedef otaUtilsResult_t (*OtaUtils_ReadBytes)(uint16_t nbBytes, - ************************************************************************************* - ********************************************************************************** */ - -+#ifdef __cplusplus -+extern "C" { -+#endif -+ - /*! ********************************************************************************* - * \brief Allows to read bytes from the Internal Flash - * -@@ -185,6 +189,8 @@ uint32_t OtaUtils_ValidateImage(OtaUtils_ReadBytes pFunctionRead, - ********************************************************************************** */ - otaUtilsResult_t OtaUtils_ReconstructRootCert(IMAGE_CERT_T *pCert, const psector_page_data_t* pPage0, const psector_page_data_t* pFlashPage); - -- -+#ifdef __cplusplus -+} -+#endif - - #endif /* _OTA_UTILS_H_ */ -\ No newline at end of file diff --git a/third_party/nxp/k32w0_sdk/sdk_fixes/fsl_os_abstraction_free_rtos_c.patch b/third_party/nxp/k32w0_sdk/sdk_fixes/fsl_os_abstraction_free_rtos_c.patch deleted file mode 100644 index 2221c979f07b72..00000000000000 --- a/third_party/nxp/k32w0_sdk/sdk_fixes/fsl_os_abstraction_free_rtos_c.patch +++ /dev/null @@ -1,54 +0,0 @@ ---- a/fsl_os_abstraction_free_rtos.c -+++ b/fsl_os_abstraction_free_rtos.c -@@ -344,6 +344,12 @@ osaStatus_t OSA_SemaphoreWait(osaSemaphoreId_t semId, uint32_t millisec) - { - #if osNumberOfSemaphores - uint32_t timeoutTicks; -+ -+ if (xTaskGetSchedulerState() == taskSCHEDULER_SUSPENDED) -+ { -+ return osaStatus_Success; -+ } -+ - if(semId == NULL) - { - return osaStatus_Error; -@@ -388,6 +394,12 @@ osaStatus_t OSA_SemaphorePost(osaSemaphoreId_t semId) - { - #if osNumberOfSemaphores - osaStatus_t status = osaStatus_Error; -+ -+ if (xTaskGetSchedulerState() == taskSCHEDULER_SUSPENDED) -+ { -+ return osaStatus_Success; -+ } -+ - if(semId) - { - semaphore_t sem = (semaphore_t)semId; -@@ -461,6 +473,12 @@ osaStatus_t OSA_MutexLock(osaMutexId_t mutexId, uint32_t millisec) - #if osNumberOfMutexes - uint32_t timeoutTicks; - mutex_t mutex = (mutex_t)mutexId; -+ -+ if (xTaskGetSchedulerState() == taskSCHEDULER_SUSPENDED) -+ { -+ return osaStatus_Success; -+ } -+ - if(mutexId == NULL) - { - return osaStatus_Error; -@@ -506,6 +524,12 @@ osaStatus_t OSA_MutexUnlock(osaMutexId_t mutexId) - { - #if osNumberOfMutexes - mutex_t mutex = (mutex_t)mutexId; -+ -+ if (xTaskGetSchedulerState() == taskSCHEDULER_SUSPENDED) -+ { -+ return osaStatus_Success; -+ } -+ - if(mutexId == NULL) - { - return osaStatus_Error; 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 5d2a66bae9283d..9f7a1c517177a8 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 @@ -15,11 +15,5 @@ convert_to_dos() { SOURCE=${BASH_SOURCE[0]} SOURCE_DIR=$(cd "$(dirname "$SOURCE")" >/dev/null 2>&1 && pwd) -convert_to_dos "$NXP_K32W0_SDK_ROOT"/middleware/wireless/framework/OSAbstraction/Source/fsl_os_abstraction_free_rtos.c -convert_to_dos "$NXP_K32W0_SDK_ROOT"/middleware/wireless/framework/OtaSupport/Interface/OtaUtils.h - -patch -N --binary -d "$NXP_K32W0_SDK_ROOT"/middleware/wireless/framework/OSAbstraction/Source/ -p1 <"$SOURCE_DIR/fsl_os_abstraction_free_rtos_c.patch" -patch -N --binary -d "$NXP_K32W0_SDK_ROOT"/middleware/wireless/framework/OtaSupport/Interface/ -p1 <"$SOURCE_DIR/OtaUtils_h.patch" - -echo "K32W SDK 2.6.7 was patched!" +echo "K32W0 SDK 2.6.9 no patch needed!" exit 0 diff --git a/third_party/nxp/libs/mbedtls/repo b/third_party/nxp/libs/mbedtls/repo deleted file mode 160000 index 62e0eb9f5ae044..00000000000000 --- a/third_party/nxp/libs/mbedtls/repo +++ /dev/null @@ -1 +0,0 @@ -Subproject commit 62e0eb9f5ae0448d03a420b5f5c76c1311b31b30 diff --git a/third_party/openthread/ot-nxp b/third_party/openthread/ot-nxp index aa5d627e8cd880..4c2fa0d3d29c35 160000 --- a/third_party/openthread/ot-nxp +++ b/third_party/openthread/ot-nxp @@ -1 +1 @@ -Subproject commit aa5d627e8cd8808b34d8403e71b9954498e9aea6 +Subproject commit 4c2fa0d3d29c358fbdc57fa627ed2ba1e76dcdfc diff --git a/third_party/openthread/platforms/nxp/k32w/k32w0/BUILD.gn b/third_party/openthread/platforms/nxp/k32w/k32w0/BUILD.gn index 1edf9ab9e960c4..0bf402053b8e80 100644 --- a/third_party/openthread/platforms/nxp/k32w/k32w0/BUILD.gn +++ b/third_party/openthread/platforms/nxp/k32w/k32w0/BUILD.gn @@ -37,7 +37,6 @@ config("openthread_k32w0_config") { defines = [ "OPENTHREAD_CONFIG_HEAP_EXTERNAL_ENABLE=1", "OPENTHREAD_CONFIG_IP6_SLAAC_ENABLE=1", - "PDM_SAVE_IDLE=1", "K32W0_RADIO_NUM_OF_RX_BUFS=16", ] } @@ -58,6 +57,7 @@ source_set("openthread_mbedtls_config_k32w0") { source_set("libopenthread-k32w0") { sources = [ + "${openthread_nxp_root}/src/common/crypto.c", "${openthread_nxp_root}/src/common/ram_storage.c", "${openthread_nxp_root}/src/k32w0/platform/alarm.c", "${openthread_nxp_root}/src/k32w0/platform/diag.c", @@ -72,6 +72,17 @@ source_set("libopenthread-k32w0") { "${openthread_nxp_root}/src/k32w0/platform/uart.c", ] + if (chip_crypto == "platform" && chip_crypto_flavor == "tinycrypt") { + sources += + [ "${openthread_nxp_root}/src/common/crypto/ecdsa_tinycrypt.cpp" ] + } + + if (chip_crypto == "platform" && chip_crypto_flavor == "NXP-Ultrafast-P256") { + sources += [ + "${openthread_nxp_root}/src/k32w0/platform/ecdsa-nxp-ultrafast-p256.cpp", + ] + } + if (chip_with_ot_cli == 1) { sources += [ "${openthread_root}/examples/apps/cli/cli_uart.cpp" ] } @@ -79,6 +90,7 @@ source_set("libopenthread-k32w0") { public_deps = [ ":openthread_core_config_k32w0", "${k32w0_sdk_build_root}:k32w0_sdk", + "${k32w0_sdk_build_root}:mbedtls", "${openthread_root}/src/core:libopenthread_core_headers", "../../..:libopenthread-platform", "../../..:libopenthread-platform-utils", diff --git a/zzz_generated/lock-app/nxp/zap-generated/af-gen-event.h b/zzz_generated/lock-app/nxp/zap-generated/af-gen-event.h new file mode 100644 index 00000000000000..814d4aab6b8bec --- /dev/null +++ b/zzz_generated/lock-app/nxp/zap-generated/af-gen-event.h @@ -0,0 +1,39 @@ +/** + * + * Copyright (c) 2020 Project CHIP Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/** + * + * Copyright (c) 2020 Silicon Labs + * + * 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. + */ + +// Enclosing macro to prevent multiple inclusion +#ifndef __AF_GEN_EVENT__ +#define __AF_GEN_EVENT__ + +#endif // __AF_GEN_EVENT__