diff --git a/.github/workflows/examples-k32w.yaml b/.github/workflows/examples-k32w.yaml index 855f0ea88fa34b..1744acc20e91ba 100644 --- a/.github/workflows/examples-k32w.yaml +++ b/.github/workflows/examples-k32w.yaml @@ -86,7 +86,6 @@ jobs: run: | scripts/run_in_build_env.sh "\ ./scripts/build/build_examples.py \ - --target k32w-light-no-ble-se05x \ --target k32w-light-crypto-platform-tokenizer \ --target k32w-lock-crypto-platform-tokenizer \ --target k32w-lock-crypto-platform-low-power-nologs \ diff --git a/.gn b/.gn index 604bc15b848d69..742fdc4273d666 100644 --- a/.gn +++ b/.gn @@ -27,7 +27,7 @@ default_args = { pw_unit_test_AUTOMATIC_RUNNER = "$dir_pigweed/targets/host/run_test" pw_build_PIP_CONSTRAINTS = [ "//scripts/setup/constraints.txt" ] - pw_build_PIP_REQUIREMENTS = [ "//scripts/setup/requirements.txt" ] + pw_build_PIP_REQUIREMENTS = [ "//scripts/setup/requirements.build.txt" ] # GN target to use for the default Python build venv. pw_build_PYTHON_BUILD_VENV = "//:matter_build_venv" diff --git a/.mergify.yml b/.mergify.yml new file mode 100644 index 00000000000000..a884d9b26d4d97 --- /dev/null +++ b/.mergify.yml @@ -0,0 +1,13 @@ +pull_request_rules: + - name: Automatic merge on PullApprove + conditions: + - "#approved-reviews-by>=1" + - "#review-threads-unresolved=0" + - "-draft" + - or: + - "check-success=pullapprove" + - "check-skipped=pullapprove" + - "check-neutral=pullapprove" + actions: + merge: + method: squash diff --git a/config/esp32/.gn b/config/esp32/.gn index 37684f9211c628..9f5db65cdad79b 100644 --- a/config/esp32/.gn +++ b/config/esp32/.gn @@ -26,8 +26,10 @@ default_args = { pw_build_PIP_CONSTRAINTS = [ "//third_party/connectedhomeip/scripts/setup/constraints.txt" ] - pw_build_PIP_REQUIREMENTS = - [ "//third_party/connectedhomeip/scripts/setup/requirements.txt" ] + pw_build_PIP_REQUIREMENTS = [ + "//third_party/connectedhomeip/scripts/setup/requirements.build.txt", + "//third_party/connectedhomeip/scripts/setup/requirements.esp32.txt", + ] import("//args.gni") } diff --git a/config/esp32/components/chip/Kconfig b/config/esp32/components/chip/Kconfig index bff112fd594046..7f6694a615bf6d 100644 --- a/config/esp32/components/chip/Kconfig +++ b/config/esp32/components/chip/Kconfig @@ -390,6 +390,39 @@ menu "CHIP Device Layer" The amount of time (in milliseconds) to wait for Internet connectivity to be established on the device's WiFi station interface during a Network Provisioning TestConnectivity operation. + choice WIFI_POWER_SAVE_MODE + prompt "WiFi power-saving mode" + default WIFI_POWER_SAVE_MIN + depends on ENABLE_WIFI_STATION && !ENABLE_WIFI_AP + help + The Modem-sleep mode which refers to the legacy power-saving mode in the IEEE 802.11 protocol. + + config WIFI_POWER_SAVE_MIN + bool "Minimal power-saving mode" + help + In minimum power-saving mode, station wakes up every DTIM to receive beacon. + + config WIFI_POWER_SAVE_MAX + bool "Maximum power-saving mode" + help + In maximum power-saving mode, station wakes up in every listen interval to receive beacon. + Listen interval can be configured by calling API 'esp_wifi_set_config()' before connecting + to AP. + + config WIFI_POWER_SAVE_NONE + bool "No power-saving" + help + No power save + + endchoice + + config WIFI_PS_LISTEN_INTERVAL + int "Listen interval for maximum power-saving mode" + depends on WIFI_POWER_SAVE_MAX + default 3 + help + Interval for station to listen to beacon from AP. The unit of listen interval is one beacon interval. + endmenu menu "WiFi AP Options" diff --git a/config/standalone/args.gni b/config/standalone/args.gni index 8ce29968cdd4a8..2bc0d7519c410b 100644 --- a/config/standalone/args.gni +++ b/config/standalone/args.gni @@ -19,4 +19,5 @@ import("//build_overrides/chip.gni") chip_build_tests = false pw_build_PIP_CONSTRAINTS = [ "${chip_root}/scripts/setup/constraints.txt" ] -pw_build_PIP_REQUIREMENTS = [ "${chip_root}/scripts/setup/requirements.txt" ] +pw_build_PIP_REQUIREMENTS = + [ "${chip_root}/scripts/setup/requirements.build.txt" ] diff --git a/examples/all-clusters-app/all-clusters-common/all-clusters-app.matter b/examples/all-clusters-app/all-clusters-common/all-clusters-app.matter index a28f341209feea..9d332ab0d7509b 100644 --- a/examples/all-clusters-app/all-clusters-common/all-clusters-app.matter +++ b/examples/all-clusters-app/all-clusters-common/all-clusters-app.matter @@ -2350,6 +2350,29 @@ server cluster ModeSelect = 80 { command ChangeToMode(ChangeToModeRequest): DefaultSuccess = 0; } +/** Attributes and commands for configuring the Refrigerator alarm. */ +server cluster RefrigeratorAlarm = 87 { + bitmap AlarmMap : BITMAP32 { + kDoorOpen = 0x1; + } + + info event Notify = 0 { + AlarmMap active = 0; + AlarmMap inactive = 1; + AlarmMap state = 2; + AlarmMap mask = 3; + } + + readonly attribute AlarmMap mask = 0; + readonly attribute AlarmMap state = 2; + readonly attribute command_id generatedCommandList[] = 65528; + readonly attribute command_id acceptedCommandList[] = 65529; + readonly attribute event_id eventList[] = 65530; + readonly attribute attrib_id attributeList[] = 65531; + readonly attribute bitmap32 featureMap = 65532; + readonly attribute int16u clusterRevision = 65533; +} + /** Attributes for reporting air quality classification */ server cluster AirQuality = 91 { enum AirQualityEnum : ENUM8 { @@ -6133,6 +6156,18 @@ endpoint 1 { ram attribute manufacturerExtension default = 255; } + server cluster RefrigeratorAlarm { + emits event Notify; + ram attribute mask default = 1; + ram attribute state default = 0; + callback attribute generatedCommandList; + callback attribute acceptedCommandList; + callback attribute eventList; + callback attribute attributeList; + ram attribute featureMap default = 0; + ram attribute clusterRevision default = 1; + } + server cluster AirQuality { ram attribute airQuality default = 0; callback attribute generatedCommandList; diff --git a/examples/all-clusters-app/all-clusters-common/all-clusters-app.zap b/examples/all-clusters-app/all-clusters-common/all-clusters-app.zap index bbdf3a2c461b57..7136a62988b61c 100644 --- a/examples/all-clusters-app/all-clusters-common/all-clusters-app.zap +++ b/examples/all-clusters-app/all-clusters-common/all-clusters-app.zap @@ -13076,6 +13076,195 @@ } ] }, + { + "name": "Refrigerator Alarm", + "code": 87, + "mfgCode": null, + "define": "REFRIGERATOR_ALARM", + "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": "Refrigerator Alarm", + "code": 87, + "mfgCode": null, + "define": "REFRIGERATOR_ALARM", + "side": "server", + "enabled": 1, + "attributes": [ + { + "name": "Mask", + "code": 0, + "mfgCode": null, + "side": "server", + "type": "AlarmMap", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "1", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "State", + "code": 2, + "mfgCode": null, + "side": "server", + "type": "AlarmMap", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0", + "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": "EventList", + "code": 65530, + "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 + } + ], + "events": [ + { + "name": "Notify", + "code": 0, + "mfgCode": null, + "side": "server", + "included": 1 + } + ] + }, { "name": "Air Quality", "code": 91, diff --git a/examples/all-clusters-app/esp32/main/CMakeLists.txt b/examples/all-clusters-app/esp32/main/CMakeLists.txt index ed62e67b6d26f7..e2311a75f51f76 100644 --- a/examples/all-clusters-app/esp32/main/CMakeLists.txt +++ b/examples/all-clusters-app/esp32/main/CMakeLists.txt @@ -71,6 +71,7 @@ set(SRC_DIRS_LIST "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/src/app/clusters/thread-network-diagnostics-server" "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/src/app/clusters/channel-server" "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/src/app/clusters/scenes-server" + "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/src/app/clusters/refrigerator-alarm-server" "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/src/app/clusters/software-diagnostics-server" "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/src/app/clusters/switch-server" "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/src/app/clusters/general-diagnostics-server" diff --git a/examples/all-clusters-app/nxp/mw320/main.cpp b/examples/all-clusters-app/nxp/mw320/main.cpp index 23675050c73052..b8b1fe85bfabdd 100644 --- a/examples/all-clusters-app/nxp/mw320/main.cpp +++ b/examples/all-clusters-app/nxp/mw320/main.cpp @@ -14,8 +14,8 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -//#include "FreeRTOS.h" -//#include "task.h" +// #include "FreeRTOS.h" +// #include "task.h" #include @@ -28,7 +28,7 @@ #include #include -//#include //==> rm from TE7.5 +// #include //==> rm from TE7.5 #include #include #include @@ -59,9 +59,9 @@ #include "app/clusters/ota-requestor/DefaultOTARequestor.h" #include "app/clusters/ota-requestor/DefaultOTARequestorDriver.h" #include "app/clusters/ota-requestor/DefaultOTARequestorStorage.h" -//#include +// #include #include "platform/nxp/mw320/OTAImageProcessorImpl.h" -//#include "app/clusters/ota-requestor/OTARequestorDriver.h" +// #include "app/clusters/ota-requestor/OTARequestorDriver.h" // for ota module test #include "mw320_ota.h" @@ -1528,7 +1528,7 @@ static void OnSwitchAttributeChangeCallback(EndpointId endpointId, AttributeId a ReadHandler * phandler = pimEngine->ActiveHandlerAt(i); if (phandler->IsType(chip::app::ReadHandler::InteractionType::Subscribe) && (phandler->IsGeneratingReports() || phandler->IsAwaitingReportResponse())) { - phandler->UnblockUrgentEventDelivery(); + phandler->ForceDirtyState(); do_sendrpt = true; break; } diff --git a/examples/chip-tool/py_matter_chip_tool_adapter/matter_chip_tool_adapter/encoder.py b/examples/chip-tool/py_matter_chip_tool_adapter/matter_chip_tool_adapter/encoder.py index f395df13674a7d..7371fb6b0fa3bb 100644 --- a/examples/chip-tool/py_matter_chip_tool_adapter/matter_chip_tool_adapter/encoder.py +++ b/examples/chip-tool/py_matter_chip_tool_adapter/matter_chip_tool_adapter/encoder.py @@ -234,10 +234,36 @@ def __get_command_name(self, request): return command_name, command_specifier def __get_arguments(self, request): + # chip-tool expects a json encoded string that contains both mandatory and optional arguments for the target command. + # + # Those arguments are either top level properties of the request object or under the 'arguments' property. + # + # Usually if an argument is used by multiple commands (e.g: 'endpoint', 'min-interval', 'commissioner-name') it is represented as + # a top level property of the request. + # Otherwise if the argument is a command specific argument, it can be retrieved as a member of the 'arguments' property. + # + # As an example, the following test step: + # + # - label: "Send Test Add Arguments Command" + # nodeId: 0x12344321 + # endpoint: 1 + # cluster: Unit Testing + # command: TestAddArguments + # identity: beta + # arguments: + # values: + # - name: arg1 + # value: 3 + # - name: arg2 + # value: 4 + # + # Will be translated to: + # destination-id": "0x12344321", "endpoint-id-ignored-for-group-commands": "1", "arg1":"3", "arg2":"17", "commissioner-name": "beta" arguments = '' arguments = self.__maybe_add_destination(arguments, request) arguments = self.__maybe_add_endpoint(arguments, request) arguments = self.__maybe_add_command_arguments(arguments, request) + arguments = self.__maybe_add_data_version(arguments, request) arguments = self.__maybe_add( arguments, request.min_interval, "min-interval") arguments = self.__maybe_add( @@ -304,6 +330,25 @@ def __maybe_add_command_arguments(self, rv, request): return rv + def __maybe_add_data_version(self, rv, request): + if request.data_version is None: + return rv + + value = '' + if type(request.data_version) is list: + for index, version in enumerate(request.data_version): + value += str(version) + if index != len(request.data_version) - 1: + value += ',' + else: + value = request.data_version + + if rv: + rv += ', ' + rv += f'"data-version":"{value}"' + + return rv + def __get_argument_name(self, request, entry): cluster_name = request.cluster command_name = request.command diff --git a/examples/common/pigweed/rpc_console/.gn b/examples/common/pigweed/rpc_console/.gn index 963ca108a40545..ead10c338ecd07 100644 --- a/examples/common/pigweed/rpc_console/.gn +++ b/examples/common/pigweed/rpc_console/.gn @@ -23,7 +23,7 @@ default_args = { pw_build_PIP_CONSTRAINTS = [ "//third_party/connectedhomeip/scripts/setup/constraints.txt" ] pw_build_PIP_REQUIREMENTS = - [ "//third_party/connectedhomeip/scripts/setup/requirements.txt" ] + [ "//third_party/connectedhomeip/scripts/setup/requirements.build.txt" ] pw_build_USE_NEW_PYTHON_BUILD = true } diff --git a/examples/common/tracing/TraceHandlers.cpp b/examples/common/tracing/TraceHandlers.cpp index 373b00cb61982c..d595580fa7619a 100644 --- a/examples/common/tracing/TraceHandlers.cpp +++ b/examples/common/tracing/TraceHandlers.cpp @@ -199,7 +199,7 @@ std::string PayloadHeaderToJson(const PayloadHeader * payloadHeader) std::string jsonBody; - uint8_t exchangeFlags = payloadHeader->GetExhangeFlags(); + uint8_t exchangeFlags = payloadHeader->GetExchangeFlags(); jsonBody += AsFirstJsonKey("exchange_flags", std::to_string(exchangeFlags)); uint16_t exchangeId = payloadHeader->GetExchangeID(); diff --git a/examples/contact-sensor-app/nxp/k32w/k32w0/BUILD.gn b/examples/contact-sensor-app/nxp/k32w/k32w0/BUILD.gn index fc64f7de9c8e66..e4c15436b3bd86 100644 --- a/examples/contact-sensor-app/nxp/k32w/k32w0/BUILD.gn +++ b/examples/contact-sensor-app/nxp/k32w/k32w0/BUILD.gn @@ -57,10 +57,6 @@ k32w0_sdk("sdk") { "${k32w0_platform_dir}/common", ] - if (chip_with_se05x == 1) { - include_dirs += [ "${chip_root}/examples/platform/nxp/se05x" ] - } - defines = [] if (is_debug) { defines += [ "BUILD_RELEASE=0" ] diff --git a/examples/darwin-framework-tool/BUILD.gn b/examples/darwin-framework-tool/BUILD.gn index b920356a29b3a3..80c3daaae8a6a6 100644 --- a/examples/darwin-framework-tool/BUILD.gn +++ b/examples/darwin-framework-tool/BUILD.gn @@ -166,6 +166,9 @@ executable("darwin-framework-tool") { "commands/common/MTRError.mm", "commands/common/MTRError_Utils.h", "commands/common/MTRLogging.h", + "commands/discover/Commands.h", + "commands/discover/DiscoverCommissionablesCommand.h", + "commands/discover/DiscoverCommissionablesCommand.mm", "commands/pairing/Commands.h", "commands/pairing/DeviceControllerDelegateBridge.mm", "commands/pairing/GetCommissionerNodeIdCommand.h", diff --git a/examples/darwin-framework-tool/commands/common/CHIPCommandBridge.h b/examples/darwin-framework-tool/commands/common/CHIPCommandBridge.h index 2280f71e141a28..3a3a6d8d64efdd 100644 --- a/examples/darwin-framework-tool/commands/common/CHIPCommandBridge.h +++ b/examples/darwin-framework-tool/commands/common/CHIPCommandBridge.h @@ -38,6 +38,10 @@ class CHIPCommandBridge : public Command { : Command(commandName) { AddArgument("commissioner-name", &mCommissionerName); + AddArgument("commissioner-nodeId", 0, UINT64_MAX, &mCommissionerNodeId, + "Sets the commisser node ID of the given " + "commissioner-name. Interactive mode will only set a single commissioner on the inital command. " + "The commissioner node ID will be persisted until a different one is specified."); AddArgument("paa-trust-store-path", &mPaaTrustStorePath, "Path to directory holding PAA certificate information. Can be absolute or relative to the current working " "directory."); @@ -134,6 +138,7 @@ class CHIPCommandBridge : public Command { std::condition_variable cvWaitingForResponse; std::mutex cvWaitingForResponseMutex; chip::Optional mCommissionerName; + chip::Optional mCommissionerNodeId; bool mWaitingForResponse { true }; static dispatch_queue_t mOTAProviderCallbackQueue; chip::Optional mPaaTrustStorePath; diff --git a/examples/darwin-framework-tool/commands/common/CHIPCommandBridge.mm b/examples/darwin-framework-tool/commands/common/CHIPCommandBridge.mm index 6c1cd92a32ed48..55f429caeca981 100644 --- a/examples/darwin-framework-tool/commands/common/CHIPCommandBridge.mm +++ b/examples/darwin-framework-tool/commands/common/CHIPCommandBridge.mm @@ -137,9 +137,13 @@ ipk = [gNocSigner getIPK]; constexpr const char * identities[] = { kIdentityAlpha, kIdentityBeta, kIdentityGamma }; + std::string commissionerName = mCommissionerName.HasValue() ? mCommissionerName.Value() : kIdentityAlpha; for (size_t i = 0; i < ArraySize(identities); ++i) { auto controllerParams = [[MTRDeviceControllerStartupParams alloc] initWithIPK:ipk fabricID:@(i + 1) nocSigner:gNocSigner]; + if (commissionerName.compare(identities[i]) == 0 && mCommissionerNodeId.HasValue()) { + controllerParams.nodeId = @(mCommissionerNodeId.Value()); + } // We're not sure whether we're creating a new fabric or using an // existing one, so just try both. auto controller = [factory createControllerOnExistingFabric:controllerParams error:&error]; diff --git a/examples/darwin-framework-tool/commands/discover/Commands.h b/examples/darwin-framework-tool/commands/discover/Commands.h new file mode 100644 index 00000000000000..d1d54eac255ddb --- /dev/null +++ b/examples/darwin-framework-tool/commands/discover/Commands.h @@ -0,0 +1,36 @@ +/* + * Copyright (c) 2023 Project CHIP Authors + * All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#pragma once + +#import + +#include "DiscoverCommissionablesCommand.h" + +void registerCommandsDiscover(Commands & commands) +{ + const char * clusterName = "Discover"; + + commands_list clusterCommands = { + make_unique(), + make_unique(), + make_unique(), + }; + + commands.Register(clusterName, clusterCommands); +} diff --git a/examples/darwin-framework-tool/commands/discover/DiscoverCommissionablesCommand.h b/examples/darwin-framework-tool/commands/discover/DiscoverCommissionablesCommand.h new file mode 100644 index 00000000000000..dc70254f32a103 --- /dev/null +++ b/examples/darwin-framework-tool/commands/discover/DiscoverCommissionablesCommand.h @@ -0,0 +1,52 @@ +/* + * Copyright (c) 2023 Project CHIP Authors + * All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#include "../common/CHIPCommandBridge.h" + +class DiscoverCommissionablesStartCommand : public CHIPCommandBridge +{ +public: + DiscoverCommissionablesStartCommand() : CHIPCommandBridge("start") {} + +protected: + /////////// CHIPCommandBridge Interface ///////// + CHIP_ERROR RunCommand() override; + chip::System::Clock::Timeout GetWaitDuration() const override { return chip::System::Clock::Seconds16(30); } +}; + +class DiscoverCommissionablesStopCommand : public CHIPCommandBridge +{ +public: + DiscoverCommissionablesStopCommand() : CHIPCommandBridge("stop") {} + +protected: + /////////// CHIPCommandBridge Interface ///////// + CHIP_ERROR RunCommand() override; + chip::System::Clock::Timeout GetWaitDuration() const override { return chip::System::Clock::Seconds16(1); } +}; + +class DiscoverCommissionablesListCommand : public CHIPCommandBridge +{ +public: + DiscoverCommissionablesListCommand() : CHIPCommandBridge("list") {} + +protected: + /////////// CHIPCommandBridge Interface ///////// + CHIP_ERROR RunCommand() override; + chip::System::Clock::Timeout GetWaitDuration() const override { return chip::System::Clock::Seconds16(1); } +}; diff --git a/examples/darwin-framework-tool/commands/discover/DiscoverCommissionablesCommand.mm b/examples/darwin-framework-tool/commands/discover/DiscoverCommissionablesCommand.mm new file mode 100644 index 00000000000000..beaf43a954aea0 --- /dev/null +++ b/examples/darwin-framework-tool/commands/discover/DiscoverCommissionablesCommand.mm @@ -0,0 +1,103 @@ +/* + * Copyright (c) 2023 Project CHIP Authors + * All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +#include "DiscoverCommissionablesCommand.h" + +NSMutableArray * gDiscoveredDevices = [[NSMutableArray alloc] init]; +auto gDispatchQueue = dispatch_queue_create("com.chip.discover", DISPATCH_QUEUE_SERIAL); + +@interface DeviceScannerDelegate : NSObject +- (void)didDiscoverCommissionable:(MTRCommissionableBrowserResult *)device; +- (void)commissionableUnavailable:(MTRCommissionableBrowserResult *)device; +@end + +@implementation DeviceScannerDelegate +- (void)didDiscoverCommissionable:(MTRCommissionableBrowserResult *)device +{ + auto serviceName = device.serviceName; + auto vendorId = device.vendorId; + auto productId = device.productId; + auto discriminator = device.discriminator; + [gDiscoveredDevices addObject:device]; + + NSLog(@"Found Device (%@) with discriminator: %@ (vendor: %@, product: %@)", serviceName, discriminator, vendorId, productId); +} + +- (void)commissionableUnavailable:(MTRCommissionableBrowserResult *)device +{ + auto serviceName = device.serviceName; + auto vendorId = device.vendorId; + auto productId = device.productId; + auto discriminator = device.discriminator; + [gDiscoveredDevices removeObjectIdenticalTo:device]; + + NSLog(@"Removed Device (%@) with discriminator: %@ (vendor: %@, product: %@)", serviceName, discriminator, vendorId, productId); +} +@end + +CHIP_ERROR DiscoverCommissionablesStartCommand::RunCommand() +{ + VerifyOrReturnError(IsInteractive(), CHIP_ERROR_INCORRECT_STATE); + + dispatch_sync(gDispatchQueue, ^{ + [gDiscoveredDevices removeAllObjects]; + }); + + auto delegate = [[DeviceScannerDelegate alloc] init]; + auto success = [CurrentCommissioner() startScan:delegate queue:gDispatchQueue]; + VerifyOrReturnError(success, CHIP_ERROR_INTERNAL); + + SetCommandExitStatus(CHIP_NO_ERROR); + return CHIP_NO_ERROR; +} + +CHIP_ERROR DiscoverCommissionablesStopCommand::RunCommand() +{ + VerifyOrReturnError(IsInteractive(), CHIP_ERROR_INCORRECT_STATE); + + auto success = [CurrentCommissioner() stopScan]; + VerifyOrReturnError(success, CHIP_ERROR_INTERNAL); + + SetCommandExitStatus(CHIP_NO_ERROR); + return CHIP_NO_ERROR; +} + +CHIP_ERROR DiscoverCommissionablesListCommand::RunCommand() +{ + VerifyOrReturnError(IsInteractive(), CHIP_ERROR_INCORRECT_STATE); + + dispatch_sync(gDispatchQueue, ^{ + auto resultsCount = [gDiscoveredDevices count]; + VerifyOrReturn(resultsCount > 0, ChipLogProgress(chipTool, "No device discovered.")); + + uint16_t index = 0; + for (id device in gDiscoveredDevices) { + auto serviceName = [device serviceName]; + auto vendorId = [device vendorId]; + auto productId = [device productId]; + auto discriminator = [device discriminator]; + + NSLog( + @"\t %u %@ - Discriminator: %@ - Vendor: %@ - Product: %@", index, serviceName, discriminator, vendorId, productId); + + index++; + } + }); + + SetCommandExitStatus(CHIP_NO_ERROR); + return CHIP_NO_ERROR; +} diff --git a/examples/darwin-framework-tool/commands/pairing/Commands.h b/examples/darwin-framework-tool/commands/pairing/Commands.h index 69eb9f39352e51..f15524833a0e31 100644 --- a/examples/darwin-framework-tool/commands/pairing/Commands.h +++ b/examples/darwin-framework-tool/commands/pairing/Commands.h @@ -55,6 +55,30 @@ class PairBleThread : public PairingCommandBridge PairBleThread() : PairingCommandBridge("ble-thread", PairingMode::Ble, PairingNetworkType::Thread) {} }; +class PairAlreadyDiscoveredByIndex : public PairingCommandBridge +{ +public: + PairAlreadyDiscoveredByIndex() : + PairingCommandBridge("by-index", PairingMode::AlreadyDiscoveredByIndex, PairingNetworkType::None) + {} +}; + +class PairAlreadyDiscoveredByIndexWithWiFi : public PairingCommandBridge +{ +public: + PairAlreadyDiscoveredByIndexWithWiFi() : + PairingCommandBridge("by-index-with-wifi", PairingMode::AlreadyDiscoveredByIndex, PairingNetworkType::WiFi) + {} +}; + +class PairAlreadyDiscoveredByIndexWithThread : public PairingCommandBridge +{ +public: + PairAlreadyDiscoveredByIndexWithThread() : + PairingCommandBridge("by-index-with-thread", PairingMode::AlreadyDiscoveredByIndex, PairingNetworkType::Thread) + {} +}; + class Unpair : public PairingCommandBridge { public: @@ -71,6 +95,7 @@ void registerCommandsPairing(Commands & commands) make_unique(), make_unique(), make_unique(), + make_unique(), make_unique(), make_unique(), make_unique(), diff --git a/examples/darwin-framework-tool/commands/pairing/PairingCommandBridge.h b/examples/darwin-framework-tool/commands/pairing/PairingCommandBridge.h index d1cdc4b6efecc5..34ad517075fb36 100644 --- a/examples/darwin-framework-tool/commands/pairing/PairingCommandBridge.h +++ b/examples/darwin-framework-tool/commands/pairing/PairingCommandBridge.h @@ -25,6 +25,7 @@ enum class PairingMode None, Code, Ble, + AlreadyDiscoveredByIndex, }; enum class PairingNetworkType @@ -67,6 +68,10 @@ class PairingCommandBridge : public CHIPCommandBridge AddArgument("setup-pin-code", 0, 134217727, &mSetupPINCode); AddArgument("discriminator", 0, 4096, &mDiscriminator); break; + case PairingMode::AlreadyDiscoveredByIndex: + AddArgument("payload", &mOnboardingPayload); + AddArgument("index", 0, UINT16_MAX, &mIndex); + break; } AddArgument("use-device-attestation-delegate", 0, 1, &mUseDeviceAttestationDelegate, @@ -82,6 +87,7 @@ class PairingCommandBridge : public CHIPCommandBridge private: void PairWithCode(NSError * __autoreleasing * error); + void PairWithIndex(NSError * __autoreleasing * error); void PairWithPayload(NSError * __autoreleasing * error); void Unpair(); void SetUpDeviceControllerDelegate(); @@ -94,6 +100,7 @@ class PairingCommandBridge : public CHIPCommandBridge chip::NodeId mNodeId; uint16_t mDiscriminator; uint32_t mSetupPINCode; + uint16_t mIndex; char * mOnboardingPayload; chip::Optional mUseDeviceAttestationDelegate; chip::Optional mDeviceAttestationFailsafeTime; diff --git a/examples/darwin-framework-tool/commands/pairing/PairingCommandBridge.mm b/examples/darwin-framework-tool/commands/pairing/PairingCommandBridge.mm index a8efcc2a44635b..316f1705e91363 100644 --- a/examples/darwin-framework-tool/commands/pairing/PairingCommandBridge.mm +++ b/examples/darwin-framework-tool/commands/pairing/PairingCommandBridge.mm @@ -28,6 +28,8 @@ using namespace ::chip; using namespace ::chip::Controller; +extern NSMutableArray * gDiscoveredDevices; + // A no-op MTRDeviceAttestationDelegate which lets us test (by default, in CI) // commissioning flows that have such a delegate. @interface NoOpAttestationDelegate : NSObject @@ -92,6 +94,9 @@ - (void)deviceAttestationCompletedForController:(MTRDeviceController *)controlle case PairingMode::Ble: PairWithCode(&error); break; + case PairingMode::AlreadyDiscoveredByIndex: + PairWithIndex(&error); + break; } if (error != nil) { @@ -108,6 +113,29 @@ - (void)deviceAttestationCompletedForController:(MTRDeviceController *)controlle [commissioner setupCommissioningSessionWithPayload:payload newNodeID:@(mNodeId) error:error]; } +void PairingCommandBridge::PairWithIndex(NSError * __autoreleasing * error) +{ + SetUpDeviceControllerDelegate(); + MTRDeviceController * commissioner = CurrentCommissioner(); + + if (mIndex >= [gDiscoveredDevices count]) { + auto errorString = [NSString stringWithFormat:@"Error retrieving discovered device at index %@", @(mIndex)]; + *error = [[NSError alloc] initWithDomain:@"PairingDomain" + code:MTRErrorCodeGeneralError + userInfo:@ { NSLocalizedDescriptionKey : NSLocalizedString(errorString, nil) }]; + return; + } + + NSString * onboardingPayload = [NSString stringWithUTF8String:mOnboardingPayload]; + auto * payload = [MTRSetupPayload setupPayloadWithOnboardingPayload:onboardingPayload error:error]; + if (payload == nil) { + return; + } + + auto discoveredDevice = (MTRCommissionableBrowserResult *) gDiscoveredDevices[mIndex]; + [commissioner setupCommissioningSessionWithDiscoveredDevice:discoveredDevice payload:payload newNodeID:@(mNodeId) error:error]; +} + void PairingCommandBridge::PairWithPayload(NSError * __autoreleasing * error) { NSString * onboardingPayload = [NSString stringWithUTF8String:mOnboardingPayload]; diff --git a/examples/darwin-framework-tool/main.mm b/examples/darwin-framework-tool/main.mm index dd191d39e441e1..51325001e59c2e 100644 --- a/examples/darwin-framework-tool/main.mm +++ b/examples/darwin-framework-tool/main.mm @@ -21,6 +21,7 @@ #import "logging/logging.h" #include "commands/common/Commands.h" +#include "commands/discover/Commands.h" #include "commands/interactive/Commands.h" #include "commands/pairing/Commands.h" #include "commands/payload/Commands.h" @@ -37,6 +38,7 @@ int main(int argc, const char * argv[]) Commands commands; registerCommandsPairing(commands); + registerCommandsDiscover(commands); registerCommandsInteractive(commands); registerCommandsPayload(commands); registerClusterOtaSoftwareUpdateProviderInteractive(commands); diff --git a/examples/lighting-app/nxp/k32w/k32w0/BUILD.gn b/examples/lighting-app/nxp/k32w/k32w0/BUILD.gn index 54721dad1a397d..2ee2e42a24259e 100644 --- a/examples/lighting-app/nxp/k32w/k32w0/BUILD.gn +++ b/examples/lighting-app/nxp/k32w/k32w0/BUILD.gn @@ -57,10 +57,6 @@ k32w0_sdk("sdk") { "${k32w0_platform_dir}/common", ] - if (chip_with_se05x == 1) { - include_dirs += [ "${chip_root}/examples/platform/nxp/se05x" ] - } - defines = [] if (is_debug) { defines += [ "BUILD_RELEASE=0" ] diff --git a/examples/lock-app/esp32/main/AppTask.cpp b/examples/lock-app/esp32/main/AppTask.cpp index 27aad563daa613..8b251a305e809c 100644 --- a/examples/lock-app/esp32/main/AppTask.cpp +++ b/examples/lock-app/esp32/main/AppTask.cpp @@ -422,6 +422,11 @@ void AppTask::ActionCompleted(BoltLockManager::Action_t aAction) sLockLED.Set(false); } + if (sAppTask.mSyncClusterToButtonAction) + { + chip::DeviceLayer::SystemLayer().ScheduleWork(UpdateClusterState, nullptr); + sAppTask.mSyncClusterToButtonAction = false; + } } void AppTask::PostLockActionRequest(int32_t aActor, BoltLockManager::Action_t aAction) diff --git a/examples/lock-app/nxp/k32w/k32w0/BUILD.gn b/examples/lock-app/nxp/k32w/k32w0/BUILD.gn index 7a18fc3eb14396..0b752583604a89 100644 --- a/examples/lock-app/nxp/k32w/k32w0/BUILD.gn +++ b/examples/lock-app/nxp/k32w/k32w0/BUILD.gn @@ -57,10 +57,6 @@ k32w0_sdk("sdk") { "${k32w0_platform_dir}/common", ] - if (chip_with_se05x == 1) { - include_dirs += [ "${chip_root}/examples/platform/nxp/se05x" ] - } - defines = [] if (is_debug) { defines += [ "BUILD_RELEASE=0" ] @@ -111,7 +107,6 @@ k32w0_executable("lock_app") { "${chip_root}/src/lib", "${chip_root}/src/platform:syscalls_stub", "${chip_root}/third_party/mbedtls:mbedtls", - "${chip_root}/third_party/simw-top-mini:se05x", "${k32w0_platform_dir}/app/support:freertos_mbedtls_utils", ] diff --git a/examples/minimal-mdns/advertiser.cpp b/examples/minimal-mdns/advertiser.cpp index 0194a3d7fb4c9a..e9cc880cae81ed 100644 --- a/examples/minimal-mdns/advertiser.cpp +++ b/examples/minimal-mdns/advertiser.cpp @@ -35,6 +35,7 @@ enum class AdvertisingMode { kCommissionableNode, kOperational, + kOperationalMultiAdmin, kCommissioner, }; @@ -100,6 +101,10 @@ bool HandleOptions(const char * aProgram, OptionSet * aOptions, int aIdentifier, { gOptions.advertisingMode = AdvertisingMode::kOperational; } + else if (strcmp(aValue, "operational-multi-admin") == 0) + { + gOptions.advertisingMode = AdvertisingMode::kOperationalMultiAdmin; + } else if (strcmp(aValue, "commissionable-node") == 0) { gOptions.advertisingMode = AdvertisingMode::kCommissionableNode; @@ -196,48 +201,50 @@ OptionDef cmdLineOptionsDef[] = { {}, }; -OptionSet cmdLineOptions = { HandleOptions, cmdLineOptionsDef, "PROGRAM OPTIONS", +OptionSet cmdLineOptions = { + HandleOptions, cmdLineOptionsDef, "PROGRAM OPTIONS", #if INET_CONFIG_ENABLE_IPV4 - " -4\n" - " --enable-ip-v4\n" - " enable listening on IPv4\n" + " -4\n" + " --enable-ip-v4\n" + " enable listening on IPv4\n" #endif - " -m \n" - " --advertising-mode \n" - " Advertise in this mode (operational or commissionable-node or commissioner).\n" - " --short-discriminator \n" - " -s \n" - " Commissioning/commissionable short discriminator.\n" - " --long-discriminator \n" - " -l \n" - " Commissioning/commissionable long discriminator.\n" - " --vendor-id \n" - " Commissioning/commissionable vendor id.\n" - " --product-id \n" - " -p \n" - " Commissioning/commissionable product id.\n" - " --commissioning-mode \n" - " Commissioning Mode (0=disabled, 1=basic, 2=enhanced).\n" - " --device-type \n" - " Device type id.\n" - " --device-name \n" - " Name of device.\n" - " --rotating-id \n" - " Rotating Id.\n" - " --pairing-instruction \n" - " Commissionable pairing instruction.\n" - " --pairing-hint \n" - " Commissionable pairing hint.\n" - " --fabric-id \n" - " -f \n" - " Operational fabric id.\n" - " --node-id \n" - " -n \n" - " Operational node id.\n" - " -t \n" - " --trace-to \n" - " trace to the given destination (supported: " SUPPORTED_COMMAND_LINE_TRACING_TARGETS ").\n" - "\n" }; + " -m \n" + " --advertising-mode \n" + " Advertise in this mode (operational, operational-multi-admin, commissionable-node or commissioner).\n" + " --short-discriminator \n" + " -s \n" + " Commissioning/commissionable short discriminator.\n" + " --long-discriminator \n" + " -l \n" + " Commissioning/commissionable long discriminator.\n" + " --vendor-id \n" + " Commissioning/commissionable vendor id.\n" + " --product-id \n" + " -p \n" + " Commissioning/commissionable product id.\n" + " --commissioning-mode \n" + " Commissioning Mode (0=disabled, 1=basic, 2=enhanced).\n" + " --device-type \n" + " Device type id.\n" + " --device-name \n" + " Name of device.\n" + " --rotating-id \n" + " Rotating Id.\n" + " --pairing-instruction \n" + " Commissionable pairing instruction.\n" + " --pairing-hint \n" + " Commissionable pairing hint.\n" + " --fabric-id \n" + " -f \n" + " Operational fabric id.\n" + " --node-id \n" + " -n \n" + " Operational node id.\n" + " -t \n" + " --trace-to \n" + " trace to the given destination (supported: " SUPPORTED_COMMAND_LINE_TRACING_TARGETS ").\n" + "\n" +}; HelpOptions helpOptions("advertiser", "Usage: advertiser [options]", "1.0"); @@ -304,6 +311,35 @@ int main(int argc, char ** args) .SetMac(chip::ByteSpan(gOptions.mac, 6)) .SetPeerId(PeerId().SetCompressedFabricId(gOptions.fabricId).SetNodeId(gOptions.nodeId))); } + else if (gOptions.advertisingMode == AdvertisingMode::kOperationalMultiAdmin) + { + err = chip::Dnssd::ServiceAdvertiser::Instance().Advertise( + chip::Dnssd::OperationalAdvertisingParameters() + .EnableIpV4(gOptions.enableIpV4) + .SetPort(CHIP_PORT) + .SetMac(chip::ByteSpan(gOptions.mac, 6)) + .SetPeerId(PeerId().SetCompressedFabricId(gOptions.fabricId).SetNodeId(gOptions.nodeId))); + + if (err == CHIP_NO_ERROR) + { + err = chip::Dnssd::ServiceAdvertiser::Instance().Advertise( + chip::Dnssd::OperationalAdvertisingParameters() + .EnableIpV4(gOptions.enableIpV4) + .SetPort(CHIP_PORT + 1) + .SetMac(chip::ByteSpan(gOptions.mac, 6)) + .SetPeerId(PeerId().SetCompressedFabricId(gOptions.fabricId + 1).SetNodeId(gOptions.nodeId + 1))); + } + + if (err == CHIP_NO_ERROR) + { + err = chip::Dnssd::ServiceAdvertiser::Instance().Advertise( + chip::Dnssd::OperationalAdvertisingParameters() + .EnableIpV4(gOptions.enableIpV4) + .SetPort(CHIP_PORT + 2) + .SetMac(chip::ByteSpan(gOptions.mac, 6)) + .SetPeerId(PeerId().SetCompressedFabricId(gOptions.fabricId + 2).SetNodeId(gOptions.nodeId + 2))); + } + } else if (gOptions.advertisingMode == AdvertisingMode::kCommissioner) { printf("Advertise Commissioner\n"); diff --git a/examples/platform/nxp/se05x/DeviceAttestationSe05xCredsExample.cpp b/examples/platform/nxp/se05x/DeviceAttestationSe05xCredsExample.cpp index 5c8b513974f866..c4231df0b129ea 100644 --- a/examples/platform/nxp/se05x/DeviceAttestationSe05xCredsExample.cpp +++ b/examples/platform/nxp/se05x/DeviceAttestationSe05xCredsExample.cpp @@ -16,20 +16,13 @@ */ #include "DeviceAttestationSe05xCredsExample.h" +#include #include #include #include #include #include -#if CHIP_CRYPTO_HSM -#include -#endif - -#ifdef ENABLE_HSM_DEVICE_ATTESTATION - -#include - /* Device attestation key ids */ #define DEV_ATTESTATION_KEY_SE05X_ID 0x7D300000 #define DEV_ATTESTATION_CERT_SE05X_ID 0x7D300001 @@ -135,7 +128,9 @@ CHIP_ERROR ExampleSe05xDACProvider::SignWithDeviceAttestationKey(const ByteSpan MutableByteSpan & out_signature_buffer) { Crypto::P256ECDSASignature signature; - Crypto::P256KeypairHSM keypair; + Crypto::P256Keypair keypair; + Crypto::P256SerializedKeypair serialized_keypair; + uint8_t magic_bytes[] = NXP_CRYPTO_KEY_MAGIC; ChipLogDetail(Crypto, "Sign using DA key from se05x"); @@ -143,9 +138,22 @@ CHIP_ERROR ExampleSe05xDACProvider::SignWithDeviceAttestationKey(const ByteSpan VerifyOrReturnError(IsSpanUsable(message_to_sign), CHIP_ERROR_INVALID_ARGUMENT); VerifyOrReturnError(out_signature_buffer.size() >= signature.Capacity(), CHIP_ERROR_BUFFER_TOO_SMALL); - keypair.SetKeyId(DEV_ATTESTATION_KEY_SE05X_ID); - keypair.provisioned_key = true; - keypair.Initialize(Crypto::ECPKeyTarget::ECDSA); + // Add public key + reference private key (ref to key inside SE) + + serialized_keypair.SetLength(Crypto::kP256_PublicKey_Length + Crypto::kP256_PrivateKey_Length); + + memset(serialized_keypair.Bytes(), 0, Crypto::kP256_PublicKey_Length); + memcpy(serialized_keypair.Bytes() + Crypto::kP256_PublicKey_Length, magic_bytes, sizeof(magic_bytes)); + *(serialized_keypair.Bytes() + Crypto::kP256_PublicKey_Length + sizeof(magic_bytes) + 0) = + (DEV_ATTESTATION_KEY_SE05X_ID & 0xFF000000) >> (8 * 3); + *(serialized_keypair.Bytes() + Crypto::kP256_PublicKey_Length + sizeof(magic_bytes) + 1) = + (DEV_ATTESTATION_KEY_SE05X_ID & 0x00FF0000) >> (8 * 2); + *(serialized_keypair.Bytes() + Crypto::kP256_PublicKey_Length + sizeof(magic_bytes) + 2) = + (DEV_ATTESTATION_KEY_SE05X_ID & 0x0000FF00) >> (8 * 1); + *(serialized_keypair.Bytes() + Crypto::kP256_PublicKey_Length + sizeof(magic_bytes) + 3) = + (DEV_ATTESTATION_KEY_SE05X_ID & 0x000000FF) >> (8 * 0); + + ReturnErrorOnFailure(keypair.Deserialize(serialized_keypair)); ReturnErrorOnFailure(keypair.ECDSA_sign_msg(message_to_sign.data(), message_to_sign.size(), signature)); @@ -164,5 +172,3 @@ DeviceAttestationCredentialsProvider * GetExampleSe05xDACProvider() } // namespace Examples } // namespace Credentials } // namespace chip - -#endif //#ifdef ENABLE_HSM_DEVICE_ATTESTATION diff --git a/examples/platform/nxp/se05x/DeviceAttestationSe05xCredsExample_v2.cpp b/examples/platform/nxp/se05x/DeviceAttestationSe05xCredsExample_v2.cpp index 4b8202cd99f86a..5592a49d17b872 100644 --- a/examples/platform/nxp/se05x/DeviceAttestationSe05xCredsExample_v2.cpp +++ b/examples/platform/nxp/se05x/DeviceAttestationSe05xCredsExample_v2.cpp @@ -14,8 +14,10 @@ * See the License for the specific language governing permissions and * limitations under the License. */ + #include "DeviceAttestationSe05xCredsExample.h" +#include #include #include #include @@ -23,17 +25,9 @@ #include #include #include -#include +#include #include -#if CHIP_CRYPTO_HSM -#include -#endif - -#ifdef ENABLE_HSM_DEVICE_ATTESTATION - -#include - /* Device attestation key ids */ #define DEV_ATTESTATION_KEY_SE05X_ID 0x7D300000 #define DEV_ATTESTATION_CERT_SE05X_ID 0x7D300001 @@ -279,5 +273,3 @@ DeviceAttestationCredentialsProvider * GetExampleSe05xDACProviderv2() } // namespace Examples } // namespace Credentials } // namespace chip - -#endif // #ifdef ENABLE_HSM_DEVICE_ATTESTATION diff --git a/examples/platform/nxp/se05x/linux/AppMain.cpp b/examples/platform/nxp/se05x/linux/AppMain.cpp index 5ae726604a4c8a..2c04b81b0ce8bb 100644 --- a/examples/platform/nxp/se05x/linux/AppMain.cpp +++ b/examples/platform/nxp/se05x/linux/AppMain.cpp @@ -77,12 +77,8 @@ #include "AppMain.h" #include "CommissionableInit.h" -#if CHIP_CRYPTO_HSM #include "DeviceAttestationSe05xCredsExample.h" -#include "se05x_t4t_utils.h" -#include -#include -#endif +#include using namespace chip; using namespace chip::ArgParser; @@ -289,95 +285,10 @@ int ChipLinuxAppInit(int argc, char * const argv[], OptionSet * customOptions) return 0; } -#ifdef ENABLE_HSM_EC_KEY - -struct CommonCaseDeviceServerInitParams_Se05x : public CommonCaseDeviceServerInitParams -{ - CHIP_ERROR InitializeStaticResourcesBeforeServerInit() - { - static chip::KvsPersistentStorageDelegate sKvsPersistenStorageDelegate; - static chip::PersistentStorageOperationalKeystoreHSM sPersistentStorageOperationalKeystore; - static chip::Credentials::PersistentStorageOpCertStore sPersistentStorageOpCertStore; - static chip::Credentials::GroupDataProviderImpl sGroupDataProvider; - static Credentials::IgnoreCertificateValidityPeriodPolicy sDefaultCertValidityPolicy; - static chip::Crypto::DefaultSessionKeystore sSessionKeystore; - -#if CHIP_CONFIG_ENABLE_SESSION_RESUMPTION - static chip::SimpleSessionResumptionStorage sSessionResumptionStorage; -#endif - static chip::app::DefaultAclStorage sAclStorage; - - // KVS-based persistent storage delegate injection - if (persistentStorageDelegate == nullptr) - { - chip::DeviceLayer::PersistedStorage::KeyValueStoreManager & kvsManager = - DeviceLayer::PersistedStorage::KeyValueStoreMgr(); - ReturnErrorOnFailure(sKvsPersistenStorageDelegate.Init(&kvsManager)); - this->persistentStorageDelegate = &sKvsPersistenStorageDelegate; - } - - // PersistentStorageDelegate "software-based" operational key access injection - if (this->operationalKeystore == nullptr) - { - // WARNING: PersistentStorageOperationalKeystore::Finish() is never called. It's fine for - // for examples and for now. - ReturnErrorOnFailure(sPersistentStorageOperationalKeystore.Init(this->persistentStorageDelegate)); - this->operationalKeystore = &sPersistentStorageOperationalKeystore; - } - - // OpCertStore can be injected but default to persistent storage default - // for simplicity of the examples. - if (this->opCertStore == nullptr) - { - // WARNING: PersistentStorageOpCertStore::Finish() is never called. It's fine for - // for examples and for now, since all storage is immediate for that impl. - ReturnErrorOnFailure(sPersistentStorageOpCertStore.Init(this->persistentStorageDelegate)); - this->opCertStore = &sPersistentStorageOpCertStore; - } - - // Session Keystore injection - this->sessionKeystore = &sSessionKeystore; - - // Group Data provider injection - sGroupDataProvider.SetStorageDelegate(this->persistentStorageDelegate); - sGroupDataProvider.SetSessionKeystore(this->sessionKeystore); - ReturnErrorOnFailure(sGroupDataProvider.Init()); - this->groupDataProvider = &sGroupDataProvider; - -#if CHIP_CONFIG_ENABLE_SESSION_RESUMPTION - ReturnErrorOnFailure(sSessionResumptionStorage.Init(this->persistentStorageDelegate)); - this->sessionResumptionStorage = &sSessionResumptionStorage; -#else - this->sessionResumptionStorage = nullptr; -#endif - - // Inject access control delegate - this->accessDelegate = Access::Examples::GetAccessControlDelegate(); - - // Inject ACL storage. (Don't initialize it.) - this->aclStorage = &sAclStorage; - - // Inject certificate validation policy compatible with non-wall-clock-time-synced - // embedded systems. - this->certificateValidityPolicy = &sDefaultCertValidityPolicy; - - return CHIP_NO_ERROR; - } -}; - -#endif - void ChipLinuxAppMainLoop(AppMainLoopImplementation * impl) { -#ifdef ENABLE_HSM_EC_KEY - static CommonCaseDeviceServerInitParams_Se05x initParams; -#else static chip::CommonCaseDeviceServerInitParams initParams; -#endif -#if CHIP_CRYPTO_HSM - VerifyOrDie(se05x_enable_contactless_interface() == 0); -#endif VerifyOrDie(initParams.InitializeStaticResourcesBeforeServerInit() == CHIP_NO_ERROR); #if defined(ENABLE_CHIP_SHELL) @@ -423,7 +334,7 @@ void ChipLinuxAppMainLoop(AppMainLoopImplementation * impl) PrintOnboardingCodes(LinuxDeviceOptions::GetInstance().payload); // Initialize device attestation config -#ifdef ENABLE_HSM_DEVICE_ATTESTATION +#if ENABLE_SE05X_DEVICE_ATTESTATION SetDeviceAttestationCredentialsProvider(Examples::GetExampleSe05xDACProvider()); #else SetDeviceAttestationCredentialsProvider(LinuxDeviceOptions::GetInstance().dacProvider); diff --git a/examples/platform/nxp/se05x/linux/BUILD.gn b/examples/platform/nxp/se05x/linux/BUILD.gn index 52ce3d417617e5..2a93a4bf085a3e 100644 --- a/examples/platform/nxp/se05x/linux/BUILD.gn +++ b/examples/platform/nxp/se05x/linux/BUILD.gn @@ -59,6 +59,7 @@ source_set("app-main") { include_dirs = [ "${chip_root}/examples/platform/linux", "${chip_root}/examples/platform/nxp/se05x", + "${chip_root}/src/platform/nxp/crypto/se05x", ] defines = [] diff --git a/examples/platform/silabs/SiWx917/SiWx917/rsi_if.c b/examples/platform/silabs/SiWx917/SiWx917/rsi_if.c index d05a0d132a5d8e..9dc57d81636733 100644 --- a/examples/platform/silabs/SiWx917/SiWx917/rsi_if.c +++ b/examples/platform/silabs/SiWx917/SiWx917/rsi_if.c @@ -44,6 +44,7 @@ #include "rsi_wlan_config.h" #include "dhcp_client.h" +#include "lwip/nd6.h" #include "wfx_rsi.h" /* Rsi driver Task will use as its stack */ @@ -558,7 +559,16 @@ void wfx_rsi_task(void * arg) hasNotifiedIPV4 = false; } #endif /* CHIP_DEVICE_CONFIG_ENABLE_IPV4 */ - /* Checks if the assigned IPv6 address is preferred by evaluating + /* + * Checks if the IPv6 event has been notified, if not invoke the nd6_tmr, + * which starts the duplicate address detectation. + */ + if (!hasNotifiedIPV6) + { + nd6_tmr(); + } + /* + * Checks if the assigned IPv6 address is preferred by evaluating * the first block of IPv6 address ( block 0) */ if ((ip6_addr_ispreferred(netif_ip6_addr_state(sta_netif, 0))) && !hasNotifiedIPV6) diff --git a/examples/platform/silabs/efr32/rs911x/rsi_if.c b/examples/platform/silabs/efr32/rs911x/rsi_if.c index 86238374ef175f..f29cf010a79e73 100644 --- a/examples/platform/silabs/efr32/rs911x/rsi_if.c +++ b/examples/platform/silabs/efr32/rs911x/rsi_if.c @@ -50,6 +50,7 @@ #include "rsi_wlan_config.h" #include "dhcp_client.h" +#include "lwip/nd6.h" #include "wfx_host_events.h" #include "wfx_rsi.h" @@ -624,7 +625,16 @@ void wfx_rsi_task(void * arg) hasNotifiedIPV4 = false; } #endif /* CHIP_DEVICE_CONFIG_ENABLE_IPV4 */ - /* Checks if the assigned IPv6 address is preferred by evaluating + /* + * Checks if the IPv6 event has been notified, if not invoke the nd6_tmr, + * which starts the duplicate address detectation. + */ + if (!hasNotifiedIPV6) + { + nd6_tmr(); + } + /* + * Checks if the assigned IPv6 address is preferred by evaluating * the first block of IPv6 address ( block 0) */ if ((ip6_addr_ispreferred(netif_ip6_addr_state(sta_netif, 0))) && !hasNotifiedIPV6) diff --git a/examples/shell/nxp/k32w/k32w0/BUILD.gn b/examples/shell/nxp/k32w/k32w0/BUILD.gn index 8b062831685aea..b19d08fe44e325 100644 --- a/examples/shell/nxp/k32w/k32w0/BUILD.gn +++ b/examples/shell/nxp/k32w/k32w0/BUILD.gn @@ -69,7 +69,6 @@ k32w0_executable("shell_app") { "${chip_root}/examples/shell/shell_common:shell_common", "${chip_root}/src/platform:syscalls_stub", "${chip_root}/third_party/mbedtls:mbedtls", - "${chip_root}/third_party/simw-top-mini:se05x", "${k32w0_platform_dir}/app/support:freertos_mbedtls_utils", ] diff --git a/examples/thermostat/nxp/linux-se05x/BUILD.gn b/examples/thermostat/nxp/linux-se05x/BUILD.gn index 1f5851a30caeca..69bdb0358106d3 100644 --- a/examples/thermostat/nxp/linux-se05x/BUILD.gn +++ b/examples/thermostat/nxp/linux-se05x/BUILD.gn @@ -14,14 +14,18 @@ import("//build_overrides/build.gni") import("//build_overrides/chip.gni") +import("${chip_root}/src/platform/nxp/crypto/nxp_crypto.gni") -executable("thermostat-se05x-app") { - sources = [ "${chip_root}/examples/thermostat/linux/main.cpp" ] - +executable("thermostat-app") { + sources = [ + "../../linux/include/low-power/LowPowerManager.cpp", + "../../linux/include/low-power/LowPowerManager.h", + "../../linux/main.cpp", + ] include_dirs = [ "${chip_root}/examples/platform/linux" ] deps = [ - "${chip_root}/examples/platform/nxp/se05x/linux:app-main", + "${chip_root}/examples/platform/nxp/${nxp_crypto_impl}/linux:app-main", "${chip_root}/examples/thermostat/thermostat-common", "${chip_root}/src/lib", ] @@ -29,4 +33,16 @@ executable("thermostat-se05x-app") { cflags = [ "-Wconversion" ] output_dir = root_out_dir + + deps += [ + "${chip_root}/src/platform/nxp/crypto/${nxp_crypto_impl}:nxp_crypto_lib", + ] +} + +group("linux") { + deps = [ ":thermostat-app" ] +} + +group("default") { + deps = [ ":linux" ] } diff --git a/examples/thermostat/nxp/linux-se05x/args.gni b/examples/thermostat/nxp/linux-se05x/args.gni index c9ccb79255d82b..98b7b40c1038b4 100644 --- a/examples/thermostat/nxp/linux-se05x/args.gni +++ b/examples/thermostat/nxp/linux-se05x/args.gni @@ -13,5 +13,8 @@ # limitations under the License. import("//build_overrides/chip.gni") + import("${chip_root}/config/standalone/args.gni") -chip_with_se05x = 1 + +# Include to define nxp_crypto_impl +import("${chip_root}/src/platform/nxp/crypto/se05x/args.gni") diff --git a/examples/tv-casting-app/darwin/MatterTvCastingBridge/chip_xcode_build_connector.sh b/examples/tv-casting-app/darwin/MatterTvCastingBridge/chip_xcode_build_connector.sh index 3d0f82ed0d2e39..ed8d6af434f89e 100755 --- a/examples/tv-casting-app/darwin/MatterTvCastingBridge/chip_xcode_build_connector.sh +++ b/examples/tv-casting-app/darwin/MatterTvCastingBridge/chip_xcode_build_connector.sh @@ -91,6 +91,8 @@ done target_cflags+=',"-flto"' } +target_cflags+=',"-fno-c++-static-destructors"' + declare -a args=( 'default_configs_cosmetic=[]' # suppress colorization 'chip_crypto="mbedtls"' diff --git a/scripts/py_matter_idl/matter_idl/generators/types.py b/scripts/py_matter_idl/matter_idl/generators/types.py index 393c444ae46060..dd9ed047584012 100644 --- a/scripts/py_matter_idl/matter_idl/generators/types.py +++ b/scripts/py_matter_idl/matter_idl/generators/types.py @@ -412,3 +412,29 @@ def ParseDataType(data_type: DataType, lookup: TypeLookupContext) -> Union[Basic "Data type %s is NOT known, but treating it as a generic IDL type." % data_type) return result + + +def IsSignedDataType(data_type: DataType) -> bool: + """ + Returns if the data type is a signed type. + Returns if the data type is a signed data type of False if the data type can not be found. + """ + lowercase_name = data_type.name.lower() + sized_type = __CHIP_SIZED_TYPES__.get(lowercase_name, None) + if sized_type is None: + return False + + return sized_type.is_signed + + +def GetDataTypeSizeInBits(data_type: DataType) -> int: + """ + Returns the size in bits for a given data type or None if the data type can not be found. + """ + + lowercase_name = data_type.name.lower() + sized_type = __CHIP_SIZED_TYPES__.get(lowercase_name, None) + if sized_type is None: + return None + + return sized_type.power_of_two_bits diff --git a/scripts/py_matter_idl/matter_idl/matter_idl_types.py b/scripts/py_matter_idl/matter_idl/matter_idl_types.py index 9e3b4beb53ed79..eb86e3ec4b99fc 100644 --- a/scripts/py_matter_idl/matter_idl/matter_idl_types.py +++ b/scripts/py_matter_idl/matter_idl/matter_idl_types.py @@ -99,8 +99,13 @@ class DataType: name: str # Applies for strings (char or binary) + min_length: Optional[int] = None max_length: Optional[int] = None + # Applies for numbers + min_value: Optional[int] = None + max_value: Optional[int] = None + @dataclass class Field: diff --git a/scripts/py_matter_idl/matter_idl/test_xml_parser.py b/scripts/py_matter_idl/matter_idl/test_xml_parser.py index 7828c4219694fd..d8c7bb0a6c5dc1 100755 --- a/scripts/py_matter_idl/matter_idl/test_xml_parser.py +++ b/scripts/py_matter_idl/matter_idl/test_xml_parser.py @@ -59,6 +59,9 @@ def testCluster(self): 0x1234 Test + SomeCharStringAttribute + SomeIntAttribute @@ -93,7 +96,17 @@ def testCluster(self): description="Test", attributes=[ Attribute(definition=Field( - data_type=DataType(name='INT32U'), + data_type=DataType( + name='CHAR_STRING', min_length=2, max_length=10), + code=10, + name='SomeCharStringAttribute', + qualities=FieldQuality.NULLABLE), + qualities=AttributeQuality.READABLE, + readacl=AccessPrivilege.VIEW, writeacl=AccessPrivilege.OPERATE), + + Attribute(definition=Field( + data_type=DataType( + name='INT32U', min_value=0, max_value=2), code=11, name='SomeIntAttribute', qualities=FieldQuality.NULLABLE), @@ -101,7 +114,8 @@ def testCluster(self): readacl=AccessPrivilege.VIEW, writeacl=AccessPrivilege.OPERATE), Attribute(definition=Field( - data_type=DataType(name='INT8U'), + data_type=DataType( + name='INT8U', min_value=0, max_value=10), code=22, name='AttributeWithAccess', qualities=FieldQuality.OPTIONAL), qualities=AttributeQuality.READABLE | AttributeQuality.WRITABLE, @@ -214,7 +228,10 @@ def testFabricScopedAndSensitive(self): name='Field3', qualities=FieldQuality.FABRIC_SENSITIVE), Field(data_type=DataType(name='int32u', - max_length=None), + min_length=None, + max_length=None, + min_value=None, + max_value=None), code=10, name='Field10')], qualities=StructQuality.FABRIC_SCOPED)], @@ -369,7 +386,7 @@ def testSkipsNotProcessedFields(self): Attribute( definition=Field( data_type=DataType( - name='Type'), + name='Type', min_value=0, max_value=9), code=0, name='Type', ), diff --git a/scripts/py_matter_idl/matter_idl/zapxml/handlers/parsing.py b/scripts/py_matter_idl/matter_idl/zapxml/handlers/parsing.py index 09243a627fea5e..c6f057b992f611 100644 --- a/scripts/py_matter_idl/matter_idl/zapxml/handlers/parsing.py +++ b/scripts/py_matter_idl/matter_idl/zapxml/handlers/parsing.py @@ -12,16 +12,23 @@ # See the License for the specific language governing permissions and # limitations under the License. +from matter_idl.generators.types import GetDataTypeSizeInBits, IsSignedDataType from matter_idl.matter_idl_types import AccessPrivilege, Attribute, AttributeQuality, DataType, Field, FieldQuality -def ParseInt(value: str) -> int: - """Convert a string that is a known integer into an actual number. +def ParseInt(value: str, data_type: DataType = None) -> int: + """ + Convert a string that is a known integer into an actual number. - Supports decimal or hex values prefixed with '0x' + Supports decimal or hex values prefixed with '0x' """ if value.startswith('0x'): - return int(value[2:], 16) + value = int(value[2:], 16) + if data_type and IsSignedDataType(data_type): + bits = GetDataTypeSizeInBits(data_type) + if value & (1 << (bits - 1)): + value -= 1 << bits + return value else: return int(value) @@ -60,9 +67,18 @@ def AttrsToAttribute(attrs) -> Attribute: else: data_type = DataType(name=attrs['type']) + if 'minLength' in attrs: + data_type.min_length = ParseInt(attrs['minLength']) + if 'length' in attrs: data_type.max_length = ParseInt(attrs['length']) + if 'min' in attrs: + data_type.min_value = ParseInt(attrs['min'], data_type) + + if 'max' in attrs: + data_type.max_value = ParseInt(attrs['max'], data_type) + field = Field( data_type=data_type, code=ParseInt(attrs['code']), diff --git a/scripts/py_matter_yamltests/matter_yamltests/constraints.py b/scripts/py_matter_yamltests/matter_yamltests/constraints.py index 406287dd497c60..09b0514e46b675 100644 --- a/scripts/py_matter_yamltests/matter_yamltests/constraints.py +++ b/scripts/py_matter_yamltests/matter_yamltests/constraints.py @@ -535,7 +535,8 @@ def _is_double(self, value): class _ConstraintMinLength(BaseConstraint): def __init__(self, context, min_length): - super().__init__(context, types=[str, bytes, list]) + super().__init__(context, types=[ + str, bytes, list], is_null_allowed=True) self._min_length = min_length def check_response(self, value, value_type_name) -> bool: @@ -547,7 +548,8 @@ def get_reason(self, value, value_type_name) -> str: class _ConstraintMaxLength(BaseConstraint): def __init__(self, context, max_length): - super().__init__(context, types=[str, bytes, list]) + super().__init__(context, types=[ + str, bytes, list], is_null_allowed=True) self._max_length = max_length def check_response(self, value, value_type_name) -> bool: diff --git a/scripts/py_matter_yamltests/matter_yamltests/parser.py b/scripts/py_matter_yamltests/matter_yamltests/parser.py index 32f54734d83af5..f7b5de016fc9cd 100644 --- a/scripts/py_matter_yamltests/matter_yamltests/parser.py +++ b/scripts/py_matter_yamltests/matter_yamltests/parser.py @@ -201,6 +201,8 @@ def __init__(self, test: dict, config: dict, definitions: SpecDefinitions, pics_ self.max_interval = _value_or_none(test, 'maxInterval') self.timed_interaction_timeout_ms = _value_or_none( test, 'timedInteractionTimeoutMs') + self.data_version = _value_or_none( + test, 'dataVersion') self.busy_wait_ms = _value_or_none(test, 'busyWaitMs') self.wait_for = _value_or_none(test, 'wait') self.event_number = _value_or_none(test, 'eventNumber') @@ -247,7 +249,7 @@ def __init__(self, test: dict, config: dict, definitions: SpecDefinitions, pics_ def _update_mappings(self, test: dict, definitions: SpecDefinitions): cluster_name = self.cluster - if definitions is None or not definitions.has_cluster_by_name(cluster_name) or cluster_name == ANY_COMMANDS_CLUSTER_NAME or self.command in ANY_COMMANDS_LIST: + if definitions is None or (not definitions.has_cluster_by_name(cluster_name) and cluster_name != ANY_COMMANDS_CLUSTER_NAME): self.argument_mapping = None self.response_mapping = None self.response_mapping_name = None @@ -297,6 +299,81 @@ def _update_mappings(self, test: dict, definitions: SpecDefinitions): argument_mapping = event_mapping response_mapping = event_mapping response_mapping_name = event.name + elif cluster_name == ANY_COMMANDS_CLUSTER_NAME or self.command in ANY_COMMANDS_LIST: + # When the cluster is ANY_COMMANDS_CLUSTER_NAME the test step does not contain the direct mapping + # for the response in the cluster/command/attribute/event fields. + # + # When the command is part of ANY_COMMANDS_LIST the test step does not contain the direct mapping + # for the response in the command/attribute/event fields. + # + # NOTE: The logic for this paragraph has not yet be implemented. + # In some cases the response type can be inferred from the argument fields, if for example the command + # is a ReadById targetting a specific ClusterId/AttributeId that exists in the definitions. + # + # For the other cases, the response can NOT be inferred directly from the argumment fields, if for exammple + # the command is a ReadById using a wildcard in one of its fields. For this type of case, the test writer + # can add additional specifiers in the expected response type to help determine the response mapping. + + mapping_names = [] + + for response in self.responses_with_placeholders: + for value in response.get('values'): + if 'constraints' not in value: + continue + + mapping_name = None + cluster_name = self.cluster if self.cluster != ANY_COMMANDS_CLUSTER_NAME else response.get( + 'cluster') + + if cluster_name is not None: + attribute_name = response.get('attribute') + event_name = response.get('event') + command_name = response.get('command') + + if attribute_name: + attribute = definitions.get_attribute_by_name( + cluster_name, attribute_name) + + if not attribute: + targets = definitions.get_attribute_names( + cluster_name) + test['response'] = ['...', response, '...'] + raise TestStepAttributeKeyError( + response, attribute_name, targets) + + mapping_name = attribute.definition.data_type.name + elif event_name: + event = definitions.get_event_by_name( + cluster_name, event_name) + + if not event: + targets = definitions.get_event_names( + cluster_name) + test['response'] = ['...', response, '...'] + raise TestStepEventKeyError( + response, attribute_name, targets) + + mapping_name = event.name + elif command_name: + command = definitions.get_command_by_name( + cluster_name, command_name) + + if not command: + targets = definitions.get_command_names( + cluster_name) + test['response'] = ['...', response, '...'] + raise TestStepCommandKeyError( + response, command_name, targets) + + mapping_name = command.output_param + + mapping_names.append(mapping_name) + + # TODO: For now only the response_mapping_name is inferred, it allows to use the type constraint + # on the responses. + argument_mapping = None + response_mapping = None + response_mapping_name = mapping_names else: command_name = self.command command = definitions.get_command_by_name( @@ -337,7 +414,8 @@ def _convert_single_value_to_values(self, container): # members of the 'values' array which is what is used for other tests. value = {} - known_keys_to_copy = ['value', 'constraints', 'saveAs'] + known_keys_to_copy = ['value', 'constraints', + 'saveAs', 'saveDataVersionAs'] known_keys_to_allow = ['error', 'clusterError'] for key, item in list(container.items()): @@ -398,6 +476,8 @@ def _update_with_definition(self, container: dict, mapping_type): item_value, mapping) elif key == 'saveAs' and type(item_value) is str and item_value not in self._parsing_config_variable_storage: self._parsing_config_variable_storage[item_value] = None + elif key == 'saveDataVersionAs' and type(item_value) is str and item_value not in self._parsing_config_variable_storage: + self._parsing_config_variable_storage[item_value] = None elif key == 'constraints': for constraint, constraint_value in item_value.items(): # Only apply update_value_with_definition to constraints that have a value that depends on @@ -488,6 +568,8 @@ def __init__(self, test: _TestStepWithPlaceholders, step_index: int, runtime_con if test.is_pics_enabled: self._update_placeholder_values(self.arguments) self._update_placeholder_values(self.responses) + self._test.data_version = self._config_variable_substitution( + self._test.data_version) self._test.node_id = self._config_variable_substitution( self._test.node_id) self._test.run_if = self._config_variable_substitution( @@ -579,6 +661,10 @@ def max_interval(self): def timed_interaction_timeout_ms(self): return self._test.timed_interaction_timeout_ms + @property + def data_version(self): + return self._test.data_version + @property def busy_wait_ms(self): return self._test.busy_wait_ms @@ -621,11 +707,16 @@ def post_process_response(self, received_responses): expected_response, received_response, result) self._response_cluster_error_validation( expected_response, received_response, result) + self._response_values_source_validation( + expected_response, received_response, result) self._response_values_validation( expected_response, received_response, result) self._response_constraints_validation( expected_response, received_response, result) - self._maybe_save_as(expected_response, received_response, result) + self._maybe_save_as('saveAs', 'value', + expected_response, received_response, result) + self._maybe_save_as('saveDataVersionAs', 'dataVersion', + expected_response, received_response, result) # An empty response array in a test step (responses: []) implies that the test step does expect a response # but without any associated value. @@ -750,6 +841,20 @@ def _response_cluster_error_validation(self, expected_response, received_respons # Nothing is logged here to not be redundant with the generic error checking code. pass + def _response_values_source_validation(self, expected_response, received_response, result): + check_type = PostProcessCheckType.RESPONSE_VALIDATION + error_value_wrong_source = 'The test expects a value from {source_name} "{expected}" but it received a value from {source_name} "{received}".' + + sources = ['endpoint', 'cluster', 'attribute'] + for source_name in sources: + expected = expected_response.get(source_name) + received = received_response.get(source_name) + success = expected is None or received is None or expected == received + + if not success: + result.error(check_type, error_value_wrong_source.format( + source_name=source_name, expected=expected, received=received)) + def _response_values_validation(self, expected_response, received_response, result): check_type = PostProcessCheckType.RESPONSE_VALIDATION error_success = 'The test expectation "{name} == {value}" is true' @@ -816,7 +921,9 @@ def _response_constraints_validation(self, expected_response, received_response, continue received_value = received_response.get('value') - if not self.is_attribute and not self.is_event: + if self.command in ANY_COMMANDS_LIST: + response_type_name = response_type_name.pop(0) + elif not self.is_attribute and not self.is_event: expected_name = value.get('name') if received_value is None or expected_name not in received_value: received_value = None @@ -843,17 +950,17 @@ def _response_constraints_validation(self, expected_response, received_response, e.update_context(expected_response, self.step_index) result.error(check_type, error_failure, e) - def _maybe_save_as(self, expected_response, received_response, result): + def _maybe_save_as(self, key: str, default_target: str, expected_response, received_response, result): check_type = PostProcessCheckType.SAVE_AS_VARIABLE error_success = 'The test save the value "{value}" as {name}.' error_name_does_not_exist = 'The test expects a value named "{name}" but it does not exists in the response."' for value in expected_response['values']: - if 'saveAs' not in value: + if key not in value: continue - received_value = received_response.get('value') - if not self.is_attribute and not self.is_event: + received_value = received_response.get(default_target) + if not self.is_attribute and not self.is_event and not (self.command in ANY_COMMANDS_LIST): expected_name = value.get('name') if received_value is None or expected_name not in received_value: result.error(check_type, error_name_does_not_exist.format( @@ -863,7 +970,7 @@ def _maybe_save_as(self, expected_response, received_response, result): received_value = received_value.get( expected_name) if received_value else None - save_as = value.get('saveAs') + save_as = value.get(key) self._runtime_config_variable_storage[save_as] = received_value result.success(check_type, error_success.format( value=received_value, name=save_as)) diff --git a/scripts/py_matter_yamltests/matter_yamltests/yaml_loader.py b/scripts/py_matter_yamltests/matter_yamltests/yaml_loader.py index a8cf54172b0593..f806127c96f7d1 100644 --- a/scripts/py_matter_yamltests/matter_yamltests/yaml_loader.py +++ b/scripts/py_matter_yamltests/matter_yamltests/yaml_loader.py @@ -105,6 +105,7 @@ def __check_test_step(self, content): 'minInterval': int, 'maxInterval': int, 'timedInteractionTimeoutMs': int, + 'dataVersion': (list, int, str), # Can be a variable 'busyWaitMs': int, 'wait': str, } @@ -166,7 +167,8 @@ def __check_test_step_response_value(self, content, allow_name_key=False): 'error': str, 'clusterError': int, 'constraints': dict, - 'saveAs': str + 'saveAs': str, + 'saveDataVersionAs': str, } if allow_name_key: diff --git a/scripts/setup/bootstrap.sh b/scripts/setup/bootstrap.sh index 3d0a1ad7e3d2c1..af00b719fcfd5d 100644 --- a/scripts/setup/bootstrap.sh +++ b/scripts/setup/bootstrap.sh @@ -14,6 +14,38 @@ # limitations under the License. # +_install_additional_pip_requirements() { + _SETUP_PLATFORM=$1 + shift + + # figure out additional pip install items + while [[ $# -gt 0 ]]; do + case $1 in + -p | --platform) + _SETUP_PLATFORM=$2 + shift # argument + shift # value + ;; + *) + shift + ;; + esac + done + + if ! [ -z "$_SETUP_PLATFORM" ]; then + IFS="," read -r -a _PLATFORMS <<<"$_SETUP_PLATFORM" + for platform in "${_PLATFORMS[@]}"; do + # Allow none as an alias of nothing extra installed (like -p none) + if [ "$platform" != "none" ]; then + echo "Installing pip requirements for $platform..." + pip install -q \ + -r "$_CHIP_ROOT/scripts/setup/requirements.$platform.txt" \ + -c "$_CHIP_ROOT/scripts/setup/constraints.txt" + fi + done + fi +} + _bootstrap_or_activate() { if [ -n "$BASH" ]; then local _BOOTSTRAP_PATH="${BASH_SOURCE[0]}" @@ -24,7 +56,7 @@ _bootstrap_or_activate() { local _BOOTSTRAP_NAME="${_BOOTSTRAP_PATH##*/}" local _BOOTSTRAP_DIR="${_BOOTSTRAP_PATH%/*}" # Strip off the 'scripts[/setup]' directory, leaving the root of the repo. - local _CHIP_ROOT="$(cd "${_BOOTSTRAP_DIR%/setup}/.." && pwd)" + _CHIP_ROOT="$(cd "${_BOOTSTRAP_DIR%/setup}/.." && pwd)" local _CONFIG_FILE="scripts/setup/environment.json" @@ -91,21 +123,42 @@ EOF --config-file "$_CHIP_ROOT/$_CONFIG_FILE" \ --virtualenv-gn-out-dir "$_PW_ACTUAL_ENVIRONMENT_ROOT/gn_out" pw_finalize bootstrap "$_SETUP_SH" + _ACTION_TAKEN="bootstrap" else pw_activate pw_finalize activate "$_SETUP_SH" + _ACTION_TAKEN="activate" fi } +# remember PW_ENVIRONMENT_ROOT so that things like another +# bootstrap or run_in_build_env.sh can be executed in a build env +_ORIGINAL_PW_ENVIRONMENT_ROOT="$PW_ENVIRONMENT_ROOT" + _bootstrap_or_activate "$0" + +if [ "$_ACTION_TAKEN" = "bootstrap" ]; then + # By default, install all extra pip dependencies even if slow. -p/--platform + # arguments may override this default. + _install_additional_pip_requirements "all" "$@" +else + _install_additional_pip_requirements "none" "$@" +fi + unset -f _bootstrap_or_activate +unset -f _install_additional_pip_requirements pw_cleanup +unset _ACTION_TAKEN +unset _CHIP_ROOT unset PW_CIPD_INSTALL_DIR -unset CIPD_CACHE_DIR unset _PW_BANNER_FUNC unset _PW_TEXT unset PW_DOCTOR_SKIP_CIPD_CHECKS unset -f _chip_bootstrap_banner + +if ! [ -z "$_ORIGINAL_PW_ENVIRONMENT_ROOT" ]; then + export PW_ENVIRONMENT_ROOT="$_ORIGINAL_PW_ENVIRONMENT_ROOT" +fi diff --git a/scripts/setup/constraints.txt b/scripts/setup/constraints.txt index 33cb08901a93e4..1fa12ca4a45c83 100644 --- a/scripts/setup/constraints.txt +++ b/scripts/setup/constraints.txt @@ -2,7 +2,7 @@ # This file is autogenerated by pip-compile with Python 3.10 # by the following command: # -# pip-compile --output-file=constraints.txt --resolver=backtracking --strip-extras requirements.txt +# pip-compile --output-file=constraints.txt --resolver=backtracking --strip-extras requirements.all.txt # anytree==2.8.0 # via -r requirements.txt diff --git a/scripts/setup/environment.json b/scripts/setup/environment.json index ebe77d9db6dbc8..7ded85c3b43b0a 100644 --- a/scripts/setup/environment.json +++ b/scripts/setup/environment.json @@ -8,7 +8,7 @@ "virtualenv": { "gn_root": ".", "gn_targets": [":python_packages.install"], - "requirements": ["scripts/setup/requirements.txt"], + "requirements": ["scripts/setup/requirements.build.txt"], "constraints": ["scripts/setup/constraints.txt"], "gn_args": ["chip_crypto=\"boringssl\""] }, diff --git a/scripts/setup/environment_no_cipd.json b/scripts/setup/environment_no_cipd.json index b2a9075fc56fed..014a7cfaa09dcb 100644 --- a/scripts/setup/environment_no_cipd.json +++ b/scripts/setup/environment_no_cipd.json @@ -2,7 +2,7 @@ "virtualenv": { "gn_root": ".", "gn_targets": [":python_packages.install"], - "requirements": ["scripts/setup/requirements.txt"], + "requirements": ["scripts/setup/requirements.build.txt"], "constraints": ["scripts/setup/constraints.txt"], "gn_args": ["chip_crypto=\"boringssl\""] }, diff --git a/scripts/setup/requirements.txt b/scripts/setup/requirements.all.txt similarity index 68% rename from scripts/setup/requirements.txt rename to scripts/setup/requirements.all.txt index 2a5c57c1eef574..eca54173203d46 100644 --- a/scripts/setup/requirements.txt +++ b/scripts/setup/requirements.all.txt @@ -8,26 +8,16 @@ virtualenv -c constraints.esp32.txt -r requirements.esp32.txt -# mbed-os -r requirements.mbed.txt - -# bouffalolab -r requirements.bouffalolab.txt - -# openiotsdk -r requirements.openiotsdk.txt - -# Infineon -r requirements.infineon.txt - -# TI -r requirements.ti.txt - -# Telink -r requirements.telink.txt - -# cirque tests -requests>=2.24.0 +-r requirements.zephyr.txt +-r requirements.cirque.txt +-r requirements.memory.txt +-r requirements.yaml_tests.txt # device controller wheel package wheel; sys_platform == 'linux' @@ -40,17 +30,6 @@ pyobjc-framework-corebluetooth; sys_platform == 'darwin' portpicker mobly -# zephyr -west>=0.12.0 -intelhex -cbor -cbor2 -jsonschema - -# happy tests -lockfile -psutil >= 5.7.3 - # pigweed ipython appnope @@ -63,13 +42,6 @@ mypy-protobuf==3.2.0 protobuf==3.20.1 types-protobuf==3.19.22 -# scripts/tools/memory -anytree -cxxfilt -ghapi -pandas ; platform_machine != 'aarch64' and platform_machine != 'arm64' -tabulate - cryptography # python unit tests @@ -78,6 +50,3 @@ colorama # update tornado for pw_watch tornado -# YAML test harness -diskcache -websockets diff --git a/scripts/setup/requirements.cirque.txt b/scripts/setup/requirements.cirque.txt new file mode 100644 index 00000000000000..f1e8ee5f9418ce --- /dev/null +++ b/scripts/setup/requirements.cirque.txt @@ -0,0 +1 @@ +requests>=2.24.0 diff --git a/scripts/setup/requirements.memory.txt b/scripts/setup/requirements.memory.txt new file mode 100644 index 00000000000000..3aeee8b36eadb7 --- /dev/null +++ b/scripts/setup/requirements.memory.txt @@ -0,0 +1,6 @@ +# scripts/tools/memory +anytree +cxxfilt +ghapi +pandas ; platform_machine != 'aarch64' and platform_machine != 'arm64' +tabulate diff --git a/scripts/setup/requirements.yaml_tests.txt b/scripts/setup/requirements.yaml_tests.txt new file mode 100644 index 00000000000000..7fc0c5f653c194 --- /dev/null +++ b/scripts/setup/requirements.yaml_tests.txt @@ -0,0 +1,2 @@ +diskcache +websockets diff --git a/scripts/setup/requirements.zephyr.txt b/scripts/setup/requirements.zephyr.txt new file mode 100644 index 00000000000000..5c871eef856d19 --- /dev/null +++ b/scripts/setup/requirements.zephyr.txt @@ -0,0 +1,5 @@ +west>=0.12.0 +intelhex +cbor +cbor2 +jsonschema diff --git a/scripts/tools/telink/readme.md b/scripts/tools/telink/readme.md index 4bb4a8a32a9d1c..1ee492c2ffc695 100644 --- a/scripts/tools/telink/readme.md +++ b/scripts/tools/telink/readme.md @@ -35,7 +35,8 @@ tool. ```shell cd path/to/connectedhomeip/scripts/tools/telink/ -python3 -m pip install -r requirements.txt +python3 -m pip install -r requirements.build.txt +python3 -m pip install -r requirements.telink.txt ``` ## Usage diff --git a/scripts/tools/telink/requirements.txt b/scripts/tools/telink/requirements.txt index 5c7590c60309f3..e6330170ff8cda 100644 --- a/scripts/tools/telink/requirements.txt +++ b/scripts/tools/telink/requirements.txt @@ -1,4 +1,4 @@ -cryptography==39.0.1 +cryptography==41.0.0 cffi==1.15.0 future==0.18.3 pycparser==2.21 diff --git a/src/app/ReadHandler.cpp b/src/app/ReadHandler.cpp index 1c2511b497b0f2..4a92fcfac91f9c 100644 --- a/src/app/ReadHandler.cpp +++ b/src/app/ReadHandler.cpp @@ -124,10 +124,10 @@ ReadHandler::~ReadHandler() if (IsType(InteractionType::Subscribe)) { InteractionModelEngine::GetInstance()->GetExchangeManager()->GetSessionManager()->SystemLayer()->CancelTimer( - OnUnblockHoldReportCallback, this); + MinIntervalExpiredCallback, this); InteractionModelEngine::GetInstance()->GetExchangeManager()->GetSessionManager()->SystemLayer()->CancelTimer( - OnRefreshSubscribeTimerSyncCallback, this); + MaxIntervalExpiredCallback, this); } if (IsAwaitingReportResponse()) @@ -248,7 +248,7 @@ CHIP_ERROR ReadHandler::OnStatusResponse(Messaging::ExchangeContext * apExchange CHIP_ERROR ReadHandler::SendStatusReport(Protocols::InteractionModel::Status aStatus) { - VerifyOrReturnLogError(IsReportable(), CHIP_ERROR_INCORRECT_STATE); + VerifyOrReturnLogError(IsReportableNow(), CHIP_ERROR_INCORRECT_STATE); if (IsPriming() || IsChunkedReport()) { mSessionHandle.Grab(mExchangeCtx->GetSessionHandle()); @@ -272,7 +272,7 @@ CHIP_ERROR ReadHandler::SendStatusReport(Protocols::InteractionModel::Status aSt CHIP_ERROR ReadHandler::SendReportData(System::PacketBufferHandle && aPayload, bool aMoreChunks) { - VerifyOrReturnLogError(IsReportable(), CHIP_ERROR_INCORRECT_STATE); + VerifyOrReturnLogError(IsReportableNow(), CHIP_ERROR_INCORRECT_STATE); VerifyOrDie(!IsAwaitingReportResponse()); // Should not be reportable! if (IsPriming() || IsChunkedReport()) { @@ -319,10 +319,10 @@ CHIP_ERROR ReadHandler::SendReportData(System::PacketBufferHandle && aPayload, b if (IsType(InteractionType::Subscribe) && !IsPriming()) { - // Ignore the error from RefreshSubscribeSyncTimer. If we've + // Ignore the error from UpdateReportTimer. If we've // successfully sent the message, we need to return success from // this method. - RefreshSubscribeSyncTimer(); + UpdateReportTimer(); } } if (!aMoreChunks) @@ -591,7 +591,7 @@ void ReadHandler::MoveToState(const HandlerState aTargetState) // If we just unblocked sending reports, let's go ahead and schedule the reporting // engine to run to kick that off. // - if (aTargetState == HandlerState::GeneratingReports && IsReportable()) + if (aTargetState == HandlerState::GeneratingReports && IsReportableNow()) { InteractionModelEngine::GetInstance()->GetReportingEngine().ScheduleRun(); } @@ -634,7 +634,7 @@ CHIP_ERROR ReadHandler::SendSubscribeResponse() ReturnErrorOnFailure(writer.Finalize(&packet)); VerifyOrReturnLogError(mExchangeCtx, CHIP_ERROR_INCORRECT_STATE); - ReturnErrorOnFailure(RefreshSubscribeSyncTimer()); + ReturnErrorOnFailure(UpdateReportTimer()); ClearStateFlag(ReadHandlerFlags::PrimingReports); return mExchangeCtx->SendMessage(Protocols::InteractionModel::MsgType::SubscribeResponse, std::move(packet)); @@ -753,42 +753,42 @@ void ReadHandler::PersistSubscription() } } -void ReadHandler::OnUnblockHoldReportCallback(System::Layer * apSystemLayer, void * apAppState) +void ReadHandler::MinIntervalExpiredCallback(System::Layer * apSystemLayer, void * apAppState) { VerifyOrReturn(apAppState != nullptr); ReadHandler * readHandler = static_cast(apAppState); ChipLogDetail(DataManagement, "Unblock report hold after min %d seconds", readHandler->mMinIntervalFloorSeconds); - readHandler->ClearStateFlag(ReadHandlerFlags::HoldReport); + readHandler->ClearStateFlag(ReadHandlerFlags::WaitingUntilMinInterval); InteractionModelEngine::GetInstance()->GetExchangeManager()->GetSessionManager()->SystemLayer()->StartTimer( - System::Clock::Seconds16(readHandler->mMaxInterval - readHandler->mMinIntervalFloorSeconds), - OnRefreshSubscribeTimerSyncCallback, readHandler); + System::Clock::Seconds16(readHandler->mMaxInterval - readHandler->mMinIntervalFloorSeconds), MaxIntervalExpiredCallback, + readHandler); } -void ReadHandler::OnRefreshSubscribeTimerSyncCallback(System::Layer * apSystemLayer, void * apAppState) +void ReadHandler::MaxIntervalExpiredCallback(System::Layer * apSystemLayer, void * apAppState) { VerifyOrReturn(apAppState != nullptr); ReadHandler * readHandler = static_cast(apAppState); - readHandler->ClearStateFlag(ReadHandlerFlags::HoldSync); + readHandler->ClearStateFlag(ReadHandlerFlags::WaitingUntilMaxInterval); ChipLogProgress(DataManagement, "Refresh subscribe timer sync after %d seconds", readHandler->mMaxInterval - readHandler->mMinIntervalFloorSeconds); } -CHIP_ERROR ReadHandler::RefreshSubscribeSyncTimer() +CHIP_ERROR ReadHandler::UpdateReportTimer() { InteractionModelEngine::GetInstance()->GetExchangeManager()->GetSessionManager()->SystemLayer()->CancelTimer( - OnUnblockHoldReportCallback, this); + MinIntervalExpiredCallback, this); InteractionModelEngine::GetInstance()->GetExchangeManager()->GetSessionManager()->SystemLayer()->CancelTimer( - OnRefreshSubscribeTimerSyncCallback, this); + MaxIntervalExpiredCallback, this); if (!IsChunkedReport()) { ChipLogProgress(DataManagement, "Refresh Subscribe Sync Timer with min %d seconds and max %d seconds", mMinIntervalFloorSeconds, mMaxInterval); - SetStateFlag(ReadHandlerFlags::HoldReport); - SetStateFlag(ReadHandlerFlags::HoldSync); + SetStateFlag(ReadHandlerFlags::WaitingUntilMinInterval); + SetStateFlag(ReadHandlerFlags::WaitingUntilMaxInterval); ReturnErrorOnFailure( InteractionModelEngine::GetInstance()->GetExchangeManager()->GetSessionManager()->SystemLayer()->StartTimer( - System::Clock::Seconds16(mMinIntervalFloorSeconds), OnUnblockHoldReportCallback, this)); + System::Clock::Seconds16(mMinIntervalFloorSeconds), MinIntervalExpiredCallback, this)); } return CHIP_NO_ERROR; @@ -800,13 +800,13 @@ void ReadHandler::ResetPathIterator() mAttributeEncoderState = AttributeValueEncoder::AttributeEncodeState(); } -void ReadHandler::SetDirty(const AttributePathParams & aAttributeChanged) +void ReadHandler::AttributePathIsDirty(const AttributePathParams & aAttributeChanged) { ConcreteAttributePath path; mDirtyGeneration = InteractionModelEngine::GetInstance()->GetReportingEngine().GetDirtySetGeneration(); - // We won't reset the path iterator for every SetDirty call to reduce the number of full data reports. + // We won't reset the path iterator for every AttributePathIsDirty call to reduce the number of full data reports. // The iterator will be reset after finishing each report session. // // Here we just reset the iterator to the beginning of the current cluster, if the dirty path affects it. @@ -829,7 +829,7 @@ void ReadHandler::SetDirty(const AttributePathParams & aAttributeChanged) mAttributeEncoderState = AttributeValueEncoder::AttributeEncodeState(); } - if (IsReportable()) + if (IsReportableNow()) { InteractionModelEngine::GetInstance()->GetReportingEngine().ScheduleRun(); } @@ -844,17 +844,17 @@ Transport::SecureSession * ReadHandler::GetSession() const return mSessionHandle->AsSecureSession(); } -void ReadHandler::UnblockUrgentEventDelivery() +void ReadHandler::ForceDirtyState() { SetStateFlag(ReadHandlerFlags::ForceDirty); } void ReadHandler::SetStateFlag(ReadHandlerFlags aFlag, bool aValue) { - bool oldReportable = IsReportable(); + bool oldReportable = IsReportableNow(); mFlags.Set(aFlag, aValue); // If we became reportable, schedule a reporting run. - if (!oldReportable && IsReportable()) + if (!oldReportable && IsReportableNow()) { InteractionModelEngine::GetInstance()->GetReportingEngine().ScheduleRun(); } diff --git a/src/app/ReadHandler.h b/src/app/ReadHandler.h index a933aa76e51389..f460188935223e 100644 --- a/src/app/ReadHandler.h +++ b/src/app/ReadHandler.h @@ -212,15 +212,15 @@ class ReadHandler : public Messaging::ExchangeDelegate enum class ReadHandlerFlags : uint8_t { - // mHoldReport is used to prevent subscription data delivery while we are + // WaitingUntilMinInterval is used to prevent subscription data delivery while we are // waiting for the min reporting interval to elapse. - HoldReport = (1 << 0), + WaitingUntilMinInterval = (1 << 0), - // mHoldSync is used to prevent subscription empty report delivery while we - // are waiting for the max reporting interval to elaps. When mHoldSync + // WaitingUntilMaxInterval is used to prevent subscription empty report delivery while we + // are waiting for the max reporting interval to elaps. When WaitingUntilMaxInterval // becomes false, we are allowed to send an empty report to keep the // subscription alive on the client. - HoldSync = (1 << 1), + WaitingUntilMaxInterval = (1 << 1), // The flag indicating we are in the middle of a series of chunked report messages, this flag will be cleared during // sending last chunked message. @@ -290,13 +290,16 @@ class ReadHandler : public Messaging::ExchangeDelegate bool IsFromSubscriber(Messaging::ExchangeContext & apExchangeContext) const; bool IsIdle() const { return mState == HandlerState::Idle; } - bool IsReportable() const + + /// @brief Returns whether the ReadHandler is in a state where it can immediately send a report. This function + /// is used to determine whether a report generation should be scheduled for the handler. + bool IsReportableNow() const { - // Important: Anything that changes the state IsReportable depends on in - // a way that causes IsReportable to become true must call ScheduleRun + // Important: Anything that changes the state IsReportableNow depends on in + // a way that causes IsReportableNow to become true must call ScheduleRun // on the reporting engine. - return mState == HandlerState::GeneratingReports && !mFlags.Has(ReadHandlerFlags::HoldReport) && - (IsDirty() || !mFlags.Has(ReadHandlerFlags::HoldSync)); + return mState == HandlerState::GeneratingReports && !mFlags.Has(ReadHandlerFlags::WaitingUntilMinInterval) && + (IsDirty() || !mFlags.Has(ReadHandlerFlags::WaitingUntilMaxInterval)); } bool IsGeneratingReports() const { return mState == HandlerState::GeneratingReports; } bool IsAwaitingReportResponse() const { return mState == HandlerState::AwaitingReportResponse; } @@ -323,10 +326,10 @@ class ReadHandler : public Messaging::ExchangeDelegate void GetSubscriptionId(SubscriptionId & aSubscriptionId) const { aSubscriptionId = mSubscriptionId; } AttributePathExpandIterator * GetAttributePathExpandIterator() { return &mAttributePathExpandIterator; } - /** - * Notify the read handler that a set of attribute paths has been marked dirty. - */ - void SetDirty(const AttributePathParams & aAttributeChanged); + /// @brief Notifies the read handler that a set of attribute paths has been marked dirty. This will schedule a reporting engine + /// run if the change to the attribute path makes the ReadHandler reportable. + /// @param aAttributeChanged Path to the attribute that was changed. + void AttributePathIsDirty(const AttributePathParams & aAttributeChanged); bool IsDirty() const { return (mDirtyGeneration > mPreviousReportsBeginGeneration) || mFlags.Has(ReadHandlerFlags::ForceDirty); @@ -349,7 +352,10 @@ class ReadHandler : public Messaging::ExchangeDelegate auto GetTransactionStartGeneration() const { return mTransactionStartGeneration; } - void UnblockUrgentEventDelivery(); + /// @brief Forces the read handler into a dirty state, regardless of what's going on with attributes. + /// This can lead to scheduling of a reporting run immediately, if the min interval has been reached, + /// or after the min interval is reached if it has not yet been reached. + void ForceDirtyState(); const AttributeValueEncoder::AttributeEncodeState & GetAttributeEncodeState() const { return mAttributeEncoderState; } void SetAttributeEncodeState(const AttributeValueEncoder::AttributeEncodeState & aState) { mAttributeEncoderState = aState; } @@ -396,9 +402,12 @@ class ReadHandler : public Messaging::ExchangeDelegate */ void Close(CloseOptions options = CloseOptions::kDropPersistedSubscription); - static void OnUnblockHoldReportCallback(System::Layer * apSystemLayer, void * apAppState); - static void OnRefreshSubscribeTimerSyncCallback(System::Layer * apSystemLayer, void * apAppState); - CHIP_ERROR RefreshSubscribeSyncTimer(); + /// @brief This function is called when the min interval timer has expired, it restarts the timer on a timeout equal to the + /// difference between the max interval and the min interval. + static void MinIntervalExpiredCallback(System::Layer * apSystemLayer, void * apAppState); + static void MaxIntervalExpiredCallback(System::Layer * apSystemLayer, void * apAppState); + /// @brief This function is called when a report is sent and it restarts the min interval timer. + CHIP_ERROR UpdateReportTimer(); CHIP_ERROR SendSubscribeResponse(); CHIP_ERROR ProcessSubscribeRequest(System::PacketBufferHandle && aPayload); CHIP_ERROR ProcessReadRequest(System::PacketBufferHandle && aPayload); @@ -416,8 +425,15 @@ class ReadHandler : public Messaging::ExchangeDelegate void PersistSubscription(); - // Helpers for managing our state flags properly. + /// @brief Modifies a state flag in the read handler. If the read handler went from a + /// non-reportable state to a reportable state, schedules a reporting engine run. + /// @param aFlag Flag to set + /// @param aValue Flag new value void SetStateFlag(ReadHandlerFlags aFlag, bool aValue = true); + + /// @brief This function call SetStateFlag with the flag value set to false, thus possibly emitting a report + /// generation. + /// @param aFlag Flag to clear void ClearStateFlag(ReadHandlerFlags aFlag); // Helpers for continuing the subscription resumption @@ -436,7 +452,7 @@ class ReadHandler : public Messaging::ExchangeDelegate // current generation when we started sending the last set reports that we completed. // // This allows us to reset the iterator to the beginning of the current - // cluster instead of the beginning of the whole report in SetDirty, without + // cluster instead of the beginning of the whole report in AttributePathIsDirty, without // permanently missing dirty any paths. uint64_t mDirtyGeneration = 0; @@ -450,14 +466,14 @@ class ReadHandler : public Messaging::ExchangeDelegate /* * (mDirtyGeneration = b > a, this is a dirty read handler) * +- Start Report -> mCurrentReportsBeginGeneration = c - * | +- SetDirty (Attribute Y) -> mDirtyGeneration = d + * | +- AttributePathIsDirty (Attribute Y) -> mDirtyGeneration = d * | | +- Last Chunk -> mPreviousReportsBeginGeneration = mCurrentReportsBeginGeneration = c * | | | +- (mDirtyGeneration = d) > (mPreviousReportsBeginGeneration = c), this is a dirty read handler * | | | | Attribute X has a dirty generation less than c, Attribute Y has a dirty generation larger than c * | | | | So Y will be included in the report but X will not be inclued in this report. * -a--b--c------d-----e---f---> Generation * | | - * | +- SetDirty (Attribute X) (mDirtyGeneration = b) + * | +- AttributePathIsDirty (Attribute X) (mDirtyGeneration = b) * +- mPreviousReportsBeginGeneration * For read handler, if mDirtyGeneration > mPreviousReportsBeginGeneration, then we regard it as a dirty read handler, and it * should generate report on timeout reached. diff --git a/src/app/clusters/on-off-server/on-off-server.cpp b/src/app/clusters/on-off-server/on-off-server.cpp index 78be247dd256ed..bfda035f23bde1 100644 --- a/src/app/clusters/on-off-server/on-off-server.cpp +++ b/src/app/clusters/on-off-server/on-off-server.cpp @@ -41,15 +41,253 @@ using namespace chip::app::Clusters; using namespace chip::app::Clusters::OnOff; using chip::Protocols::InteractionModel::Status; +#ifdef EMBER_AF_PLUGIN_LEVEL_CONTROL +static bool LevelControlWithOnOffFeaturePresent(EndpointId endpoint) +{ + if (!emberAfContainsServer(endpoint, LevelControl::Id)) + { + return false; + } + + return LevelControlHasFeature(endpoint, LevelControl::Feature::kOnOff); +} +#endif // EMBER_AF_PLUGIN_LEVEL_CONTROL + +static constexpr size_t kOnOffMaxEnpointCount = + EMBER_AF_ON_OFF_CLUSTER_SERVER_ENDPOINT_COUNT + CHIP_DEVICE_CONFIG_DYNAMIC_ENDPOINT_COUNT; + +#ifdef EMBER_AF_PLUGIN_SCENES +static EmberEventControl sceneHandlerEventControls[kOnOffMaxEnpointCount]; +static void sceneOnOffCallback(EndpointId endpoint); + +class DefaultOnOffSceneHandler : public scenes::DefaultSceneHandlerImpl +{ +public: + /// @brief Struct to keep track of the desired state of the OnOff attribute between ApplyScene and + /// transition time expiration + struct EndpointStatePair + { + EndpointStatePair(EndpointId endpoint = kInvalidEndpointId, bool status = false) : mEndpoint(endpoint), mState(status) {} + EndpointId mEndpoint; + bool mState; + }; + + /// @brief Struct holding an array of EndpointStatePair. Handles insertion, get and removal by EndpointID. + /// TODO: Implement generic object to handle this boilerplate array manipulation + struct StatePairBuffer + { + bool IsEmpty() const { return (mPairCount == 0); } + + CHIP_ERROR FindPair(const EndpointId endpoint, uint16_t & found_index) const + { + VerifyOrReturnError(!IsEmpty(), CHIP_ERROR_NOT_FOUND); + for (found_index = 0; found_index < mPairCount; found_index++) + { + if (endpoint == mStatePairBuffer[found_index].mEndpoint) + { + return CHIP_NO_ERROR; + } + } + + return CHIP_ERROR_NOT_FOUND; + } + + CHIP_ERROR InsertPair(const EndpointStatePair & status) + { + uint16_t idx; + CHIP_ERROR err = FindPair(status.mEndpoint, idx); + + if (CHIP_NO_ERROR == err) + { + mStatePairBuffer[idx] = status; + } + else if (mPairCount < MAX_ENDPOINT_COUNT) + { + // if not found, insert at the end + mStatePairBuffer[mPairCount] = status; + mPairCount++; + } + else + { + return CHIP_ERROR_NO_MEMORY; + } + + return CHIP_NO_ERROR; + } + + CHIP_ERROR GetPair(const EndpointId endpoint, EndpointStatePair & status) const + { + uint16_t idx; + ReturnErrorOnFailure(FindPair(endpoint, idx)); + + status = mStatePairBuffer[idx]; + return CHIP_NO_ERROR; + } + + /// @brief Removes Pair and decrements Pair count if the endpoint existed in the array + /// @param endpoint : endpoint id of the pair + CHIP_ERROR RemovePair(const EndpointId endpoint) + { + uint16_t position; + VerifyOrReturnValue(CHIP_NO_ERROR == FindPair(endpoint, position), CHIP_NO_ERROR); + + uint16_t nextPos = static_cast(position + 1); + uint16_t moveNum = static_cast(mPairCount - nextPos); + + // Compress array after removal, if the removed position is not the last + if (moveNum) + { + memmove(&mStatePairBuffer[position], &mStatePairBuffer[nextPos], sizeof(EndpointStatePair) * moveNum); + } + + mPairCount--; + // Clear last occupied position + mStatePairBuffer[mPairCount].mEndpoint = kInvalidEndpointId; + + return CHIP_NO_ERROR; + } + + uint16_t mPairCount; + EndpointStatePair mStatePairBuffer[kOnOffMaxEnpointCount]; + }; + + StatePairBuffer mSceneEndpointStatePairs; + // As per spec, 1 attribute is scenable in the on off cluster + static constexpr uint8_t scenableAttributeCount = 1; + + DefaultOnOffSceneHandler() = default; + ~DefaultOnOffSceneHandler() override {} + + // Default function for OnOff cluster, only puts the OnOff cluster ID in the span if supported on the given endpoint + virtual void GetSupportedClusters(EndpointId endpoint, Span & clusterBuffer) override + { + ClusterId * buffer = clusterBuffer.data(); + if (emberAfContainsServer(endpoint, OnOff::Id) && clusterBuffer.size() >= 1) + { + buffer[0] = OnOff::Id; + clusterBuffer.reduce_size(1); + } + else + { + clusterBuffer.reduce_size(0); + } + } + + // Default function for OnOff cluster, only checks if OnOff is enabled on the endpoint + bool SupportsCluster(EndpointId endpoint, ClusterId cluster) override + { + return (cluster == OnOff::Id) && (emberAfContainsServer(endpoint, OnOff::Id)); + } + + /// @brief Serialize the Cluster's EFS value + /// @param endpoint target endpoint + /// @param cluster target cluster + /// @param serializedBytes data to serialize into EFS + /// @return CHIP_NO_ERROR if successfully serialized the data, CHIP_ERROR_INVALID_ARGUMENT otherwise + CHIP_ERROR SerializeSave(EndpointId endpoint, ClusterId cluster, MutableByteSpan & serializedBytes) override + { + using AttributeValuePair = Scenes::Structs::AttributeValuePair::Type; + + bool currentValue; + // read current on/off value + EmberAfStatus status = Attributes::OnOff::Get(endpoint, ¤tValue); + if (status != EMBER_ZCL_STATUS_SUCCESS) + { + ChipLogError(Zcl, "ERR: reading on/off %x", status); + return CHIP_ERROR_READ_FAILED; + } + + AttributeValuePair pairs[scenableAttributeCount]; + + pairs[0].attributeID.SetValue(Attributes::OnOff::Id); + pairs[0].attributeValue = currentValue; + + app::DataModel::List attributeValueList(pairs); + + return EncodeAttributeValueList(attributeValueList, serializedBytes); + } + + /// @brief Default EFS interaction when applying scene to the OnOff Cluster + /// @param endpoint target endpoint + /// @param cluster target cluster + /// @param serializedBytes Data from nvm + /// @param timeMs transition time in ms + /// @return CHIP_NO_ERROR if value as expected, CHIP_ERROR_INVALID_ARGUMENT otherwise + CHIP_ERROR ApplyScene(EndpointId endpoint, ClusterId cluster, const ByteSpan & serializedBytes, + scenes::TransitionTimeMs timeMs) override + { + app::DataModel::DecodableList attributeValueList; + + VerifyOrReturnError(cluster == OnOff::Id, CHIP_ERROR_INVALID_ARGUMENT); + + ReturnErrorOnFailure(DecodeAttributeValueList(serializedBytes, attributeValueList)); + + size_t attributeCount = 0; + ReturnErrorOnFailure(attributeValueList.ComputeSize(&attributeCount)); + VerifyOrReturnError(attributeCount <= scenableAttributeCount, CHIP_ERROR_BUFFER_TOO_SMALL); + + auto pair_iterator = attributeValueList.begin(); + while (pair_iterator.Next()) + { + auto & decodePair = pair_iterator.GetValue(); + if (decodePair.attributeID.HasValue()) + { + // If attribute ID was encoded, verify it is the proper ID for the OnOff attribute + VerifyOrReturnError(decodePair.attributeID.Value() == Attributes::OnOff::Id, CHIP_ERROR_INVALID_ARGUMENT); + } + ReturnErrorOnFailure( + mSceneEndpointStatePairs.InsertPair(EndpointStatePair(endpoint, static_cast(decodePair.attributeValue)))); + } + // Verify that the EFS was completely read + CHIP_ERROR err = pair_iterator.GetStatus(); + if (CHIP_NO_ERROR != err) + { + mSceneEndpointStatePairs.RemovePair(endpoint); + return err; + } + + OnOffServer::Instance().scheduleTimerCallbackMs(sceneEventControl(endpoint), timeMs); + + return CHIP_NO_ERROR; + } + +private: + /** + * @brief Configures EventControl callback when setting On Off through scenes callback + * + * @param[in] endpoint endpoint to start timer for + * @return EmberEventControl* configured event control + */ + EmberEventControl * sceneEventControl(EndpointId endpoint) + { + EmberEventControl * controller = + OnOffServer::Instance().getEventControl(endpoint, Span(sceneHandlerEventControls)); + VerifyOrReturnValue(controller != nullptr, nullptr); + + controller->endpoint = endpoint; + controller->callback = &sceneOnOffCallback; + + return controller; + } +}; +static DefaultOnOffSceneHandler sOnOffSceneHandler; + +static void sceneOnOffCallback(EndpointId endpoint) +{ + DefaultOnOffSceneHandler::EndpointStatePair savedState; + ReturnOnFailure(sOnOffSceneHandler.mSceneEndpointStatePairs.GetPair(endpoint, savedState)); + chip::CommandId command = (savedState.mState) ? Commands::On::Id : Commands::Off::Id; + OnOffServer::Instance().setOnOffValue(endpoint, command, false); + ReturnOnFailure(sOnOffSceneHandler.mSceneEndpointStatePairs.RemovePair(endpoint)); +} +#endif // EMBER_AF_PLUGIN_SCENES + /********************************************************** * Attributes Definition *********************************************************/ static OnOffEffect * firstEffect = nullptr; OnOffServer OnOffServer::instance; - -static constexpr size_t kOnOffMaxEnpointCount = - EMBER_AF_ON_OFF_CLUSTER_SERVER_ENDPOINT_COUNT + CHIP_DEVICE_CONFIG_DYNAMIC_ENDPOINT_COUNT; static EmberEventControl gEventControls[kOnOffMaxEnpointCount]; /********************************************************** @@ -85,7 +323,7 @@ void OnOffServer::cancelEndpointTimerCallback(EmberEventControl * control) void OnOffServer::cancelEndpointTimerCallback(EndpointId endpoint) { - auto control = OnOffServer::getEventControl(endpoint); + auto control = OnOffServer::getEventControl(endpoint, Span(gEventControls)); if (control) { cancelEndpointTimerCallback(control); @@ -107,6 +345,16 @@ OnOffServer & OnOffServer::Instance() return instance; } +chip::scenes::SceneHandler * OnOffServer::GetSceneHandler() +{ + +#ifdef EMBER_AF_PLUGIN_SCENES + return &sOnOffSceneHandler; +#else + return nullptr; +#endif // EMBER_AF_PLUGIN_SCENES +} + bool OnOffServer::HasFeature(chip::EndpointId endpoint, Feature feature) { bool success; @@ -130,18 +378,6 @@ EmberAfStatus OnOffServer::getOnOffValue(chip::EndpointId endpoint, bool * curre return status; } -#ifdef EMBER_AF_PLUGIN_LEVEL_CONTROL -static bool LevelControlWithOnOffFeaturePresent(EndpointId endpoint) -{ - if (!emberAfContainsServer(endpoint, LevelControl::Id)) - { - return false; - } - - return LevelControlHasFeature(endpoint, LevelControl::Feature::kOnOff); -} -#endif // EMBER_AF_PLUGIN_LEVEL_CONTROL - /** @brief On/off Cluster Set Value * * This function is called when the on/off value needs to be set, either through @@ -194,7 +430,7 @@ EmberAfStatus OnOffServer::setOnOffValue(chip::EndpointId endpoint, chip::Comman Attributes::OffWaitTime::Set(endpoint, 0); // Stop timer on the endpoint - EmberEventControl * event = getEventControl(endpoint); + EmberEventControl * event = getEventControl(endpoint, Span(gEventControls)); if (event != nullptr) { cancelEndpointTimerCallback(event); @@ -307,6 +543,11 @@ void OnOffServer::initOnOffServer(chip::EndpointId endpoint) status = setOnOffValue(endpoint, onOffValueForStartUp, true); } +#ifdef EMBER_AF_PLUGIN_SCENES + // Registers Scene handlers for the On/Off cluster on the server + // app::Clusters::Scenes::ScenesServer::Instance().RegisterSceneHandler(OnOffServer::Instance().GetSceneHandler()); +#endif + #ifdef EMBER_AF_PLUGIN_MODE_SELECT // If OnMode is not a null value, then change the current mode to it. if (onOffValueForStartUp && emberAfContainsServer(endpoint, ModeSelect::Id) && @@ -322,6 +563,7 @@ void OnOffServer::initOnOffServer(chip::EndpointId endpoint) #endif } #endif // IGNORE_ON_OFF_CLUSTER_START_UP_ON_OFF + emberAfPluginOnOffClusterServerPostInitCallback(endpoint); } @@ -629,7 +871,7 @@ void OnOffServer::updateOnOffTimeCommand(chip::EndpointId endpoint) ChipLogProgress(Zcl, "Timer Callback - wait Off Time cycle finished"); // Stop timer on the endpoint - cancelEndpointTimerCallback(getEventControl(endpoint)); + cancelEndpointTimerCallback(getEventControl(endpoint, Span(gEventControls))); } } } @@ -645,28 +887,31 @@ bool OnOffServer::areStartUpOnOffServerAttributesNonVolatile(EndpointId endpoint /** * @brief event control object for an endpoint * - * @param[in] endpoint + * @param[in] endpoint target endpoint + * @param[in] eventControlArray Array where to find the event control + * @param[in] eventControlArraySize Size of the event control array * @return EmberEventControl* configured event control */ -EmberEventControl * OnOffServer::getEventControl(EndpointId endpoint) +EmberEventControl * OnOffServer::getEventControl(EndpointId endpoint, const Span & eventControlArray) { uint16_t index = emberAfGetClusterServerEndpointIndex(endpoint, OnOff::Id, EMBER_AF_ON_OFF_CLUSTER_SERVER_ENDPOINT_COUNT); - if (index >= ArraySize(gEventControls)) + if (index >= eventControlArray.size()) { return nullptr; } - return &gEventControls[index]; + + return &eventControlArray[index]; } /** - * @brief Configures EnventControl callback when using XY colors + * @brief Configures EventControl callback when using XY colors * * @param[in] endpoint endpoint to start timer for * @return EmberEventControl* configured event control */ EmberEventControl * OnOffServer::configureEventControl(EndpointId endpoint) { - EmberEventControl * controller = getEventControl(endpoint); + EmberEventControl * controller = getEventControl(endpoint, Span(gEventControls)); VerifyOrReturnError(controller != nullptr, nullptr); controller->endpoint = endpoint; diff --git a/src/app/clusters/on-off-server/on-off-server.h b/src/app/clusters/on-off-server/on-off-server.h index 4b9da3d89cdfdc..c91c0612126aa1 100644 --- a/src/app/clusters/on-off-server/on-off-server.h +++ b/src/app/clusters/on-off-server/on-off-server.h @@ -20,6 +20,7 @@ #include #include #include +#include #include #include #include @@ -49,6 +50,8 @@ class OnOffServer static OnOffServer & Instance(); + chip::scenes::SceneHandler * GetSceneHandler(); + bool offCommand(chip::app::CommandHandler * commandObj, const chip::app::ConcreteCommandPath & commandPath); bool onCommand(chip::app::CommandHandler * commandObj, const chip::app::ConcreteCommandPath & commandPath); bool toggleCommand(chip::app::CommandHandler * commandObj, const chip::app::ConcreteCommandPath & commandPath); @@ -76,7 +79,7 @@ class OnOffServer #ifndef IGNORE_ON_OFF_CLUSTER_START_UP_ON_OFF bool areStartUpOnOffServerAttributesNonVolatile(chip::EndpointId endpoint); #endif - EmberEventControl * getEventControl(chip::EndpointId endpoint); + EmberEventControl * getEventControl(chip::EndpointId endpoint, const chip::Span & eventControlArray); EmberEventControl * configureEventControl(chip::EndpointId endpoint); uint32_t calculateNextWaitTimeMS(void); @@ -92,6 +95,8 @@ class OnOffServer static OnOffServer instance; chip::System::Clock::Timestamp nextDesiredOnWithTimedOffTimestamp; + + friend class DefaultOnOffSceneHandler; }; struct OnOffEffect diff --git a/src/app/clusters/refrigerator-alarm-server/refrigerator-alarm-server.cpp b/src/app/clusters/refrigerator-alarm-server/refrigerator-alarm-server.cpp new file mode 100644 index 00000000000000..719b144902776d --- /dev/null +++ b/src/app/clusters/refrigerator-alarm-server/refrigerator-alarm-server.cpp @@ -0,0 +1,157 @@ +/** + * + * Copyright (c) 2023 Project CHIP Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +#include "refrigerator-alarm-server.h" + +#include +#include +#include +#include +#include +#include +#include + +using namespace chip; +using namespace chip::app; +using namespace chip::app::Clusters; +using namespace chip::app::Clusters::RefrigeratorAlarm; +using namespace chip::app::Clusters::RefrigeratorAlarm::Attributes; +using namespace chip::DeviceLayer; +using chip::Protocols::InteractionModel::Status; + +using namespace std; +RefrigeratorAlarmServer RefrigeratorAlarmServer::instance; + +RefrigeratorAlarmServer & RefrigeratorAlarmServer::Instance() +{ + return instance; +} + +EmberAfStatus RefrigeratorAlarmServer::GetMaskValue(EndpointId endpoint, BitMask * mask) +{ + EmberAfStatus status = Attributes::Mask::Get(endpoint, mask); + if (status != EMBER_ZCL_STATUS_SUCCESS) + { + ChipLogProgress(Zcl, "Refrigerator Alarm: ERR: reading mask, err:0x%x", status); + return status; + } + + ChipLogProgress(Zcl, "Refrigerator Alarm: Mask ep%d value: %" PRIu32 "", endpoint, mask->Raw()); + + return status; +} + +EmberAfStatus RefrigeratorAlarmServer::GetStateValue(EndpointId endpoint, BitMask * state) +{ + EmberAfStatus status = Attributes::State::Get(endpoint, state); + if (status != EMBER_ZCL_STATUS_SUCCESS) + { + ChipLogProgress(Zcl, "Refrigerator Alarm: ERR: reading state, err:0x%x", status); + return status; + } + + ChipLogProgress(Zcl, "Refrigerator Alarm: State ep%d value: %" PRIu32 "", endpoint, state->Raw()); + + return status; +} + +EmberAfStatus RefrigeratorAlarmServer::SetMaskValue(EndpointId endpoint, const BitMask mask) +{ + EmberAfStatus status = EMBER_ZCL_STATUS_SUCCESS; + status = Attributes::Mask::Set(endpoint, mask); + if (status != EMBER_ZCL_STATUS_SUCCESS) + { + ChipLogProgress(Zcl, "Refrigerator Alarm: ERR: writing mask, err:0x%x", status); + return status; + } + + ChipLogProgress(Zcl, "Refrigerator Alarm: Mask ep%d value: %" PRIu32 "", endpoint, mask.Raw()); + + // Whenever there is change in Mask, State should change accordingly. + BitMask state; + status = GetStateValue(endpoint, &state); + if (status != EMBER_ZCL_STATUS_SUCCESS) + { + return status; + } + + if (state != (mask & state)) + { + state = mask & state; + status = SetStateValue(endpoint, state); + } + return status; +} + +EmberAfStatus RefrigeratorAlarmServer::SetStateValue(EndpointId endpoint, BitMask newState) +{ + EmberAfStatus status = EMBER_ZCL_STATUS_SUCCESS; + BitMask currentState; + + status = Attributes::State::Get(endpoint, ¤tState); + if (status != EMBER_ZCL_STATUS_SUCCESS) + { + ChipLogProgress(Zcl, "Refrigerator Alarm: ERR: reading state, err:0x%x", status); + return status; + } + + status = Attributes::State::Set(endpoint, newState); + if (status != EMBER_ZCL_STATUS_SUCCESS) + { + ChipLogProgress(Zcl, "Refrigerator Alarm: ERR: writing state, err:0x%x", status); + return status; + } + + ChipLogProgress(Zcl, "Refrigerator Alarm: State ep%d value: %" PRIu32 "", endpoint, newState.Raw()); + + // Generate Notify event. + BitMask becameActive; + becameActive.Set(newState).Clear(currentState); + BitMask becameInactive; + becameInactive.Set(currentState).Clear(newState); + // This field SHALL be a copy of the Mask attribute when this event was generated. + BitMask mask; + + status = GetMaskValue(endpoint, &mask); + if (status != EMBER_ZCL_STATUS_SUCCESS) + { + return status; + } + SendNotifyEvent(endpoint, becameActive, becameInactive, newState, mask); + + return status; +} + +void RefrigeratorAlarmServer::SendNotifyEvent(EndpointId endpointId, BitMask becameActive, + BitMask becameInactive, BitMask newState, BitMask mask) +{ + Events::Notify::Type event{ .active = becameActive, .inactive = becameInactive, .state = newState, .mask = mask }; + EventNumber eventNumber; + CHIP_ERROR error = LogEvent(event, endpointId, eventNumber); + if (CHIP_NO_ERROR != error) + { + ChipLogError(Zcl, "[Notify] Unable to send notify event: %s [endpointId=%d]", error.AsString(), endpointId); + } +} + +/********************************************************** + * Callbacks Implementation + *********************************************************/ + +void emberAfRefrigeratorAlarmClusterServerInitCallback(EndpointId endpoint) {} + +void MatterRefrigeratorAlarmPluginServerInitCallback() {} diff --git a/src/app/clusters/refrigerator-alarm-server/refrigerator-alarm-server.h b/src/app/clusters/refrigerator-alarm-server/refrigerator-alarm-server.h new file mode 100644 index 00000000000000..a165a6c62d0d15 --- /dev/null +++ b/src/app/clusters/refrigerator-alarm-server/refrigerator-alarm-server.h @@ -0,0 +1,50 @@ +/* + * + * Copyright (c) 2023 Project CHIP Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#pragma once + +#include +#include +#include +#include +#include +#include + +class RefrigeratorAlarmServer +{ +public: + static RefrigeratorAlarmServer & Instance(); + + EmberAfStatus GetMaskValue(chip::EndpointId endpoint, chip::BitMask * mask); + EmberAfStatus GetStateValue(chip::EndpointId endpoint, chip::BitMask * state); + + // Whenever there is change on Mask we should change State accordingly. + EmberAfStatus SetMaskValue(chip::EndpointId endpoint, + const chip::BitMask mask); + + // When State changes we are generating Notify event. + EmberAfStatus SetStateValue(chip::EndpointId endpoint, + chip::BitMask newState); + +private: + static RefrigeratorAlarmServer instance; + + void SendNotifyEvent(chip::EndpointId endpointId, chip::BitMask becameActive, + chip::BitMask becameInactive, + chip::BitMask newState, + chip::BitMask mask); +}; diff --git a/src/app/clusters/scenes-server/SceneTable.h b/src/app/clusters/scenes-server/SceneTable.h index 0453161b51e446..b76ade0a15c665 100644 --- a/src/app/clusters/scenes-server/SceneTable.h +++ b/src/app/clusters/scenes-server/SceneTable.h @@ -250,7 +250,7 @@ class SceneTable SceneTable(){}; - virtual ~SceneTable() = default; + virtual ~SceneTable(){}; // Not copyable SceneTable(const SceneTable &) = delete; diff --git a/src/app/clusters/scenes-server/SceneTableImpl.h b/src/app/clusters/scenes-server/SceneTableImpl.h index b162f819b4a747..c7b7e18a2f7782 100644 --- a/src/app/clusters/scenes-server/SceneTableImpl.h +++ b/src/app/clusters/scenes-server/SceneTableImpl.h @@ -40,8 +40,7 @@ using clusterId = chip::ClusterId; class DefaultSceneHandlerImpl : public scenes::SceneHandler { public: - static constexpr uint8_t kMaxValueSize = 4; - static constexpr uint8_t kMaxAvPair = 15; + static constexpr uint8_t kMaxAvPair = CHIP_CONFIG_SCENES_MAX_AV_PAIRS_EFS; DefaultSceneHandlerImpl() = default; ~DefaultSceneHandlerImpl() override{}; @@ -98,8 +97,7 @@ class DefaultSceneTableImpl : public SceneTable { public: DefaultSceneTableImpl() {} - - ~DefaultSceneTableImpl() override {} + ~DefaultSceneTableImpl() { Finish(); }; CHIP_ERROR Init(PersistentStorageDelegate * storage) override; void Finish() override; diff --git a/src/app/clusters/scenes-server/scenes-server.cpp b/src/app/clusters/scenes-server/scenes-server.cpp index 3655b0d087760b..e0398563982352 100644 --- a/src/app/clusters/scenes-server/scenes-server.cpp +++ b/src/app/clusters/scenes-server/scenes-server.cpp @@ -143,8 +143,6 @@ void ScenesServer::Shutdown() { chip::app::InteractionModelEngine::GetInstance()->UnregisterCommandHandler(this); - SceneTable * sceneTable = scenes::GetSceneTableImpl(); - sceneTable->Finish(); mGroupProvider = nullptr; mIsInitialized = false; } @@ -547,6 +545,32 @@ void ScenesServer::RecallScene(FabricIndex aFabricIx, EndpointId aEndpointId, Gr } } +bool ScenesServer::IsHandlerRegistered(scenes::SceneHandler * handler) +{ + SceneTable * sceneTable = scenes::GetSceneTableImpl(); + return sceneTable->mHandlerList.Contains(handler); +} + +void ScenesServer::RegisterSceneHandler(scenes::SceneHandler * handler) +{ + SceneTable * sceneTable = scenes::GetSceneTableImpl(); + + if (!IsHandlerRegistered(handler)) + { + sceneTable->RegisterHandler(handler); + } +} + +void ScenesServer::UnregisterSceneHandler(scenes::SceneHandler * handler) +{ + SceneTable * sceneTable = scenes::GetSceneTableImpl(); + + if (IsHandlerRegistered(handler)) + { + sceneTable->UnregisterHandler(handler); + } +} + void ScenesServer::HandleAddScene(HandlerContext & ctx, const Commands::AddScene::DecodableType & req) { AddSceneParse(ctx, req, mGroupProvider); diff --git a/src/app/clusters/scenes-server/scenes-server.h b/src/app/clusters/scenes-server/scenes-server.h index ed14cc8cfb1eb0..47eb05db6616f4 100644 --- a/src/app/clusters/scenes-server/scenes-server.h +++ b/src/app/clusters/scenes-server/scenes-server.h @@ -51,9 +51,13 @@ class ScenesServer : public CommandHandlerInterface, public AttributeAccessInter void StoreCurrentScene(FabricIndex aFabricIx, EndpointId aEndpointId, GroupId aGroupId, SceneId aSceneId); void RecallScene(FabricIndex aFabricIx, EndpointId aEndpointId, GroupId aGroupId, SceneId aSceneId); + bool IsHandlerRegistered(scenes::SceneHandler * handler); + void RegisterSceneHandler(scenes::SceneHandler * handler); + void UnregisterSceneHandler(scenes::SceneHandler * handler); + private: ScenesServer() : CommandHandlerInterface(Optional(), Id), AttributeAccessInterface(Optional(), Id) {} - ~ScenesServer() {} + ~ScenesServer() { Shutdown(); } bool mIsInitialized = false; diff --git a/src/app/reporting/Engine.cpp b/src/app/reporting/Engine.cpp index 0f9d592737ce79..a9853215332fd5 100644 --- a/src/app/reporting/Engine.cpp +++ b/src/app/reporting/Engine.cpp @@ -636,7 +636,7 @@ void Engine::Run() ReadHandler * readHandler = imEngine->ActiveHandlerAt(mCurReadHandlerIdx % (uint32_t) imEngine->mReadHandlers.Allocated()); VerifyOrDie(readHandler != nullptr); - if (readHandler->IsReportable()) + if (readHandler->IsReportableNow()) { mRunningReadHandler = readHandler; CHIP_ERROR err = BuildAndSendSingleReportData(readHandler); @@ -826,16 +826,16 @@ CHIP_ERROR Engine::SetDirty(AttributePathParams & aAttributePath) bool intersectsInterestPath = false; InteractionModelEngine::GetInstance()->mReadHandlers.ForEachActiveObject( [&aAttributePath, &intersectsInterestPath](ReadHandler * handler) { - // We call SetDirty for both read interactions and subscribe interactions, since we may send inconsistent attribute data - // between two chunks. SetDirty will be ignored automatically by read handlers which are waiting for a response to the - // last message chunk for read interactions. + // We call AttributePathIsDirty for both read interactions and subscribe interactions, since we may send inconsistent + // attribute data between two chunks. AttributePathIsDirty will not schedule a new run for read handlers which are + // waiting for a response to the last message chunk for read interactions. if (handler->IsGeneratingReports() || handler->IsAwaitingReportResponse()) { for (auto object = handler->GetAttributePathList(); object != nullptr; object = object->mpNext) { if (object->mValue.Intersects(aAttributePath)) { - handler->SetDirty(aAttributePath); + handler->AttributePathIsDirty(aAttributePath); intersectsInterestPath = true; break; } @@ -937,7 +937,7 @@ CHIP_ERROR Engine::ScheduleEventDelivery(ConcreteEventPath & aPath, uint32_t aBy if (interestedPath->mValue.IsEventPathSupersetOf(aPath) && interestedPath->mValue.mIsUrgentEvent) { isUrgentEvent = true; - handler->UnblockUrgentEventDelivery(); + handler->ForceDirtyState(); break; } } @@ -967,7 +967,7 @@ void Engine::ScheduleUrgentEventDeliverySync(Optional fabricIndex) return Loop::Continue; } - handler->UnblockUrgentEventDelivery(); + handler->ForceDirtyState(); return Loop::Continue; }); diff --git a/src/app/tests/TestReadInteraction.cpp b/src/app/tests/TestReadInteraction.cpp index fe0d2a04e39731..9ec3d59330c216 100644 --- a/src/app/tests/TestReadInteraction.cpp +++ b/src/app/tests/TestReadInteraction.cpp @@ -1587,7 +1587,7 @@ void TestReadInteraction::TestSubscribeRoundtrip(nlTestSuite * apSuite, void * a dirtyPath5.mAttributeId = 4; // Test report with 2 different path - delegate.mpReadHandler->SetStateFlag(ReadHandler::ReadHandlerFlags::HoldReport, false); + delegate.mpReadHandler->SetStateFlag(ReadHandler::ReadHandlerFlags::WaitingUntilMinInterval, false); delegate.mGotReport = false; delegate.mGotEventResponse = false; delegate.mNumAttributeResponse = 0; @@ -1604,7 +1604,7 @@ void TestReadInteraction::TestSubscribeRoundtrip(nlTestSuite * apSuite, void * a NL_TEST_ASSERT(apSuite, delegate.mNumAttributeResponse == 2); // Test report with 2 different path, and 1 same path - delegate.mpReadHandler->SetStateFlag(ReadHandler::ReadHandlerFlags::HoldReport, false); + delegate.mpReadHandler->SetStateFlag(ReadHandler::ReadHandlerFlags::WaitingUntilMinInterval, false); delegate.mGotReport = false; delegate.mNumAttributeResponse = 0; err = engine->GetReportingEngine().SetDirty(dirtyPath1); @@ -1620,7 +1620,7 @@ void TestReadInteraction::TestSubscribeRoundtrip(nlTestSuite * apSuite, void * a NL_TEST_ASSERT(apSuite, delegate.mNumAttributeResponse == 2); // Test report with 3 different path, and one path is overlapped with another - delegate.mpReadHandler->SetStateFlag(ReadHandler::ReadHandlerFlags::HoldReport, false); + delegate.mpReadHandler->SetStateFlag(ReadHandler::ReadHandlerFlags::WaitingUntilMinInterval, false); delegate.mGotReport = false; delegate.mNumAttributeResponse = 0; err = engine->GetReportingEngine().SetDirty(dirtyPath1); @@ -1636,7 +1636,7 @@ void TestReadInteraction::TestSubscribeRoundtrip(nlTestSuite * apSuite, void * a NL_TEST_ASSERT(apSuite, delegate.mNumAttributeResponse == 2); // Test report with 3 different path, all are not overlapped, one path is not interested for current subscription - delegate.mpReadHandler->SetStateFlag(ReadHandler::ReadHandlerFlags::HoldReport, false); + delegate.mpReadHandler->SetStateFlag(ReadHandler::ReadHandlerFlags::WaitingUntilMinInterval, false); delegate.mGotReport = false; delegate.mNumAttributeResponse = 0; err = engine->GetReportingEngine().SetDirty(dirtyPath1); @@ -1652,8 +1652,8 @@ void TestReadInteraction::TestSubscribeRoundtrip(nlTestSuite * apSuite, void * a NL_TEST_ASSERT(apSuite, delegate.mNumAttributeResponse == 2); // Test empty report - delegate.mpReadHandler->SetStateFlag(ReadHandler::ReadHandlerFlags::HoldReport, false); - delegate.mpReadHandler->SetStateFlag(ReadHandler::ReadHandlerFlags::HoldSync, false); + delegate.mpReadHandler->SetStateFlag(ReadHandler::ReadHandlerFlags::WaitingUntilMinInterval, false); + delegate.mpReadHandler->SetStateFlag(ReadHandler::ReadHandlerFlags::WaitingUntilMaxInterval, false); NL_TEST_ASSERT(apSuite, engine->GetReportingEngine().IsRunScheduled()); delegate.mGotReport = false; delegate.mNumAttributeResponse = 0; @@ -1740,12 +1740,13 @@ void TestReadInteraction::TestSubscribeUrgentWildcardEvent(nlTestSuite * apSuite GenerateEvents(apSuite, apContext); - NL_TEST_ASSERT(apSuite, delegate.mpReadHandler->mFlags.Has(ReadHandler::ReadHandlerFlags::HoldReport)); + NL_TEST_ASSERT(apSuite, delegate.mpReadHandler->mFlags.Has(ReadHandler::ReadHandlerFlags::WaitingUntilMinInterval)); NL_TEST_ASSERT(apSuite, delegate.mpReadHandler->IsDirty()); delegate.mGotEventResponse = false; delegate.mGotReport = false; - NL_TEST_ASSERT(apSuite, nonUrgentDelegate.mpReadHandler->mFlags.Has(ReadHandler::ReadHandlerFlags::HoldReport)); + NL_TEST_ASSERT(apSuite, + nonUrgentDelegate.mpReadHandler->mFlags.Has(ReadHandler::ReadHandlerFlags::WaitingUntilMinInterval)); NL_TEST_ASSERT(apSuite, !nonUrgentDelegate.mpReadHandler->IsDirty()); nonUrgentDelegate.mGotEventResponse = false; nonUrgentDelegate.mGotReport = false; @@ -1781,13 +1782,14 @@ void TestReadInteraction::TestSubscribeUrgentWildcardEvent(nlTestSuite * apSuite // Since we just sent a report for our urgent subscription, we should have our min interval timer // running again. - NL_TEST_ASSERT(apSuite, delegate.mpReadHandler->mFlags.Has(ReadHandler::ReadHandlerFlags::HoldReport)); + NL_TEST_ASSERT(apSuite, delegate.mpReadHandler->mFlags.Has(ReadHandler::ReadHandlerFlags::WaitingUntilMinInterval)); NL_TEST_ASSERT(apSuite, !delegate.mpReadHandler->IsDirty()); delegate.mGotEventResponse = false; // For our non-urgent subscription, we did not send anything, so we // should not have a min interval timer running there. - NL_TEST_ASSERT(apSuite, !nonUrgentDelegate.mpReadHandler->mFlags.Has(ReadHandler::ReadHandlerFlags::HoldReport)); + NL_TEST_ASSERT(apSuite, + !nonUrgentDelegate.mpReadHandler->mFlags.Has(ReadHandler::ReadHandlerFlags::WaitingUntilMinInterval)); NL_TEST_ASSERT(apSuite, !nonUrgentDelegate.mpReadHandler->IsDirty()); // Wait for the min interval timer to fire. @@ -1807,15 +1809,16 @@ void TestReadInteraction::TestSubscribeUrgentWildcardEvent(nlTestSuite * apSuite // min-interval timer should have fired, and our handler should still // not be dirty or even reportable. - NL_TEST_ASSERT(apSuite, !delegate.mpReadHandler->mFlags.Has(ReadHandler::ReadHandlerFlags::HoldReport)); + NL_TEST_ASSERT(apSuite, !delegate.mpReadHandler->mFlags.Has(ReadHandler::ReadHandlerFlags::WaitingUntilMinInterval)); NL_TEST_ASSERT(apSuite, !delegate.mpReadHandler->IsDirty()); - NL_TEST_ASSERT(apSuite, !delegate.mpReadHandler->IsReportable()); + NL_TEST_ASSERT(apSuite, !delegate.mpReadHandler->IsReportableNow()); // And the non-urgent one should not have changed state either, since // it's waiting for the max-interval. - NL_TEST_ASSERT(apSuite, !nonUrgentDelegate.mpReadHandler->mFlags.Has(ReadHandler::ReadHandlerFlags::HoldReport)); + NL_TEST_ASSERT(apSuite, + !nonUrgentDelegate.mpReadHandler->mFlags.Has(ReadHandler::ReadHandlerFlags::WaitingUntilMinInterval)); NL_TEST_ASSERT(apSuite, !nonUrgentDelegate.mpReadHandler->IsDirty()); - NL_TEST_ASSERT(apSuite, !nonUrgentDelegate.mpReadHandler->IsReportable()); + NL_TEST_ASSERT(apSuite, !nonUrgentDelegate.mpReadHandler->IsReportableNow()); // There should be no reporting run scheduled. This is very important; // otherwise we can get a false-positive pass below because the run was @@ -1827,11 +1830,11 @@ void TestReadInteraction::TestSubscribeUrgentWildcardEvent(nlTestSuite * apSuite // Urgent read handler should now be dirty, and reportable. NL_TEST_ASSERT(apSuite, delegate.mpReadHandler->IsDirty()); - NL_TEST_ASSERT(apSuite, delegate.mpReadHandler->IsReportable()); + NL_TEST_ASSERT(apSuite, delegate.mpReadHandler->IsReportableNow()); // Non-urgent read handler should not be reportable. NL_TEST_ASSERT(apSuite, !nonUrgentDelegate.mpReadHandler->IsDirty()); - NL_TEST_ASSERT(apSuite, !nonUrgentDelegate.mpReadHandler->IsReportable()); + NL_TEST_ASSERT(apSuite, !nonUrgentDelegate.mpReadHandler->IsReportableNow()); // Still no reporting should have happened. NL_TEST_ASSERT(apSuite, !delegate.mGotEventResponse); @@ -1914,7 +1917,7 @@ void TestReadInteraction::TestSubscribeWildcard(nlTestSuite * apSuite, void * ap // Set a concrete path dirty { - delegate.mpReadHandler->SetStateFlag(ReadHandler::ReadHandlerFlags::HoldReport, false); + delegate.mpReadHandler->SetStateFlag(ReadHandler::ReadHandlerFlags::WaitingUntilMinInterval, false); delegate.mGotReport = false; delegate.mNumAttributeResponse = 0; @@ -1935,7 +1938,7 @@ void TestReadInteraction::TestSubscribeWildcard(nlTestSuite * apSuite, void * ap // Set a endpoint dirty { - delegate.mpReadHandler->SetStateFlag(ReadHandler::ReadHandlerFlags::HoldReport, false); + delegate.mpReadHandler->SetStateFlag(ReadHandler::ReadHandlerFlags::WaitingUntilMinInterval, false); delegate.mGotReport = false; delegate.mNumAttributeResponse = 0; delegate.mNumArrayItems = 0; @@ -2027,7 +2030,7 @@ void TestReadInteraction::TestSubscribePartialOverlap(nlTestSuite * apSuite, voi // Set a partial overlapped path dirty { - delegate.mpReadHandler->SetStateFlag(ReadHandler::ReadHandlerFlags::HoldReport, false); + delegate.mpReadHandler->SetStateFlag(ReadHandler::ReadHandlerFlags::WaitingUntilMinInterval, false); delegate.mGotReport = false; delegate.mNumAttributeResponse = 0; @@ -2104,7 +2107,7 @@ void TestReadInteraction::TestSubscribeSetDirtyFullyOverlap(nlTestSuite * apSuit // Set a full overlapped path dirty and expect to receive one E2C3A1 { - delegate.mpReadHandler->SetStateFlag(ReadHandler::ReadHandlerFlags::HoldReport, false); + delegate.mpReadHandler->SetStateFlag(ReadHandler::ReadHandlerFlags::WaitingUntilMinInterval, false); delegate.mGotReport = false; delegate.mNumAttributeResponse = 0; @@ -2225,8 +2228,8 @@ void TestReadInteraction::TestSubscribeInvalidAttributePathRoundtrip(nlTestSuite NL_TEST_ASSERT(apSuite, engine->ActiveHandlerAt(0) != nullptr); delegate.mpReadHandler = engine->ActiveHandlerAt(0); - delegate.mpReadHandler->SetStateFlag(ReadHandler::ReadHandlerFlags::HoldReport, false); - delegate.mpReadHandler->SetStateFlag(ReadHandler::ReadHandlerFlags::HoldSync, false); + delegate.mpReadHandler->SetStateFlag(ReadHandler::ReadHandlerFlags::WaitingUntilMinInterval, false); + delegate.mpReadHandler->SetStateFlag(ReadHandler::ReadHandlerFlags::WaitingUntilMaxInterval, false); NL_TEST_ASSERT(apSuite, engine->GetReportingEngine().IsRunScheduled()); ctx.DrainAndServiceIO(); @@ -2401,7 +2404,7 @@ void TestReadInteraction::TestPostSubscribeRoundtripStatusReportTimeout(nlTestSu dirtyPath2.mAttributeId = 2; // Test report with 2 different path - delegate.mpReadHandler->SetStateFlag(ReadHandler::ReadHandlerFlags::HoldReport, false); + delegate.mpReadHandler->SetStateFlag(ReadHandler::ReadHandlerFlags::WaitingUntilMinInterval, false); delegate.mGotReport = false; delegate.mNumAttributeResponse = 0; @@ -2415,8 +2418,8 @@ void TestReadInteraction::TestPostSubscribeRoundtripStatusReportTimeout(nlTestSu NL_TEST_ASSERT(apSuite, delegate.mGotReport); NL_TEST_ASSERT(apSuite, delegate.mNumAttributeResponse == 2); - delegate.mpReadHandler->SetStateFlag(ReadHandler::ReadHandlerFlags::HoldReport, false); - delegate.mpReadHandler->SetStateFlag(ReadHandler::ReadHandlerFlags::HoldSync, false); + delegate.mpReadHandler->SetStateFlag(ReadHandler::ReadHandlerFlags::WaitingUntilMinInterval, false); + delegate.mpReadHandler->SetStateFlag(ReadHandler::ReadHandlerFlags::WaitingUntilMaxInterval, false); delegate.mGotReport = false; delegate.mNumAttributeResponse = 0; ctx.ExpireSessionBobToAlice(); @@ -2763,8 +2766,8 @@ void TestReadInteraction::TestPostSubscribeRoundtripChunkStatusReportTimeout(nlT dirtyPath1.mEndpointId = Test::kMockEndpoint3; dirtyPath1.mAttributeId = Test::MockAttributeId(4); - delegate.mpReadHandler->SetStateFlag(ReadHandler::ReadHandlerFlags::HoldReport, false); - delegate.mpReadHandler->SetStateFlag(ReadHandler::ReadHandlerFlags::HoldSync, false); + delegate.mpReadHandler->SetStateFlag(ReadHandler::ReadHandlerFlags::WaitingUntilMinInterval, false); + delegate.mpReadHandler->SetStateFlag(ReadHandler::ReadHandlerFlags::WaitingUntilMaxInterval, false); err = engine->GetReportingEngine().SetDirty(dirtyPath1); NL_TEST_ASSERT(apSuite, err == CHIP_NO_ERROR); delegate.mGotReport = false; @@ -2865,8 +2868,8 @@ void TestReadInteraction::TestPostSubscribeRoundtripChunkReportTimeout(nlTestSui dirtyPath1.mEndpointId = Test::kMockEndpoint3; dirtyPath1.mAttributeId = Test::MockAttributeId(4); - delegate.mpReadHandler->SetStateFlag(ReadHandler::ReadHandlerFlags::HoldReport, false); - delegate.mpReadHandler->SetStateFlag(ReadHandler::ReadHandlerFlags::HoldSync, false); + delegate.mpReadHandler->SetStateFlag(ReadHandler::ReadHandlerFlags::WaitingUntilMinInterval, false); + delegate.mpReadHandler->SetStateFlag(ReadHandler::ReadHandlerFlags::WaitingUntilMaxInterval, false); err = engine->GetReportingEngine().SetDirty(dirtyPath1); NL_TEST_ASSERT(apSuite, err == CHIP_NO_ERROR); delegate.mGotReport = false; @@ -4246,7 +4249,7 @@ void TestReadInteraction::TestSubscriptionReportWithDefunctSession(nlTestSuite * NL_TEST_ASSERT(apSuite, SessionHandle(*readHandler->GetSession()) == ctx.GetSessionAliceToBob()); // Test that we send reports as needed. - readHandler->SetStateFlag(ReadHandler::ReadHandlerFlags::HoldReport, false); + readHandler->SetStateFlag(ReadHandler::ReadHandlerFlags::WaitingUntilMinInterval, false); delegate.mGotReport = false; delegate.mNumAttributeResponse = 0; engine->GetReportingEngine().SetDirty(subscribePath); @@ -4262,7 +4265,7 @@ void TestReadInteraction::TestSubscriptionReportWithDefunctSession(nlTestSuite * // Test that if the session is defunct we don't send reports and clean // up properly. readHandler->GetSession()->MarkAsDefunct(); - readHandler->SetStateFlag(ReadHandler::ReadHandlerFlags::HoldReport, false); + readHandler->SetStateFlag(ReadHandler::ReadHandlerFlags::WaitingUntilMinInterval, false); delegate.mGotReport = false; delegate.mNumAttributeResponse = 0; engine->GetReportingEngine().SetDirty(subscribePath); diff --git a/src/app/tests/TestSceneTable.cpp b/src/app/tests/TestSceneTable.cpp index b45bc3ee67dd28..f9c65adf57f284 100644 --- a/src/app/tests/TestSceneTable.cpp +++ b/src/app/tests/TestSceneTable.cpp @@ -159,7 +159,7 @@ class TestSceneHandler : public scenes::DefaultSceneHandlerImpl clusterBuffer.reduce_size(2); } } - else if (endpoint == kTestEndpoint1) + else if (endpoint == kTestEndpoint2) { if (clusterBuffer.size() >= 2) { @@ -168,7 +168,7 @@ class TestSceneHandler : public scenes::DefaultSceneHandlerImpl clusterBuffer.reduce_size(2); } } - else if (endpoint == kTestEndpoint1) + else if (endpoint == kTestEndpoint3) { if (clusterBuffer.size() >= 3) { @@ -178,6 +178,10 @@ class TestSceneHandler : public scenes::DefaultSceneHandlerImpl clusterBuffer.reduce_size(3); } } + else + { + clusterBuffer.reduce_size(0); + } } // Default function only checks if endpoint and clusters are valid @@ -432,6 +436,18 @@ void TestHandlerRegistration(nlTestSuite * aSuite, void * aContext) { sceneTable->RegisterHandler(&tmpHandler[i]); } + + // Emptying Handler array + sceneTable->UnregisterAllHandlers(); + + // Verify the handler num has been updated properly + NL_TEST_ASSERT(aSuite, sceneTable->HandlerListEmpty()); + + for (uint8_t i = 0; i < scenes::kMaxClustersPerScene; i++) + { + sceneTable->RegisterHandler(&tmpHandler[i]); + } + // Hanlder order in table : [H0, H1, H2] NL_TEST_ASSERT(aSuite, !sceneTable->HandlerListEmpty()); diff --git a/src/app/tests/suites/TestConstraints.yaml b/src/app/tests/suites/TestConstraints.yaml index aa1896d7ebd94e..9336cda206d9de 100644 --- a/src/app/tests/suites/TestConstraints.yaml +++ b/src/app/tests/suites/TestConstraints.yaml @@ -359,6 +359,34 @@ tests: arguments: value: "" + # Tests for NULLABLE_CHAR_STRING attribute + + - label: "Write attribute NULLABLE_CHAR_STRING Value" + command: "writeAttribute" + attribute: "nullable_char_string" + arguments: + value: null + + - label: "Read attribute NULLABLE_CHAR_STRING Value MinLength Constraints" + command: "readAttribute" + attribute: "nullable_char_string" + response: + constraints: + minLength: 5 + + - label: "Read attribute NULLABLE_CHAR_STRING Value MaxLength Constraints" + command: "readAttribute" + attribute: "nullable_char_string" + response: + constraints: + maxLength: 20 + + - label: "Write attribute NULLABLE_CHAR_STRING Value Back to Default Value" + command: "writeAttribute" + attribute: "nullable_char_string" + arguments: + value: "" + # Tests for hasValue attribute - label: "Read attribute NULLABLE_INT8U Default Value" diff --git a/src/app/tests/suites/include/ConstraintsChecker.h b/src/app/tests/suites/include/ConstraintsChecker.h index eb52c3b6b6bba5..0811ca85923f83 100644 --- a/src/app/tests/suites/include/ConstraintsChecker.h +++ b/src/app/tests/suites/include/ConstraintsChecker.h @@ -79,12 +79,36 @@ class ConstraintsChecker return CheckConstraintMinLength(itemName, current.size(), expected); } + template + bool CheckConstraintMinLength(const char * itemName, const chip::app::DataModel::Nullable> & current, + uint64_t expected) + { + if (current.IsNull()) + { + return true; + } + + return CheckConstraintMinLength(itemName, current.Value(), expected); + } + template bool CheckConstraintMaxLength(const char * itemName, const chip::Span & current, uint64_t expected) { return CheckConstraintMaxLength(itemName, current.size(), expected); } + template + bool CheckConstraintMaxLength(const char * itemName, const chip::app::DataModel::Nullable> & current, + uint64_t expected) + { + if (current.IsNull()) + { + return true; + } + + return CheckConstraintMaxLength(itemName, current.Value(), expected); + } + template bool CheckConstraintMinLength(const char * itemName, const chip::app::DataModel::DecodableList & current, uint64_t expected) { diff --git a/src/app/zap-templates/zcl/data-model/chip/door-lock-cluster.xml b/src/app/zap-templates/zcl/data-model/chip/door-lock-cluster.xml index 554426b035ac19..3b65e551bf963e 100644 --- a/src/app/zap-templates/zcl/data-model/chip/door-lock-cluster.xml +++ b/src/app/zap-templates/zcl/data-model/chip/door-lock-cluster.xml @@ -69,8 +69,8 @@ limitations under the License. cluster itself. Those attributes/commands are marked with a special comment. --> - LockState - LockType + LockState + LockType ActuatorEnabled DoorState diff --git a/src/app/zap-templates/zcl/data-model/chip/matter-devices.xml b/src/app/zap-templates/zcl/data-model/chip/matter-devices.xml index 8e091aa7f42ecd..f284a4aecafa90 100644 --- a/src/app/zap-templates/zcl/data-model/chip/matter-devices.xml +++ b/src/app/zap-templates/zcl/data-model/chip/matter-devices.xml @@ -1879,6 +1879,26 @@ limitations under the License. + + MA-smokecoalarm + CHIP + Matter Smoke CO Alarm + 0x0103 + 0x0076 + + + IDENTIFY_TIME + IDENTIFY_TYPE + Identify + + + + + + + + + MA-all-clusters-app CHIP @@ -2053,7 +2073,7 @@ limitations under the License. SERVER_LIST CLIENT_LIST PARTS_LIST - + diff --git a/src/app/zap-templates/zcl/data-model/chip/media-playback-cluster.xml b/src/app/zap-templates/zcl/data-model/chip/media-playback-cluster.xml index 4a6be6d3345b42..0444bdfbf9c98a 100644 --- a/src/app/zap-templates/zcl/data-model/chip/media-playback-cluster.xml +++ b/src/app/zap-templates/zcl/data-model/chip/media-playback-cluster.xml @@ -26,7 +26,7 @@ limitations under the License. This cluster provides an interface for controlling Media Playback (PLAY, PAUSE, etc) on a media device such as a TV or Speaker. - CurrentState + CurrentState StartTime Duration SampledPosition diff --git a/src/app/zap_cluster_list.json b/src/app/zap_cluster_list.json index 7925bbf5ee5fd9..6975c5cfe70164 100644 --- a/src/app/zap_cluster_list.json +++ b/src/app/zap_cluster_list.json @@ -263,11 +263,10 @@ ], "PWM_CLUSTER": [], "RADON_CONCENTRATION_MEASUREMENT_CLUSTER": [], - "REFRIGERATOR_ALARM_CLUSTER": ["refrigerator-alarm-server"], + "REFRIGERATOR_ALARM": ["refrigerator-alarm-server"], "REFRIGERATOR_AND_TEMPERATURE_CONTROLLED_CABINET_MODE_CLUSTER": [ "mode-select-server" ], - "REFRIGERATOR_ALARM_CLUSTER": ["refrigerator-alarm-server"], "RELATIVE_HUMIDITY_MEASUREMENT_CLUSTER": [], "RVC_CLEAN_MODE_CLUSTER": ["mode-select-server"], "RVC_RUN_MODE_CLUSTER": ["mode-select-server"], diff --git a/src/ble/BleLayer.cpp b/src/ble/BleLayer.cpp index 9109924ccd3754..57a8ca8dc0fdff 100644 --- a/src/ble/BleLayer.cpp +++ b/src/ble/BleLayer.cpp @@ -308,6 +308,13 @@ void BleLayer::Shutdown() void BleLayer::CloseAllBleConnections() { + // Cancel any ongoing attempt to establish new BLE connection + CHIP_ERROR err = CancelBleIncompleteConnection(); + if (err != CHIP_NO_ERROR) + { + ChipLogError(Ble, "CancelBleIncompleteConnection() failed, err = %" CHIP_ERROR_FORMAT, err.Format()); + } + // Close and free all BLE end points. for (size_t i = 0; i < BLE_LAYER_NUM_BLE_ENDPOINTS; i++) { diff --git a/src/controller/SetUpCodePairer.cpp b/src/controller/SetUpCodePairer.cpp index 27272caebf1fd4..e1ab5e778dd6df 100644 --- a/src/controller/SetUpCodePairer.cpp +++ b/src/controller/SetUpCodePairer.cpp @@ -36,19 +36,10 @@ constexpr uint32_t kDeviceDiscoveredTimeout = CHIP_CONFIG_SETUP_CODE_PAIRER_DISC namespace chip { namespace Controller { -CHIP_ERROR SetUpCodePairer::PairDevice(NodeId remoteId, const char * setUpCode, SetupCodePairerBehaviour commission, - DiscoveryType discoveryType, Optional resolutionData) -{ - VerifyOrReturnError(mSystemLayer != nullptr, CHIP_ERROR_INCORRECT_STATE); - if (resolutionData.HasValue()) - { - VerifyOrReturnError(discoveryType != DiscoveryType::kAll, CHIP_ERROR_INVALID_ARGUMENT); - } - - SetupPayload payload; - mConnectionType = commission; - mDiscoveryType = discoveryType; +namespace { +CHIP_ERROR GetPayload(const char * setUpCode, SetupPayload & payload) +{ bool isQRCode = strncmp(setUpCode, kQRCodePrefix, strlen(kQRCodePrefix)) == 0; if (isQRCode) { @@ -61,8 +52,33 @@ CHIP_ERROR SetUpCodePairer::PairDevice(NodeId remoteId, const char * setUpCode, VerifyOrReturnError(payload.isValidManualCode(), CHIP_ERROR_INVALID_ARGUMENT); } - mRemoteId = remoteId; - mSetUpPINCode = payload.setUpPINCode; + return CHIP_NO_ERROR; +} +} // namespace + +CHIP_ERROR SetUpCodePairer::PairDevice(NodeId remoteId, const char * setUpCode, SetupCodePairerBehaviour commission, + DiscoveryType discoveryType, Optional resolutionData) +{ + VerifyOrReturnError(mSystemLayer != nullptr, CHIP_ERROR_INCORRECT_STATE); + + SetupPayload payload; + ReturnErrorOnFailure(GetPayload(setUpCode, payload)); + + if (resolutionData.HasValue()) + { + VerifyOrReturnError(discoveryType != DiscoveryType::kAll, CHIP_ERROR_INVALID_ARGUMENT); + if (mRemoteId == remoteId && mSetUpPINCode == payload.setUpPINCode && mConnectionType == commission && + mDiscoveryType == discoveryType) + { + NotifyCommissionableDeviceDiscovered(resolutionData.Value()); + return CHIP_NO_ERROR; + } + } + + mConnectionType = commission; + mDiscoveryType = discoveryType; + mRemoteId = remoteId; + mSetUpPINCode = payload.setUpPINCode; ResetDiscoveryState(); diff --git a/src/controller/SetUpCodePairer.h b/src/controller/SetUpCodePairer.h index b6a93f4eeedfc8..04177ec313182a 100644 --- a/src/controller/SetUpCodePairer.h +++ b/src/controller/SetUpCodePairer.h @@ -51,6 +51,7 @@ class DeviceCommissioner; class SetUpCodePairerParameters : public RendezvousParameters { public: + SetUpCodePairerParameters() = default; SetUpCodePairerParameters(const Dnssd::CommonResolutionData & data, size_t index); #if CONFIG_NETWORK_LAYER_BLE SetUpCodePairerParameters(BLE_CONNECTION_OBJECT connObj, bool connected = true); diff --git a/src/controller/java/AndroidOperationalCredentialsIssuer.cpp b/src/controller/java/AndroidOperationalCredentialsIssuer.cpp index 8d405396a03901..ddbf9052cd3f12 100644 --- a/src/controller/java/AndroidOperationalCredentialsIssuer.cpp +++ b/src/controller/java/AndroidOperationalCredentialsIssuer.cpp @@ -111,27 +111,14 @@ CHIP_ERROR AndroidOperationalCredentialsIssuer::GenerateNOCChainAfterValidation( // If root certificate not found in the storage, generate new root certificate. else { - ReturnErrorOnFailure(rcac_dn.AddAttribute_MatterRCACId(mIssuerId)); - - ChipLogProgress(Controller, "Generating RCAC"); - chip::Credentials::X509CertRequestParams rcac_request = { 0, mNow, mNow + mValidity, rcac_dn, rcac_dn }; - ReturnErrorOnFailure(NewRootX509Cert(rcac_request, mIssuer, rcac)); - - VerifyOrReturnError(CanCastTo(rcac.size()), CHIP_ERROR_INTERNAL); + ReturnErrorOnFailure(GenerateRootCertificate(mIssuer, mIssuerId, Optional(), mNow, mNow + mValidity, rcac)); PERSISTENT_KEY_OP(fabricId, kOperationalCredentialsRootCertificateStorage, key, ReturnErrorOnFailure(mStorage->SyncSetKeyValue(key, rcac.data(), static_cast(rcac.size())))); } icac.reduce_size(0); - ChipDN noc_dn; - ReturnErrorOnFailure(noc_dn.AddAttribute_MatterFabricId(fabricId)); - ReturnErrorOnFailure(noc_dn.AddAttribute_MatterNodeId(nodeId)); - ReturnErrorOnFailure(noc_dn.AddCATs(cats)); - - ChipLogProgress(Controller, "Generating NOC"); - chip::Credentials::X509CertRequestParams noc_request = { 1, mNow, mNow + mValidity, noc_dn, rcac_dn }; - return NewNodeOperationalX509Cert(noc_request, pubkey, mIssuer, noc); + return GenerateOperationalCertificate(mIssuer, rcac, pubkey, fabricId, nodeId, cats, mNow, mNow + mValidity, noc); } CHIP_ERROR AndroidOperationalCredentialsIssuer::GenerateNOCChain(const ByteSpan & csrElements, const ByteSpan & csrNonce, @@ -403,6 +390,75 @@ CHIP_ERROR AndroidOperationalCredentialsIssuer::LocalGenerateNOCChain(const Byte return CHIP_NO_ERROR; } +CHIP_ERROR AndroidOperationalCredentialsIssuer::GenerateRootCertificate(Crypto::P256Keypair & keypair, uint64_t issuerId, + Optional fabricId, uint32_t validityStart, + uint32_t validityEnd, MutableByteSpan & rcac) +{ + ChipDN rcac_dn; + ReturnErrorOnFailure(rcac_dn.AddAttribute_MatterRCACId(issuerId)); + + if (fabricId.HasValue()) + { + FabricId fabric = fabricId.Value(); + VerifyOrReturnError(IsValidFabricId(fabric), CHIP_ERROR_INVALID_ARGUMENT); + ReturnErrorOnFailure(rcac_dn.AddAttribute_MatterFabricId(fabric)); + } + + ChipLogProgress(Controller, "Generating RCAC"); + chip::Credentials::X509CertRequestParams rcac_request = { 0, validityStart, validityEnd, rcac_dn, rcac_dn }; + ReturnErrorOnFailure(NewRootX509Cert(rcac_request, keypair, rcac)); + + VerifyOrReturnError(CanCastTo(rcac.size()), CHIP_ERROR_INTERNAL); + + return CHIP_NO_ERROR; +} + +CHIP_ERROR AndroidOperationalCredentialsIssuer::GenerateIntermediateCertificate( + Crypto::P256Keypair & rootKeypair, const ByteSpan & rcac, const Crypto::P256PublicKey & intermediatePublicKey, + uint64_t issuerId, Optional fabricId, uint32_t validityStart, uint32_t validityEnd, MutableByteSpan & icac) +{ + ChipDN rcac_dn; + ReturnErrorOnFailure(ExtractSubjectDNFromX509Cert(rcac, rcac_dn)); + + ChipDN icac_dn; + ReturnErrorOnFailure(icac_dn.AddAttribute_MatterICACId(issuerId)); + + if (fabricId.HasValue()) + { + FabricId fabric = fabricId.Value(); + VerifyOrReturnError(IsValidFabricId(fabric), CHIP_ERROR_INVALID_ARGUMENT); + ReturnErrorOnFailure(icac_dn.AddAttribute_MatterFabricId(fabric)); + } + + ChipLogProgress(Controller, "Generating ICAC"); + chip::Credentials::X509CertRequestParams icac_request = { 0, validityStart, validityEnd, icac_dn, rcac_dn }; + ReturnErrorOnFailure(NewICAX509Cert(icac_request, intermediatePublicKey, rootKeypair, icac)); + + VerifyOrReturnError(CanCastTo(icac.size()), CHIP_ERROR_INTERNAL); + + return CHIP_NO_ERROR; +} + +CHIP_ERROR AndroidOperationalCredentialsIssuer::GenerateOperationalCertificate(Crypto::P256Keypair & signingKeypair, + const ByteSpan & signingCertificate, + const Crypto::P256PublicKey & operationalPublicKey, + FabricId fabricId, NodeId nodeId, + const chip::CATValues & cats, uint32_t validityStart, + uint32_t validityEnd, MutableByteSpan & noc) +{ + ChipDN rcac_dn; + ReturnErrorOnFailure(ExtractSubjectDNFromX509Cert(signingCertificate, rcac_dn)); + + ChipDN noc_dn; + ReturnErrorOnFailure(noc_dn.AddAttribute_MatterFabricId(fabricId)); + ReturnErrorOnFailure(noc_dn.AddAttribute_MatterNodeId(nodeId)); + ReturnErrorOnFailure(noc_dn.AddCATs(cats)); + + ChipLogProgress(Controller, "Generating NOC"); + chip::Credentials::X509CertRequestParams noc_request = { 1, validityStart, validityEnd, noc_dn, rcac_dn }; + return NewNodeOperationalX509Cert(noc_request, operationalPublicKey, signingKeypair, noc); +} + CHIP_ERROR N2J_CSRInfo(JNIEnv * env, jbyteArray nonce, jbyteArray elements, jbyteArray csrElementsSignature, jbyteArray csr, jobject & outCSRInfo) { diff --git a/src/controller/java/AndroidOperationalCredentialsIssuer.h b/src/controller/java/AndroidOperationalCredentialsIssuer.h index 11ca4a5c49d8df..f297a0bf3b2f57 100644 --- a/src/controller/java/AndroidOperationalCredentialsIssuer.h +++ b/src/controller/java/AndroidOperationalCredentialsIssuer.h @@ -95,6 +95,39 @@ class DLL_EXPORT AndroidOperationalCredentialsIssuer : public OperationalCredent const Crypto::P256PublicKey & pubkey, MutableByteSpan & rcac, MutableByteSpan & icac, MutableByteSpan & noc); + /** + * Create a root (self-signed) X.509 DER encoded certificate that has the + * right fields to be a valid Matter root certificate. + */ + static CHIP_ERROR GenerateRootCertificate(Crypto::P256Keypair & keypair, uint64_t issuerId, Optional fabricId, + uint32_t validityStart, uint32_t validityEnd, MutableByteSpan & rcac); + + /** + * Create an intermediate X.509 DER encoded certificate that has the + * right fields to be a valid Matter intermediate certificate. + */ + static CHIP_ERROR GenerateIntermediateCertificate(Crypto::P256Keypair & rootKeypair, const ByteSpan & rcac, + const Crypto::P256PublicKey & intermediatePublicKey, uint64_t issuerId, + Optional fabricId, uint32_t validityStart, uint32_t validityEnd, + MutableByteSpan & icac); + + /** + * Create an X.509 DER encoded certificate that has the + * right fields to be a valid Matter operational certificate. + * + * signingKeypair and signingCertificate are the root or intermediate that is + * signing the operational certificate. + * + * cats may be null to indicate no CASE Authenticated Tags + * should be used. If cats is not null, it must contain at most + * 3 numbers, which are expected to be 32-bit unsigned Case Authenticated Tag + * values. + */ + static CHIP_ERROR GenerateOperationalCertificate(Crypto::P256Keypair & signingKeypair, const ByteSpan & signingCertificate, + const Crypto::P256PublicKey & operationalPublicKey, FabricId fabricId, + NodeId nodeId, const chip::CATValues & cats, uint32_t validityStart, + uint32_t validityEnd, MutableByteSpan & noc); + private: CHIP_ERROR CallbackGenerateNOCChain(const ByteSpan & csrElements, const ByteSpan & csrNonce, const ByteSpan & attestationSignature, const ByteSpan & attestationChallenge, diff --git a/src/controller/java/CHIPDeviceController-JNI.cpp b/src/controller/java/CHIPDeviceController-JNI.cpp index fd87516e19dd0a..1e6fedc01327d1 100644 --- a/src/controller/java/CHIPDeviceController-JNI.cpp +++ b/src/controller/java/CHIPDeviceController-JNI.cpp @@ -840,6 +840,269 @@ JNI_METHOD(void, updateCommissioningNetworkCredentials) } } +jint GetCalendarFieldID(JNIEnv * env, const char * method) +{ + jclass calendarCls = env->FindClass("java/util/Calendar"); + jfieldID fieldID = env->GetStaticFieldID(calendarCls, method, "I"); + return env->GetStaticIntField(calendarCls, fieldID); +} + +CHIP_ERROR GetEpochTime(JNIEnv * env, jobject calendar, uint32_t & epochTime) +{ + using namespace ASN1; + ASN1UniversalTime universalTime; + + jmethodID getMethod = nullptr; + + jint yearID = GetCalendarFieldID(env, "YEAR"); + jint monthID = GetCalendarFieldID(env, "MONTH"); + jint dayID = GetCalendarFieldID(env, "DAY_OF_MONTH"); + jint hourID = GetCalendarFieldID(env, "HOUR_OF_DAY"); + jint minuteID = GetCalendarFieldID(env, "MINUTE"); + jint secondID = GetCalendarFieldID(env, "SECOND"); + + if (calendar == nullptr) + { + return CHIP_ERROR_INVALID_ARGUMENT; + } + + ReturnErrorOnFailure(JniReferences::GetInstance().FindMethod(env, calendar, "get", "(I)I", &getMethod)); + + universalTime.Year = static_cast(env->CallIntMethod(calendar, getMethod, yearID)); + // The first month of the year in the Gregorian and Julian calendars is JANUARY which is 0. See detailed in + // https://docs.oracle.com/javase/8/docs/api/java/util/Calendar.html#MONTH + universalTime.Month = static_cast(env->CallIntMethod(calendar, getMethod, monthID)) + 1; + universalTime.Day = static_cast(env->CallIntMethod(calendar, getMethod, dayID)); + universalTime.Hour = static_cast(env->CallIntMethod(calendar, getMethod, hourID)); + universalTime.Minute = static_cast(env->CallIntMethod(calendar, getMethod, minuteID)); + universalTime.Second = static_cast(env->CallIntMethod(calendar, getMethod, secondID)); + + ReturnErrorOnFailure(ASN1ToChipEpochTime(universalTime, epochTime)); + + return CHIP_NO_ERROR; +} + +JNI_METHOD(jbyteArray, createRootCertificate) +(JNIEnv * env, jclass clazz, jobject jKeypair, jlong issuerId, jobject fabricId, jobject validityStart, jobject validityEnd) +{ +#ifdef JAVA_MATTER_CONTROLLER_TEST + return nullptr; +#else + CHIP_ERROR err = CHIP_NO_ERROR; + + uint32_t allocatedCertLength = chip::Credentials::kMaxDERCertLength; + chip::Platform::ScopedMemoryBuffer outBuf; + jbyteArray outRcac = nullptr; + CHIPP256KeypairBridge keypair; + Optional fabric = Optional(); + + VerifyOrExit(outBuf.Alloc(allocatedCertLength), err = CHIP_ERROR_NO_MEMORY); + + keypair.SetDelegate(jKeypair); + err = keypair.Initialize(Crypto::ECPKeyTarget::ECDSA); + SuccessOrExit(err); + + if (fabricId != nullptr) + { + jlong jfabricId = chip::JniReferences::GetInstance().LongToPrimitive(fabricId); + fabric = MakeOptional(static_cast(jfabricId)); + } + + { + MutableByteSpan rcac(outBuf.Get(), allocatedCertLength); + + uint32_t start; + uint32_t end; + + err = GetEpochTime(env, validityStart, start); + SuccessOrExit(err); + + err = GetEpochTime(env, validityEnd, end); + SuccessOrExit(err); + + err = AndroidOperationalCredentialsIssuer::GenerateRootCertificate(keypair, static_cast(issuerId), fabric, start, + end, rcac); + SuccessOrExit(err); + + err = JniReferences::GetInstance().N2J_ByteArray(env, rcac.data(), static_cast(rcac.size()), outRcac); + SuccessOrExit(err); + } +exit: + if (err != CHIP_NO_ERROR) + { + ChipLogError(Controller, "Failed to create Root Certificate. Err = %" CHIP_ERROR_FORMAT, err.Format()); + JniReferences::GetInstance().ThrowError(env, sChipDeviceControllerExceptionCls, err); + } + + return outRcac; +#endif +} + +JNI_METHOD(jbyteArray, createIntermediateCertificate) +(JNIEnv * env, jclass clazz, jobject rootKeypair, jbyteArray rootCertificate, jbyteArray intermediatePublicKey, jlong issuerId, + jobject fabricId, jobject validityStart, jobject validityEnd) +{ +#ifdef JAVA_MATTER_CONTROLLER_TEST + return nullptr; +#else + CHIP_ERROR err = CHIP_NO_ERROR; + + uint32_t allocatedCertLength = chip::Credentials::kMaxDERCertLength; + chip::Platform::ScopedMemoryBuffer outBuf; + jbyteArray outIcac = nullptr; + CHIPP256KeypairBridge keypair; + Optional fabric = Optional(); + + chip::JniByteArray jniRcac(env, rootCertificate); + chip::JniByteArray jnipublicKey(env, intermediatePublicKey); + + Credentials::P256PublicKeySpan publicKeySpan(reinterpret_cast(jnipublicKey.data())); + Crypto::P256PublicKey publicKey{ publicKeySpan }; + + VerifyOrExit(outBuf.Alloc(allocatedCertLength), err = CHIP_ERROR_NO_MEMORY); + + keypair.SetDelegate(rootKeypair); + err = keypair.Initialize(Crypto::ECPKeyTarget::ECDSA); + SuccessOrExit(err); + + if (fabricId != nullptr) + { + jlong jfabricId = chip::JniReferences::GetInstance().LongToPrimitive(fabricId); + fabric = MakeOptional(static_cast(jfabricId)); + } + + { + MutableByteSpan icac(outBuf.Get(), allocatedCertLength); + + uint32_t start; + uint32_t end; + + err = GetEpochTime(env, validityStart, start); + SuccessOrExit(err); + + err = GetEpochTime(env, validityEnd, end); + SuccessOrExit(err); + + err = AndroidOperationalCredentialsIssuer::GenerateIntermediateCertificate( + keypair, jniRcac.byteSpan(), publicKey, static_cast(issuerId), fabric, start, end, icac); + SuccessOrExit(err); + + ChipLogByteSpan(Controller, icac); + + err = JniReferences::GetInstance().N2J_ByteArray(env, icac.data(), static_cast(icac.size()), outIcac); + SuccessOrExit(err); + } +exit: + if (err != CHIP_NO_ERROR) + { + ChipLogError(Controller, "Failed to create Intermediate Certificate. Err = %" CHIP_ERROR_FORMAT, err.Format()); + JniReferences::GetInstance().ThrowError(env, sChipDeviceControllerExceptionCls, err); + } + + return outIcac; +#endif +} + +JNI_METHOD(jbyteArray, createOperationalCertificate) +(JNIEnv * env, jclass clazz, jobject signingKeypair, jbyteArray signingCertificate, jbyteArray operationalPublicKey, jlong fabricId, + jlong nodeId, jobject caseAuthenticatedTags, jobject validityStart, jobject validityEnd) +{ +#ifdef JAVA_MATTER_CONTROLLER_TEST + return nullptr; +#else + CHIP_ERROR err = CHIP_NO_ERROR; + + uint32_t allocatedCertLength = chip::Credentials::kMaxDERCertLength; + chip::Platform::ScopedMemoryBuffer outBuf; + jbyteArray outNoc = nullptr; + CHIPP256KeypairBridge keypair; + + chip::JniByteArray jniCert(env, signingCertificate); + chip::JniByteArray jnipublicKey(env, operationalPublicKey); + + Credentials::P256PublicKeySpan publicKeySpan(reinterpret_cast(jnipublicKey.data())); + Crypto::P256PublicKey publicKey{ publicKeySpan }; + + chip::CATValues cats = chip::kUndefinedCATs; + if (caseAuthenticatedTags != nullptr) + { + jint size; + JniReferences::GetInstance().GetListSize(caseAuthenticatedTags, size); + VerifyOrExit(static_cast(size) <= chip::kMaxSubjectCATAttributeCount, err = CHIP_ERROR_INVALID_ARGUMENT); + + for (jint i = 0; i < size; i++) + { + jobject cat = nullptr; + JniReferences::GetInstance().GetListItem(caseAuthenticatedTags, i, cat); + VerifyOrExit(cat != nullptr, err = CHIP_ERROR_INVALID_ARGUMENT); + cats.values[i] = static_cast(JniReferences::GetInstance().IntegerToPrimitive(cat)); + } + } + + VerifyOrExit(outBuf.Alloc(allocatedCertLength), err = CHIP_ERROR_NO_MEMORY); + + keypair.SetDelegate(signingKeypair); + err = keypair.Initialize(Crypto::ECPKeyTarget::ECDSA); + SuccessOrExit(err); + { + MutableByteSpan noc(outBuf.Get(), allocatedCertLength); + + uint32_t start; + uint32_t end; + + err = GetEpochTime(env, validityStart, start); + SuccessOrExit(err); + + err = GetEpochTime(env, validityEnd, end); + SuccessOrExit(err); + + err = AndroidOperationalCredentialsIssuer::GenerateOperationalCertificate( + keypair, jniCert.byteSpan(), publicKey, static_cast(fabricId), static_cast(nodeId), cats, start, + end, noc); + SuccessOrExit(err); + + ChipLogByteSpan(Controller, noc); + + err = JniReferences::GetInstance().N2J_ByteArray(env, noc.data(), static_cast(noc.size()), outNoc); + SuccessOrExit(err); + } +exit: + if (err != CHIP_NO_ERROR) + { + ChipLogError(Controller, "Failed to create Intermediate Certificate. Err = %" CHIP_ERROR_FORMAT, err.Format()); + JniReferences::GetInstance().ThrowError(env, sChipDeviceControllerExceptionCls, err); + } + + return outNoc; +#endif +} + +JNI_METHOD(jbyteArray, publicKeyFromCSR) +(JNIEnv * env, jclass clazz, jbyteArray certificateSigningRequest) +{ + jbyteArray outJbytes = nullptr; + + chip::JniByteArray jniCsr(env, certificateSigningRequest); + P256PublicKey publicKey; + CHIP_ERROR err = VerifyCertificateSigningRequest(jniCsr.byteSpan().data(), jniCsr.byteSpan().size(), publicKey); + if (err != CHIP_NO_ERROR) + { + ChipLogError(Controller, "publicKeyFromCSR: %" CHIP_ERROR_FORMAT, err.Format()); + return nullptr; + } + + err = JniReferences::GetInstance().N2J_ByteArray(env, publicKey.Bytes(), static_cast(publicKey.Length()), outJbytes); + SuccessOrExit(err); +exit: + if (err != CHIP_NO_ERROR) + { + ChipLogError(Controller, "Failed to publicKeyFromCSR. Err = %" CHIP_ERROR_FORMAT, err.Format()); + JniReferences::GetInstance().ThrowError(env, sChipDeviceControllerExceptionCls, err); + } + + return outJbytes; +} + JNI_METHOD(jbyteArray, convertX509CertToMatterCert) (JNIEnv * env, jobject self, jbyteArray x509Cert) { diff --git a/src/controller/java/src/chip/devicecontroller/ChipDeviceController.java b/src/controller/java/src/chip/devicecontroller/ChipDeviceController.java index 2551e08a136ef7..916f65fb270819 100644 --- a/src/controller/java/src/chip/devicecontroller/ChipDeviceController.java +++ b/src/controller/java/src/chip/devicecontroller/ChipDeviceController.java @@ -25,6 +25,7 @@ import chip.devicecontroller.model.ChipEventPath; import chip.devicecontroller.model.InvokeElement; import java.util.ArrayList; +import java.util.Calendar; import java.util.List; import java.util.Optional; import javax.annotation.Nullable; @@ -925,6 +926,99 @@ public void invoke( imTimeoutMs); } + /** Create a root (self-signed) X.509 DER encoded certificate */ + public static byte[] createRootCertificate( + KeypairDelegate keypair, long issuerId, @Nullable Long fabricId) { + // current time + Calendar start = Calendar.getInstance(); + Calendar end = Calendar.getInstance(); + // current time + 10 years + end.add(Calendar.YEAR, 10); + return createRootCertificate(keypair, issuerId, fabricId, start, end); + } + + public static native byte[] createRootCertificate( + KeypairDelegate keypair, + long issuerId, + @Nullable Long fabricId, + Calendar validityStart, + Calendar validityEnd); + + /** Create an intermediate X.509 DER encoded certificate */ + public static byte[] createIntermediateCertificate( + KeypairDelegate rootKeypair, + byte[] rootCertificate, + byte[] intermediatePublicKey, + long issuerId, + @Nullable Long fabricId) { + // current time + Calendar start = Calendar.getInstance(); + // current time + 10 years + Calendar end = Calendar.getInstance(); + end.add(Calendar.YEAR, 10); + return createIntermediateCertificate( + rootKeypair, rootCertificate, intermediatePublicKey, issuerId, fabricId, start, end); + } + + public static native byte[] createIntermediateCertificate( + KeypairDelegate rootKeypair, + byte[] rootCertificate, + byte[] intermediatePublicKey, + long issuerId, + @Nullable Long fabricId, + Calendar validityStart, + Calendar validityEnd); + + /** + * Create an X.509 DER encoded certificate that has the right fields to be a valid Matter + * operational certificate. + * + *

signingKeypair and signingCertificate are the root or intermediate that is signing the + * operational certificate. + * + *

caseAuthenticatedTags may be null to indicate no CASE Authenticated Tags should be used. If + * caseAuthenticatedTags is not null, it must contain at most 3 numbers, which are expected to be + * 32-bit unsigned Case Authenticated Tag values. + */ + public static byte[] createOperationalCertificate( + KeypairDelegate signingKeypair, + byte[] signingCertificate, + byte[] operationalPublicKey, + long fabricId, + long nodeId, + List caseAuthenticatedTags) { + // current time + Calendar start = Calendar.getInstance(); + // current time + 10 years + Calendar end = Calendar.getInstance(); + end.add(Calendar.YEAR, 10); + return createOperationalCertificate( + signingKeypair, + signingCertificate, + operationalPublicKey, + fabricId, + nodeId, + caseAuthenticatedTags, + start, + end); + } + + public static native byte[] createOperationalCertificate( + KeypairDelegate signingKeypair, + byte[] signingCertificate, + byte[] operationalPublicKey, + long fabricId, + long nodeId, + List caseAuthenticatedTags, + Calendar validityStart, + Calendar validityEnd); + + /** + * Extract the public key from the given PKCS#10 certificate signing request. This is the public + * key that a certificate issued in response to the request would need to have. + */ + public static native byte[] publicKeyFromCSR(byte[] csr); + /** * Converts a given X.509v3 certificate into a Matter certificate. * diff --git a/src/controller/python/BUILD.gn b/src/controller/python/BUILD.gn index 07f288830a3f7d..c76c64c65d7df4 100644 --- a/src/controller/python/BUILD.gn +++ b/src/controller/python/BUILD.gn @@ -360,6 +360,7 @@ chip_python_wheel_action("chip-clusters") { "chip/clusters/Types.py", "chip/clusters/enum.py", "chip/tlv/__init__.py", + "chip/tlv/tlvlist.py", ] }, { diff --git a/src/controller/python/ChipDeviceController-ScriptDevicePairingDelegate.cpp b/src/controller/python/ChipDeviceController-ScriptDevicePairingDelegate.cpp index 66f461d0071b3c..b1e7fa98c9df1d 100644 --- a/src/controller/python/ChipDeviceController-ScriptDevicePairingDelegate.cpp +++ b/src/controller/python/ChipDeviceController-ScriptDevicePairingDelegate.cpp @@ -20,6 +20,7 @@ #include "ChipDeviceController-ScriptDevicePairingDelegate.h" #include "lib/support/TypeTraits.h" #include +#include #include namespace chip { @@ -133,11 +134,15 @@ void ScriptDevicePairingDelegate::OnOpenCommissioningWindow(NodeId deviceId, CHI { if (mOnWindowOpenCompleteCallback != nullptr) { - QRCodeSetupPayloadGenerator generator(payload); - std::string code; - generator.payloadBase38Representation(code); - ChipLogProgress(Zcl, "code = %s", code.c_str()); - mOnWindowOpenCompleteCallback(deviceId, payload.setUpPINCode, code.c_str(), ToPyChipError(status)); + std::string setupManualCode; + std::string setupQRCode; + + ManualSetupPayloadGenerator(payload).payloadDecimalStringRepresentation(setupManualCode); + QRCodeSetupPayloadGenerator(payload).payloadBase38Representation(setupQRCode); + ChipLogProgress(Zcl, "SetupManualCode = %s", setupManualCode.c_str()); + ChipLogProgress(Zcl, "SetupQRCode = %s", setupQRCode.c_str()); + mOnWindowOpenCompleteCallback(deviceId, payload.setUpPINCode, setupManualCode.c_str(), setupQRCode.c_str(), + ToPyChipError(status)); } if (mWindowOpener != nullptr) { diff --git a/src/controller/python/ChipDeviceController-ScriptDevicePairingDelegate.h b/src/controller/python/ChipDeviceController-ScriptDevicePairingDelegate.h index 2bfd50b37436a8..b93ba94f532270 100644 --- a/src/controller/python/ChipDeviceController-ScriptDevicePairingDelegate.h +++ b/src/controller/python/ChipDeviceController-ScriptDevicePairingDelegate.h @@ -35,8 +35,8 @@ namespace Controller { extern "C" { typedef void (*DevicePairingDelegate_OnPairingCompleteFunct)(PyChipError err); typedef void (*DevicePairingDelegate_OnCommissioningCompleteFunct)(NodeId nodeId, PyChipError err); -typedef void (*DevicePairingDelegate_OnWindowOpenCompleteFunct)(NodeId nodeId, uint32_t setupPinCode, const char * setupCode, - PyChipError err); +typedef void (*DevicePairingDelegate_OnWindowOpenCompleteFunct)(NodeId nodeId, uint32_t setupPinCode, const char * manualCode, + const char * setupQRCode, PyChipError err); // Used for testing by OpCredsBinding typedef void (*DevicePairingDelegate_OnCommissioningSuccessFunct)(PeerId peerId); diff --git a/src/controller/python/chip/ChipDeviceCtrl.py b/src/controller/python/chip/ChipDeviceCtrl.py index d9f3eab9a5a6a5..401a356d7556ca 100644 --- a/src/controller/python/chip/ChipDeviceCtrl.py +++ b/src/controller/python/chip/ChipDeviceCtrl.py @@ -57,14 +57,17 @@ from .interaction_model import delegate as im from .native import PyChipError -__all__ = ["ChipDeviceController"] +__all__ = ["ChipDeviceController", "CommissioningParameters"] + +# Defined in $CHIP_ROOT/src/lib/core/CHIPError.h +CHIP_ERROR_TIMEOUT: int = 50 _DevicePairingDelegate_OnPairingCompleteFunct = CFUNCTYPE(None, PyChipError) _DeviceUnpairingCompleteFunct = CFUNCTYPE(None, c_uint64, PyChipError) _DevicePairingDelegate_OnCommissioningCompleteFunct = CFUNCTYPE( None, c_uint64, PyChipError) _DevicePairingDelegate_OnOpenWindowCompleteFunct = CFUNCTYPE( - None, c_uint64, c_uint32, c_char_p, PyChipError) + None, c_uint64, c_uint32, c_char_p, c_char_p, PyChipError) _DevicePairingDelegate_OnCommissioningStatusUpdateFunct = CFUNCTYPE( None, c_uint64, c_uint8, PyChipError) # void (*)(Device *, CHIP_ERROR). @@ -79,6 +82,13 @@ _ChipDeviceController_IterateDiscoveredCommissionableNodesFunct = CFUNCTYPE(None, c_char_p, c_size_t) +@dataclass +class CommissioningParameters: + setupPinCode: int + setupManualCode: str + setupQRCode: str + + @dataclass class NOCChain: nocBytes: bytes @@ -89,7 +99,8 @@ class NOCChain: @_IssueNOCChainCallbackPythonCallbackFunct -def _IssueNOCChainCallbackPythonCallback(devCtrl, status: PyChipError, noc: c_void_p, nocLen: int, icac: c_void_p, icacLen: int, rcac: c_void_p, rcacLen: int, ipk: c_void_p, ipkLen: int, adminSubject: int): +def _IssueNOCChainCallbackPythonCallback(devCtrl, status: PyChipError, noc: c_void_p, nocLen: int, icac: c_void_p, + icacLen: int, rcac: c_void_p, rcacLen: int, ipk: c_void_p, ipkLen: int, adminSubject: int): nocChain = NOCChain(None, None, None, None, 0) if status.is_success: nocBytes = None @@ -135,13 +146,13 @@ class CommissionableNode(discovery.CommissionableNode): def SetDeviceController(self, devCtrl: 'ChipDeviceController'): self._devCtrl = devCtrl - def Commission(self, nodeId: int, setupPinCode: int): + def Commission(self, nodeId: int, setupPinCode: int) -> PyChipError: ''' Commission the device using the device controller discovered this device. nodeId: The nodeId commissioned to the device setupPinCode: The setup pin code of the device ''' - self._devCtrl.CommissionOnNetwork( + return self._devCtrl.CommissionOnNetwork( nodeId, setupPinCode, filterType=discovery.FilterType.INSTANCE_NAME, filter=self.instanceName) def __rich_repr__(self): @@ -256,10 +267,12 @@ def HandleCommissioningComplete(nodeid, err): self._ChipStack.commissioningCompleteEvent.set() self._ChipStack.completeEvent.set() - def HandleOpenWindowComplete(nodeid: int, setupPinCode: int, setupCode: str, err: PyChipError) -> None: + def HandleOpenWindowComplete(nodeid: int, setupPinCode: int, setupManualCode: str, + setupQRCode: str, err: PyChipError) -> None: if err.is_success: print("Open Commissioning Window complete setting nodeid {} pincode to {}".format(nodeid, setupPinCode)) - self._ChipStack.openCommissioningWindowPincode[nodeid] = (setupPinCode, setupCode) + self._ChipStack.openCommissioningWindowPincode[nodeid] = CommissioningParameters( + setupPinCode=setupPinCode, setupManualCode=setupManualCode.decode(), setupQRCode=setupQRCode.decode()) else: print("Failed to open commissioning window: {}".format(err)) @@ -354,7 +367,7 @@ def Shutdown(self): C++ constructor instance in the SDK. ''' if (self._isActive): - if self.devCtrl != None: + if self.devCtrl is not None: self._ChipStack.Call( lambda: self._dmLib.pychip_DeviceController_DeleteDeviceController( self.devCtrl) @@ -399,7 +412,7 @@ def IsConnected(self): self.devCtrl) ) - def ConnectBLE(self, discriminator, setupPinCode, nodeid): + def ConnectBLE(self, discriminator, setupPinCode, nodeid) -> PyChipError: self.CheckIsActive() self._ChipStack.commissioningCompleteEvent.clear() @@ -411,8 +424,8 @@ def ConnectBLE(self, discriminator, setupPinCode, nodeid): ).raise_on_error() if not self._ChipStack.commissioningCompleteEvent.isSet(): # Error 50 is a timeout - return False - return self._ChipStack.commissioningEventRes.is_success + return PyChipError(CHIP_ERROR_TIMEOUT) + return self._ChipStack.commissioningEventRes def UnpairDevice(self, nodeid: int): self.CheckIsActive() @@ -521,7 +534,8 @@ def GetAddressAndPort(self, nodeid): return (address.value.decode(), port.value) if error == 0 else None - def DiscoverCommissionableNodes(self, filterType: discovery.FilterType = discovery.FilterType.NONE, filter: typing.Any = None, stopOnFirst: bool = False, timeoutSecond: int = 5) -> typing.Union[None, CommissionableNode, typing.List[CommissionableNode]]: + def DiscoverCommissionableNodes(self, filterType: discovery.FilterType = discovery.FilterType.NONE, filter: typing.Any = None, + stopOnFirst: bool = False, timeoutSecond: int = 5) -> typing.Union[None, CommissionableNode, typing.List[CommissionableNode]]: ''' Discover commissionable nodes via DNS-SD with specified filters. Supported filters are: @@ -550,7 +564,8 @@ def DiscoverCommissionableNodes(self, filterType: discovery.FilterType = discove if stopOnFirst: target = time.time() + timeoutSecond while time.time() < target: - if self._ChipStack.Call(lambda: self._dmLib.pychip_DeviceController_HasDiscoveredCommissionableNode(self.devCtrl)): + if self._ChipStack.Call( + lambda: self._dmLib.pychip_DeviceController_HasDiscoveredCommissionableNode(self.devCtrl)): break time.sleep(0.1) else: @@ -652,7 +667,8 @@ def DiscoverAllCommissioning(self): self.devCtrl) ).raise_on_error() - def OpenCommissioningWindow(self, nodeid: int, timeout: int, iteration: int, discriminator: int, option: int) -> (int, str): + def OpenCommissioningWindow(self, nodeid: int, timeout: int, iteration: int, + discriminator: int, option: int) -> CommissioningParameters: self.CheckIsActive() self._ChipStack.CallAsync( lambda: self._dmLib.pychip_DeviceController_OpenCommissioningWindow( @@ -831,7 +847,8 @@ async def WriteAttribute(self, nodeid: int, attributes: typing.List[typing.Tuple future, eventLoop, device.deviceProxy, attrs, timedRequestTimeoutMs=timedRequestTimeoutMs, interactionTimeoutMs=interactionTimeoutMs, busyWaitMs=busyWaitMs).raise_on_error() return await future - def WriteGroupAttribute(self, groupid: int, attributes: typing.List[typing.Tuple[ClusterObjects.ClusterAttributeDescriptor, int]], busyWaitMs: typing.Union[None, int] = None): + def WriteGroupAttribute( + self, groupid: int, attributes: typing.List[typing.Tuple[ClusterObjects.ClusterAttributeDescriptor, int]], busyWaitMs: typing.Union[None, int] = None): ''' Write a list of attributes on a target group. @@ -878,8 +895,8 @@ def _parseAttributePathTuple(self, pathTuple: typing.Union[ if pathTuple == ('*') or pathTuple == (): # Wildcard pass - elif type(pathTuple) is not tuple: - if type(pathTuple) is int: + elif not isinstance(pathTuple, tuple): + if isinstance(pathTuple, int): endpoint = pathTuple elif issubclass(pathTuple, ClusterObjects.Cluster): cluster = pathTuple @@ -934,9 +951,9 @@ def _parseEventPathTuple(self, pathTuple: typing.Union[ if pathTuple in [('*'), ()]: # Wildcard pass - elif type(pathTuple) is not tuple: + elif not isinstance(pathTuple, tuple): print(type(pathTuple)) - if type(pathTuple) is int: + if isinstance(pathTuple, int): endpoint = pathTuple elif issubclass(pathTuple, ClusterObjects.Cluster): cluster = pathTuple @@ -1133,7 +1150,7 @@ def ZCLSend(self, cluster, command, nodeid, endpoint, groupid, args, blocking=Fa try: req = eval( f"GeneratedObjects.{cluster}.Commands.{command}")(**args) - except: + except BaseException: raise UnknownCommand(cluster, command) try: res = asyncio.run(self.SendCommand(nodeid, endpoint, req)) @@ -1151,21 +1168,22 @@ def ZCLReadAttribute(self, cluster, attribute, nodeid, endpoint, groupid, blocki try: attributeType = eval( f"GeneratedObjects.{cluster}.Attributes.{attribute}") - except: + except BaseException: raise UnknownAttribute(cluster, attribute) result = asyncio.run(self.ReadAttribute( nodeid, [(endpoint, attributeType)])) path = ClusterAttribute.AttributePath( EndpointId=endpoint, Attribute=attributeType) - return im.AttributeReadResult(path=im.AttributePath(nodeId=nodeid, endpointId=path.EndpointId, clusterId=path.ClusterId, attributeId=path.AttributeId), status=0, value=result[endpoint][clusterType][attributeType], dataVersion=result[endpoint][clusterType][ClusterAttribute.DataVersion]) + return im.AttributeReadResult(path=im.AttributePath(nodeId=nodeid, endpointId=path.EndpointId, clusterId=path.ClusterId, attributeId=path.AttributeId), + status=0, value=result[endpoint][clusterType][attributeType], dataVersion=result[endpoint][clusterType][ClusterAttribute.DataVersion]) def ZCLWriteAttribute(self, cluster: str, attribute: str, nodeid, endpoint, groupid, value, dataVersion=0, blocking=True): req = None try: req = eval( f"GeneratedObjects.{cluster}.Attributes.{attribute}")(value) - except: + except BaseException: raise UnknownAttribute(cluster, attribute) return asyncio.run(self.WriteAttribute(nodeid, [(endpoint, req, dataVersion)])) @@ -1176,7 +1194,7 @@ def ZCLSubscribeAttribute(self, cluster, attribute, nodeid, endpoint, minInterva req = None try: req = eval(f"GeneratedObjects.{cluster}.Attributes.{attribute}") - except: + except BaseException: raise UnknownAttribute(cluster, attribute) return asyncio.run(self.ReadAttribute(nodeid, [(endpoint, req)], None, False, reportInterval=(minInterval, maxInterval))) @@ -1430,7 +1448,8 @@ class ChipDeviceController(ChipDeviceControllerBase): TODO: This class contains DEPRECATED functions, we should update the test scripts to avoid the usage of those functions. ''' - def __init__(self, opCredsContext: ctypes.c_void_p, fabricId: int, nodeId: int, adminVendorId: int, catTags: typing.List[int] = [], paaTrustStorePath: str = "", useTestCommissioner: bool = False, fabricAdmin: FabricAdmin = None, name: str = None, keypair: p256keypair.P256Keypair = None): + def __init__(self, opCredsContext: ctypes.c_void_p, fabricId: int, nodeId: int, adminVendorId: int, catTags: typing.List[int] = [ + ], paaTrustStorePath: str = "", useTestCommissioner: bool = False, fabricAdmin: FabricAdmin = None, name: str = None, keypair: p256keypair.P256Keypair = None): super().__init__( name or f"caIndex({fabricAdmin.caIndex:x})/fabricId(0x{fabricId:016X})/nodeId(0x{nodeId:016X})" @@ -1472,7 +1491,7 @@ def caIndex(self) -> int: def fabricAdmin(self) -> FabricAdmin: return self._fabricAdmin - def Commission(self, nodeid) -> bool: + def Commission(self, nodeid) -> PyChipError: ''' Start the auto-commissioning process on a node after establishing a PASE connection. This function is intended to be used in conjunction with `EstablishPASESessionBLE` or @@ -1492,15 +1511,18 @@ def Commission(self, nodeid) -> bool: lambda: self._dmLib.pychip_DeviceController_Commission( self.devCtrl, nodeid) ) - return (self._ChipStack.commissioningCompleteEvent.isSet() and (self._ChipStack.commissioningEventRes == 0)) + if not self._ChipStack.commissioningCompleteEvent.isSet(): + # Error 50 is a timeout + return PyChipError(CHIP_ERROR_TIMEOUT) + return self._ChipStack.commissioningEventRes - def CommissionThread(self, discriminator, setupPinCode, nodeId, threadOperationalDataset: bytes): + def CommissionThread(self, discriminator, setupPinCode, nodeId, threadOperationalDataset: bytes) -> PyChipError: ''' Commissions a Thread device over BLE ''' self.SetThreadOperationalDataset(threadOperationalDataset) return self.ConnectBLE(discriminator, setupPinCode, nodeId) - def CommissionWiFi(self, discriminator, setupPinCode, nodeId, ssid: str, credentials: str): + def CommissionWiFi(self, discriminator, setupPinCode, nodeId, ssid: str, credentials: str) -> PyChipError: ''' Commissions a WiFi device over BLE ''' self.SetWiFiCredentials(ssid, credentials) @@ -1522,7 +1544,8 @@ def SetThreadOperationalDataset(self, threadOperationalDataset): threadOperationalDataset, len(threadOperationalDataset)) ).raise_on_error() - def CommissionOnNetwork(self, nodeId: int, setupPinCode: int, filterType: DiscoveryFilterType = DiscoveryFilterType.NONE, filter: typing.Any = None): + def CommissionOnNetwork(self, nodeId: int, setupPinCode: int, + filterType: DiscoveryFilterType = DiscoveryFilterType.NONE, filter: typing.Any = None) -> PyChipError: ''' Does the routine for OnNetworkCommissioning, with a filter for mDNS discovery. Supported filters are: @@ -1556,10 +1579,11 @@ def CommissionOnNetwork(self, nodeId: int, setupPinCode: int, filterType: Discov self.devCtrl, nodeId, setupPinCode, int(filterType), str(filter).encode("utf-8") + b"\x00" if filter is not None else None) ) if not self._ChipStack.commissioningCompleteEvent.isSet(): - return False, -1 - return self._ChipStack.commissioningEventRes == 0, self._ChipStack.commissioningEventRes + # Error 50 is a timeout + return PyChipError(CHIP_ERROR_TIMEOUT) + return self._ChipStack.commissioningEventRes - def CommissionWithCode(self, setupPayload: str, nodeid: int): + def CommissionWithCode(self, setupPayload: str, nodeid: int) -> PyChipError: self.CheckIsActive() setupPayload = setupPayload.encode() + b'\0' @@ -1575,10 +1599,11 @@ def CommissionWithCode(self, setupPayload: str, nodeid: int): self.devCtrl, setupPayload, nodeid) ) if not self._ChipStack.commissioningCompleteEvent.isSet(): - return False - return self._ChipStack.commissioningEventRes == 0 + # Error 50 is a timeout + return PyChipError(CHIP_ERROR_TIMEOUT) + return self._ChipStack.commissioningEventRes - def CommissionIP(self, ipaddr: str, setupPinCode: int, nodeid: int): + def CommissionIP(self, ipaddr: str, setupPinCode: int, nodeid: int) -> PyChipError: """ DEPRECATED, DO NOT USE! Use `CommissionOnNetwork` or `CommissionWithCode` """ self.CheckIsActive() @@ -1593,8 +1618,9 @@ def CommissionIP(self, ipaddr: str, setupPinCode: int, nodeid: int): self.devCtrl, ipaddr.encode("utf-8"), setupPinCode, nodeid) ) if not self._ChipStack.commissioningCompleteEvent.isSet(): - return False - return self._ChipStack.commissioningEventRes == 0 + # Error 50 is a timeout + return PyChipError(CHIP_ERROR_TIMEOUT) + return self._ChipStack.commissioningEventRes def IssueNOCChain(self, csr: Clusters.OperationalCredentials.Commands.CSRResponse, nodeId: int): """Issue an NOC chain using the associated OperationalCredentialsDelegate. @@ -1611,7 +1637,8 @@ class BareChipDeviceController(ChipDeviceControllerBase): ''' A bare device controller without AutoCommissioner support. ''' - def __init__(self, operationalKey: p256keypair.P256Keypair, noc: bytes, icac: typing.Union[bytes, None], rcac: bytes, ipk: typing.Union[bytes, None], adminVendorId: int, name: str = None): + def __init__(self, operationalKey: p256keypair.P256Keypair, noc: bytes, + icac: typing.Union[bytes, None], rcac: bytes, ipk: typing.Union[bytes, None], adminVendorId: int, name: str = None): '''Creates a controller without autocommissioner. The allocated controller uses the noc, icac, rcac and ipk instead of the default, diff --git a/src/controller/python/chip/native/__init__.py b/src/controller/python/chip/native/__init__.py index e83821242bf583..26e394e61fca6a 100644 --- a/src/controller/python/chip/native/__init__.py +++ b/src/controller/python/chip/native/__init__.py @@ -103,6 +103,9 @@ def __str__(self): GetLibraryHandle().pychip_FormatError(ctypes.pointer(self), buf, 256) return buf.value.decode() + def __bool__(self): + return self.is_success + def __eq__(self, other): if isinstance(other, int): return self.code == other diff --git a/src/controller/python/chip/tlv/__init__.py b/src/controller/python/chip/tlv/__init__.py index 6b22fbb8536299..a29704f5343ebd 100644 --- a/src/controller/python/chip/tlv/__init__.py +++ b/src/controller/python/chip/tlv/__init__.py @@ -32,6 +32,8 @@ from collections.abc import Mapping, Sequence from enum import Enum +from .tlvlist import TLVList + TLV_TYPE_SIGNED_INTEGER = 0x00 TLV_TYPE_UNSIGNED_INTEGER = 0x04 TLV_TYPE_BOOLEAN = 0x08 @@ -223,6 +225,11 @@ def put(self, tag, val): for containedTag, containedVal in val.items(): self.put(containedTag, containedVal) self.endContainer() + elif isinstance(val, TLVList): + self.startPath(tag) + for containedTag, containedVal in val: + self.put(containedTag, containedVal) + self.endContainer() elif isinstance(val, Sequence): self.startArray(tag) for containedVal in val: @@ -576,7 +583,7 @@ def _decodeVal(self, tlv, decoding): decoding["Array"] = [] self._get(tlv, decoding["Array"], decoding["value"]) elif decoding["type"] == "Path": - decoding["value"] = [] + decoding["value"] = TLVList() decoding["Path"] = [] self._get(tlv, decoding["Path"], decoding["value"]) elif decoding["type"] == "Null": @@ -682,6 +689,9 @@ def _get(self, tlv, decodings, out): if isinstance(out, Mapping): tag = decoding["tag"] if decoding["tag"] is not None else "Any" out[tag] = decoding["value"] + elif isinstance(out, TLVList): + tag = decoding["tag"] if decoding["tag"] is not None else None + out.append(tag, decoding["value"]) else: out.append(decoding["value"]) else: diff --git a/src/controller/python/chip/tlv/tlvlist.py b/src/controller/python/chip/tlv/tlvlist.py new file mode 100644 index 00000000000000..a9afaa3e2bb26e --- /dev/null +++ b/src/controller/python/chip/tlv/tlvlist.py @@ -0,0 +1,175 @@ +#!/usr/bin/env python3 +# coding=utf-8 + +# +# Copyright (c) 2023 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 dataclasses +import enum +from typing import Any, Iterator, List, Tuple, Union + + +class TLVList: + """Represents a list in CHIP TLV. + + A TLVList can be constructed from a `list` of tuples of tag and value. `None` stands for "anonymous tag". + + e.g. + ``` + l = TLVList([(1, 'a'), (2, 'b'), (None, 'c')]) + ``` + + Constructs a list of three items, tag 1 is 'a', tag 2 is 'b' and with an anonymous item 'c'. + + Since TLVLists are ordered, it is meanful to iterate over an list: + + e.g. + ``` + for tag, val in l: + print(f"tag={tag}, val={val}") + ``` + + Outputs: + ``` + tag=1, val=a + tag=2, val=b + tag=None, val=c + ``` + + One can also append items into an list: + + e.g. + ``` + l.append(3, 'd') + ``` + + The content of `l` will be `[(1, 'a'), (2, 'b'), (None, 'c'), (3, 'd')]` + + One can access an item in the list via the tag. + + e.g. + ``` + val = l[1] + # val is 'a' + ``` + + It is also possible to get an item via the index since it is ordered: + + e.g. + ``` + tag, val = l[TLVList.IndexMethod.Tag:2] + # tag is None, val is 'c' + ``` + """ + + @dataclasses.dataclass + class TLVListItem: + tag: Union[None, int] + value: Any + + def as_tuple(self): + return (self.tag, self.value) + + def as_rich_repr_tuple(self): + if self.tag is None: + return "Anonymous", repr(self.value) + else: + return str(self.tag), repr(self.value) + + def __repr__(self): + if self.tag is None: + return "Anonymous: " + repr(self.value) + else: + return str(self.tag) + ": " + repr(self.value) + + def __rich_repr__(self): + yield self.as_rich_repr_tuple() + + class IndexMethod(enum.Enum): + Index = 0 + Tag = 1 + + class Iterator: + def __init__(self, iter: Iterator): + self._iterator = iter + + def __iter__(self): + return self + + def __next__(self): + res = next(self._iterator) + return res.tag, res.value + + def __init__(self, items: List[Tuple[Union[int, None], Any]] = []): + """Constructs a TLVList. + + items: A list of tuples for the tag and value for the items in the TLVList. + """ + self._data: List[TLVList.TLVListItem] = [] + + for tag, val in items: + self.append(tag, val) + + def _get_item_by_tag(self, tag) -> Any: + if not isinstance(tag, int): + raise ValueError("Tag should be a integer for non-anonymous fields.") + for data in self._data: + if data.tag == tag: + return data.value + raise KeyError(f"Tag {tag} not found in the list.") + + def __getitem__(self, access) -> Any: + """Gets a item in the list by the tag or the index. + + Examples: + ``` + tlv_list[1] # returns the item in the list with tag `1` + tlv_list[TLVList.IndexMethod.Tag:2] # returns the item in the list with tag `2` + tlv_list[TLVList.IndexMethod.Index:0] # returns the tag and value of the first item in the list + ``` + """ + if isinstance(access, slice): + tag, index = access.start, access.stop + if tag == TLVList.IndexMethod.Tag: + return self._get_item_by_tag(index) + elif tag == TLVList.IndexMethod.Index: + return self._data[index].as_tuple() + raise ValueError("Method should be TLVList.IndexMethod.Tag or TLVList.IndexMethod.Index") + elif isinstance(access, int): + return self._get_item_by_tag(access) + raise ValueError("Invalid access method") + + def append(self, tag: Union[None, int], value: Any) -> None: + """Appends an item to the list.""" + if (tag is not None) and (not isinstance(tag, int)): + raise KeyError(f"Tag should be a integer or none for anonymous tag, {type(tag)} got") + self._data.append(TLVList.TLVListItem(tag, value)) + + def __repr__(self): + return "TLVList" + repr(self._data) + + def __rich_repr__(self): + for items in self._data: + yield items.as_rich_repr_tuple() + + def __iter__(self) -> """TLVList.Iterator""": + return TLVList.Iterator(iter(self._data)) + + def __eq__(self, rhs: "TLVList") -> bool: + if not isinstance(rhs, TLVList): + return False + return self._data == rhs._data diff --git a/src/controller/python/test/test_scripts/base.py b/src/controller/python/test/test_scripts/base.py index 57a757401eeec5..8ab30f8f6f5686 100644 --- a/src/controller/python/test/test_scripts/base.py +++ b/src/controller/python/test/test_scripts/base.py @@ -130,14 +130,12 @@ def CheckEnableBeforeRun(*args, **kwargs): def configurable_tests(): - res = [v for v in _configurable_test_sets] - res.sort() + res = sorted([v for v in _configurable_test_sets]) return res def configurable_test_cases(): - res = [v for v in _configurable_tests] - res.sort() + res = sorted([v for v in _configurable_tests]) return res @@ -190,7 +188,8 @@ def assertValueEqual(self, expected): class BaseTestHelper: - def __init__(self, nodeid: int, paaTrustStorePath: str, testCommissioner: bool = False, keypair: p256keypair.P256Keypair = None): + def __init__(self, nodeid: int, paaTrustStorePath: str, testCommissioner: bool = False, + keypair: p256keypair.P256Keypair = None): chip.native.Init() self.chipStack = ChipStack('/tmp/repl_storage.json') @@ -250,16 +249,16 @@ async def TestRevokeCommissioningWindow(self, ip: str, setuppin: int, nodeid: in nodeid, 0, Clusters.GeneralCommissioning.Commands.ArmFailSafe(expiryLengthSeconds=180, breadcrumb=0)) await self.devCtrl.SendCommand( - nodeid, 0, Clusters.AdministratorCommissioning.Commands.RevokeCommissioning(), timedRequestTimeoutMs=10000) + nodeid, 0, Clusters.AdministratorCommissioning.Commands.RevokeCommissioning(), timedRequestTimeoutMs=10000) await self.devCtrl.SendCommand( nodeid, 0, Clusters.AdministratorCommissioning.Commands.OpenBasicCommissioningWindow(180), timedRequestTimeoutMs=10000) await self.devCtrl.SendCommand( - nodeid, 0, Clusters.AdministratorCommissioning.Commands.RevokeCommissioning(), timedRequestTimeoutMs=10000) + nodeid, 0, Clusters.AdministratorCommissioning.Commands.RevokeCommissioning(), timedRequestTimeoutMs=10000) return True def TestEnhancedCommissioningWindow(self, ip: str, nodeid: int): - pin, code = self.devCtrl.OpenCommissioningWindow(nodeid=nodeid, timeout=600, iteration=10000, discriminator=3840, option=1) - return self.TestPaseOnly(ip=ip, nodeid=nodeid, setuppin=pin, devCtrl=self.devCtrl2) + params = self.devCtrl.OpenCommissioningWindow(nodeid=nodeid, timeout=600, iteration=10000, discriminator=3840, option=1) + return self.TestPaseOnly(ip=ip, nodeid=nodeid, setuppin=params.setupPinCode, devCtrl=self.devCtrl2) def TestPaseOnly(self, ip: str, setuppin: int, nodeid: int, devCtrl=None): if devCtrl is None: @@ -461,9 +460,9 @@ async def TestControllerCATValues(self, nodeid: int): # Read out the attribute again - this time, it should succeed. res = await newControllers[0].ReadAttribute(nodeid=nodeid, attributes=[(0, Clusters.AccessControl.Attributes.Acl)]) - if (type(res[0][ + if (not isinstance(res[0][ Clusters.AccessControl][ - Clusters.AccessControl.Attributes.Acl][0]) != Clusters.AccessControl.Structs.AccessControlEntryStruct): + Clusters.AccessControl.Attributes.Acl][0], Clusters.AccessControl.Structs.AccessControlEntryStruct)): self.logger.error(f"2: Received something other than data:{res}") return False @@ -505,9 +504,9 @@ async def TestMultiControllerFabric(self, nodeid: int): # Doing this ensures that we're not somehow aliasing the CASE sessions. # res = await self.devCtrl.ReadAttribute(nodeid=nodeid, attributes=[(0, Clusters.AccessControl.Attributes.Acl)]) - if (type(res[0][ + if (not isinstance(res[0][ Clusters.AccessControl][ - Clusters.AccessControl.Attributes.Acl][0]) != Clusters.AccessControl.Structs.AccessControlEntryStruct): + Clusters.AccessControl.Attributes.Acl][0], Clusters.AccessControl.Structs.AccessControlEntryStruct)): self.logger.error(f"2: Received something other than data:{res}") return False @@ -531,9 +530,9 @@ async def TestMultiControllerFabric(self, nodeid: int): targetNodeId=nodeid ) res = await newControllers[0].ReadAttribute(nodeid=nodeid, attributes=[(0, Clusters.AccessControl.Attributes.Acl)]) - if (type(res[0][ + if (not isinstance(res[0][ Clusters.AccessControl][ - Clusters.AccessControl.Attributes.Acl][0]) != Clusters.AccessControl.Structs.AccessControlEntryStruct): + Clusters.AccessControl.Attributes.Acl][0], Clusters.AccessControl.Structs.AccessControlEntryStruct)): self.logger.error(f"4: Received something other than data:{res}") return False @@ -547,9 +546,9 @@ async def TestMultiControllerFabric(self, nodeid: int): targetNodeId=nodeid ) res = await newControllers[1].ReadAttribute(nodeid=nodeid, attributes=[(0, Clusters.AccessControl.Attributes.Acl)]) - if (type(res[0][ + if (not isinstance(res[0][ Clusters.AccessControl][ - Clusters.AccessControl.Attributes.Acl][0]) != Clusters.AccessControl.Structs.AccessControlEntryStruct): + Clusters.AccessControl.Attributes.Acl][0], Clusters.AccessControl.Structs.AccessControlEntryStruct)): self.logger.error(f"5: Received something other than data:{res}") return False @@ -571,11 +570,9 @@ async def TestMultiControllerFabric(self, nodeid: int): # res = await newControllers[1].ReadAttribute(nodeid=nodeid, attributes=[(0, Clusters.BasicInformation.Attributes.ClusterRevision)]) - if (type( - res[0][ + if (not isinstance(res[0][ Clusters.BasicInformation][ - Clusters.BasicInformation.Attributes.ClusterRevision] - ) != Clusters.BasicInformation.Attributes.ClusterRevision.attribute_type.Type): + Clusters.BasicInformation.Attributes.ClusterRevision], Clusters.BasicInformation.Attributes.ClusterRevision.attribute_type.Type)): self.logger.error(f"7: Received something other than data:{res}") return False diff --git a/src/controller/python/test/unit_tests/test_tlv.py b/src/controller/python/test/unit_tests/test_tlv.py index 74d7aefe0f07cc..7a80b24c497320 100644 --- a/src/controller/python/test/unit_tests/test_tlv.py +++ b/src/controller/python/test/unit_tests/test_tlv.py @@ -17,7 +17,7 @@ import unittest -from chip.tlv import TLVReader, TLVWriter +from chip.tlv import TLVList, TLVReader, TLVWriter from chip.tlv import uint as tlvUint @@ -112,6 +112,24 @@ def test_uint(self): except Exception: pass + def test_list(self): + encodeVal = self._getEncoded(TLVList([(None, 1), (None, 2), (1, 3)])) + self.assertEqual(encodeVal, bytearray([0b00010111, # List, anonymous tag + 0x00, 0x01, # Anonymous tag, 1 octet signed int `1`` + 0x00, 0x02, # Anonymous tag, 1 octet signed int `2`` + 0b00100000, 0x01, 0x03, # Context specific tag `1`, 1 octet signed int `3` + 0x18 # End of container + ])) + encodeVal = self._getEncoded(TLVList([(None, 1), (None, TLVList([(None, 2), (3, 4)]))])) + self.assertEqual(encodeVal, bytearray([0b00010111, # List, anonymous tag + 0x00, 0x01, # Anonymous tag, 1 octet signed int `1`` + 0b00010111, # List anonymous tag + 0x00, 0x02, # Anonymous tag, 1 octet signed int `2`` + 0b00100000, 0x03, 0x04, # Context specific tag `1`, 1 octet signed int `3` + 0x18, # End of inner list + 0x18 # End of container + ])) + class TestTLVReader(unittest.TestCase): def _read_case(self, input, answer): @@ -151,16 +169,52 @@ def test_structure(self): test_cases = [ (b'\x15\x36\x01\x15\x35\x01\x26\x00\xBF\xA2\x55\x16\x37\x01\x24' b'\x02\x00\x24\x03\x28\x24\x04\x00\x18\x24\x02\x01\x18\x18\x18\x18', - {1: [{1: {0: 374710975, 1: [0, 40, 0], 2: 1}}]}), + {1: [{1: {0: 374710975, 1: TLVList([(2, 0), (3, 40), (4, 0)]), 2: 1}}]}), (b'\x156\x01\x155\x01&\x00\xBF\xA2U\x167\x01$\x02\x00$\x03($\x04\x01' b'\x18,\x02\x18Nordic Semiconductor ASA\x18\x18\x18\x18', - {1: [{1: {0: 374710975, 1: [0, 40, 1], 2: 'Nordic Semiconductor ASA'}}]}), + {1: [{1: {0: 374710975, 1: TLVList([(2, 0), (3, 40), (4, 1)]), 2: 'Nordic Semiconductor ASA'}}]}), (b"\0256\001\0255\001&\000\031\346x\2077\001$\002\001$\003\006$\004\000\030(\002\030\030\030\030", - {1: [{1: {0: 2272847385, 1: [1, 6, 0], 2: False}}]}) + {1: [{1: {0: 2272847385, 1: TLVList([(2, 1), (3, 6), (4, 0)]), 2: False}}]}) ] for tlv_bytes, answer in test_cases: self._read_case(tlv_bytes, answer) + def test_list(self): + self._read_case([0b00010111, # List, anonymous tag + 0x00, 0x01, # Anonymous tag, 1 octet signed int `1`` + 0x00, 0x02, # Anonymous tag, 1 octet signed int `2`` + 0b00100000, 0x01, 0x03, # Context specific tag `1`, 1 octet signed int `3` + 0x18 # End of container + ], TLVList([(None, 1), (None, 2), (1, 3)])) + self._read_case([0b00010111, # List, anonymous tag + 0x00, 0x01, # Anonymous tag, 1 octet signed int `1`` + 0b00010111, # List anonymous tag + 0x00, 0x02, # Anonymous tag, 1 octet signed int `2`` + 0b00100000, 0x03, 0x04, # Context specific tag `1`, 1 octet signed int `3` + 0x18, # End of inner list + 0x18 # End of container + ], TLVList([(None, 1), (None, TLVList([(None, 2), (3, 4)]))])) + + +class TestTLVTypes(unittest.TestCase): + def test_list(self): + var = TLVList([(None, 1), (None, 2), (1, 3)]) + self.assertEqual(var[1], 3) + self.assertEqual(var[TLVList.IndexMethod.Index:0], (None, 1)) + self.assertEqual(var[TLVList.IndexMethod.Tag:1], 3) + + var.append(None, 4) + self.assertEqual(var, TLVList([(None, 1), (None, 2), (1, 3), (None, 4)])) + + var.append(5, 6) + self.assertEqual(var, TLVList([(None, 1), (None, 2), (1, 3), (None, 4), (5, 6)])) + + expectIterateContent = [(None, 1), (None, 2), (1, 3), (None, 4), (5, 6)] + iteratedContent = [] + for tag, value in var: + iteratedContent.append((tag, value)) + self.assertEqual(expectIterateContent, iteratedContent) + if __name__ == '__main__': unittest.main() diff --git a/src/crypto/BUILD.gn b/src/crypto/BUILD.gn index d97c89737c15bc..d0fe7190175ed6 100644 --- a/src/crypto/BUILD.gn +++ b/src/crypto/BUILD.gn @@ -55,14 +55,6 @@ buildconfig_header("crypto_buildconfig") { "CHIP_CRYPTO_BORINGSSL=${chip_crypto_boringssl}", "CHIP_CRYPTO_PLATFORM=${chip_crypto_platform}", ] - - if (chip_with_se05x == 1) { - defines += [ "CHIP_CRYPTO_HSM=1" ] - defines += [ "CHIP_CRYPTO_HSM_NXP=1" ] - } else { - defines += [ "CHIP_CRYPTO_HSM=0" ] - defines += [ "CHIP_CRYPTO_HSM_NXP=0" ] - } } source_set("public_headers") { @@ -177,19 +169,4 @@ static_library("crypto") { } else { assert(false, "Invalid CHIP crypto") } - - if (chip_with_se05x == 1) { - sources += [ - "hsm/nxp/CHIPCryptoPALHsm_SE05X_HKDF.cpp", - "hsm/nxp/CHIPCryptoPALHsm_SE05X_HMAC.cpp", - "hsm/nxp/CHIPCryptoPALHsm_SE05X_P256.cpp", - "hsm/nxp/CHIPCryptoPALHsm_SE05X_PBKDF.cpp", - "hsm/nxp/CHIPCryptoPALHsm_SE05X_Spake2p.cpp", - "hsm/nxp/CHIPCryptoPALHsm_SE05X_utils.cpp", - "hsm/nxp/PersistentStorageOperationalKeystoreHSM.cpp", - "hsm/nxp/PersistentStorageOperationalKeystoreHSM.h", - ] - public_deps += [ "${chip_root}/third_party/simw-top-mini:se05x" ] - public_configs += [ "${chip_root}/third_party/simw-top-mini:se05x_config" ] - } } diff --git a/src/crypto/CHIPCryptoPAL.cpp b/src/crypto/CHIPCryptoPAL.cpp index 69c3f575867ab6..8d42fd49726156 100644 --- a/src/crypto/CHIPCryptoPAL.cpp +++ b/src/crypto/CHIPCryptoPAL.cpp @@ -197,11 +197,7 @@ CHIP_ERROR ConvertIntegerRawToDerInternal(const ByteSpan & raw_integer, MutableB namespace chip { namespace Crypto { -#ifdef ENABLE_HSM_HKDF -using HKDF_sha_crypto = HKDF_shaHSM; -#else using HKDF_sha_crypto = HKDF_sha; -#endif CHIP_ERROR Spake2p::InternalHash(const uint8_t * in, size_t in_len) { @@ -549,11 +545,7 @@ CHIP_ERROR Spake2pVerifier::Generate(uint32_t pbkdf2IterCount, const ByteSpan & size_t len; // Create local Spake2+ object for w0 and L computations. -#ifdef ENABLE_HSM_SPAKE - Spake2pHSM_P256_SHA256_HKDF_HMAC spake2p; -#else Spake2p_P256_SHA256_HKDF_HMAC spake2p; -#endif uint8_t context[kSHA256_Hash_Length] = { 0 }; SuccessOrExit(err = spake2p.Init(context, sizeof(context))); @@ -575,11 +567,7 @@ CHIP_ERROR Spake2pVerifier::Generate(uint32_t pbkdf2IterCount, const ByteSpan & CHIP_ERROR Spake2pVerifier::ComputeWS(uint32_t pbkdf2IterCount, const ByteSpan & salt, uint32_t setupPin, uint8_t * ws, uint32_t ws_len) { -#ifdef ENABLE_HSM_PBKDF2 - PBKDF2_sha256HSM pbkdf2; -#else PBKDF2_sha256 pbkdf2; -#endif uint8_t littleEndianSetupPINCode[sizeof(uint32_t)]; Encoding::LittleEndian::Put32(littleEndianSetupPINCode, setupPin); diff --git a/src/crypto/RawKeySessionKeystore.cpp b/src/crypto/RawKeySessionKeystore.cpp index 97666569345d04..7db2c0c8b28962 100644 --- a/src/crypto/RawKeySessionKeystore.cpp +++ b/src/crypto/RawKeySessionKeystore.cpp @@ -22,11 +22,7 @@ namespace chip { namespace Crypto { -#ifdef ENABLE_HSM_HKDF -using HKDF_sha_crypto = HKDF_shaHSM; -#else using HKDF_sha_crypto = HKDF_sha; -#endif CHIP_ERROR RawKeySessionKeystore::CreateKey(const Aes128KeyByteArray & keyMaterial, Aes128KeyHandle & key) { diff --git a/src/crypto/hsm/CHIPCryptoPALHsm.h b/src/crypto/hsm/CHIPCryptoPALHsm.h deleted file mode 100644 index dde8be48c52a8a..00000000000000 --- a/src/crypto/hsm/CHIPCryptoPALHsm.h +++ /dev/null @@ -1,212 +0,0 @@ -/* - * - * Copyright (c) 2020 Project CHIP Authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -/** - * @file - * Header that exposes the platform agnostic CHIP crypto primitives - */ - -#pragma once - -#include "CHIPCryptoPALHsm_config.h" -#include - -#if CHIP_CRYPTO_HSM_NXP -#include -#endif - -#if ((ENABLE_HSM_SPAKE_VERIFIER) || (ENABLE_HSM_SPAKE_PROVER)) -typedef struct hsm_pake_context_s -{ - uint8_t spake_context[32]; - size_t spake_context_len; -#if CHIP_CRYPTO_HSM_NXP - SE05x_CryptoObjectID_t spake_objId; -#endif -} hsm_pake_context_t; -#endif //#if ((ENABLE_HSM_SPAKE_VERIFIER) || (ENABLE_HSM_SPAKE_PROVER)) - -namespace chip { -namespace Crypto { - -#if ((ENABLE_HSM_SPAKE_VERIFIER) || (ENABLE_HSM_SPAKE_PROVER)) -/* Spake HSM class */ - -class Spake2pHSM_P256_SHA256_HKDF_HMAC : public Spake2p_P256_SHA256_HKDF_HMAC -{ -public: - Spake2pHSM_P256_SHA256_HKDF_HMAC() {} - - ~Spake2pHSM_P256_SHA256_HKDF_HMAC() {} - - CHIP_ERROR Init(const uint8_t * context, size_t context_len) override; - -#if ENABLE_HSM_SPAKE_VERIFIER - CHIP_ERROR BeginVerifier(const uint8_t * my_identity, size_t my_identity_len, const uint8_t * peer_identity, - size_t peer_identity_len, const uint8_t * w0in, size_t w0in_len, const uint8_t * Lin, - size_t Lin_len) override; -#endif - -#if ENABLE_HSM_SPAKE_PROVER - CHIP_ERROR BeginProver(const uint8_t * my_identity, size_t my_identity_len, const uint8_t * peer_identity, - size_t peer_identity_len, const uint8_t * w0in, size_t w0in_len, const uint8_t * w1in, - size_t w1in_len) override; -#endif - - CHIP_ERROR ComputeRoundOne(const uint8_t * pab, size_t pab_len, uint8_t * out, size_t * out_len) override; - - CHIP_ERROR ComputeRoundTwo(const uint8_t * in, size_t in_len, uint8_t * out, size_t * out_len) override; - - CHIP_ERROR KeyConfirm(const uint8_t * in, size_t in_len) override; - - hsm_pake_context_t hsm_pake_context; -}; - -#endif //#if ((ENABLE_HSM_SPAKE_VERIFIER) || (ENABLE_HSM_SPAKE_PROVER)) - -#if ENABLE_HSM_GENERATE_EC_KEY -/* Nist256 Key pair HSM class */ - -class P256PublicKeyHSM : public P256PublicKey -{ -public: - P256PublicKeyHSM() { PublicKeyid = 0; } - - size_t Length() const override { return kP256_PublicKey_Length; } - operator uint8_t *() override { return bytes; } - operator const uint8_t *() const override { return bytes; } - - const uint8_t * ConstBytes() const override { return &bytes[0]; } - uint8_t * Bytes() override { return &bytes[0]; } - bool IsUncompressed() const override - { - constexpr uint8_t kUncompressedPointMarker = 0x04; - // SEC1 definition of an uncompressed point is (0x04 || X || Y) where X and Y are - // raw zero-padded big-endian large integers of the group size. - return (Length() == ((kP256_FE_Length * 2) + 1)) && (ConstBytes()[0] == kUncompressedPointMarker); - } - - void SetPublicKeyId(uint32_t id) { PublicKeyid = id; } - - CHIP_ERROR ECDSA_validate_msg_signature(const uint8_t * msg, size_t msg_length, - const P256ECDSASignature & signature) const override; - - CHIP_ERROR ECDSA_validate_hash_signature(const uint8_t * hash, size_t hash_length, - const P256ECDSASignature & signature) const override; - -private: - uint8_t bytes[kP256_PublicKey_Length]; - uint32_t PublicKeyid; -}; - -class P256KeypairHSM : public P256Keypair -{ -public: - P256KeypairHSM() - { - provisioned_key = false; - keyid = 0; - } - - ~P256KeypairHSM(); - - virtual CHIP_ERROR Initialize(ECPKeyTarget key_target) override; - - virtual CHIP_ERROR Serialize(P256SerializedKeypair & output) const override; - - virtual CHIP_ERROR Deserialize(P256SerializedKeypair & input) override; - - virtual CHIP_ERROR ECDSA_sign_msg(const uint8_t * msg, size_t msg_length, P256ECDSASignature & out_signature) const override; - - virtual CHIP_ERROR ECDH_derive_secret(const P256PublicKey & remote_public_key, - P256ECDHDerivedSecret & out_secret) const override; - - CHIP_ERROR NewCertificateSigningRequest(uint8_t * csr, size_t & csr_length) const override; - - const P256PublicKeyHSM & Pubkey() const override { return mPublicKeyHSM; } - - bool provisioned_key; - - void SetKeyId(uint32_t id) { keyid = id; } - - uint32_t GetKeyId(void) { return keyid; } - -private: - uint32_t keyid; - P256PublicKeyHSM mPublicKeyHSM; -}; - -#endif //#if ENABLE_HSM_GENERATE_EC_KEY - -#if ENABLE_HSM_PBKDF2_SHA256 - -class PBKDF2_sha256HSM : public PBKDF2_sha256 -{ -public: - PBKDF2_sha256HSM(); - ~PBKDF2_sha256HSM(); - - virtual CHIP_ERROR pbkdf2_sha256(const uint8_t * password, size_t plen, const uint8_t * salt, size_t slen, - unsigned int iteration_count, uint32_t key_length, uint8_t * output) override; - - void SetKeyId(uint32_t id) { keyid = id; } - - uint32_t GetKeyId() { return keyid; } - -private: - uint32_t keyid; -}; - -#endif //#if ENABLE_HSM_PBKDF2_SHA256 - -#if ENABLE_HSM_HKDF_SHA256 - -class HKDF_shaHSM : public HKDF_sha -{ -public: - HKDF_shaHSM(); - ~HKDF_shaHSM(); - - virtual CHIP_ERROR HKDF_SHA256(const uint8_t * secret, const size_t secret_length, const uint8_t * salt, - const size_t salt_length, const uint8_t * info, const size_t info_length, uint8_t * out_buffer, - size_t out_length) override; - -private: - uint32_t keyid; -}; - -#endif //#if ENABLE_HSM_HKDF_SHA256 - -#if ENABLE_HSM_HMAC_SHA256 - -class HMAC_shaHSM : public HMAC_sha -{ -public: - HMAC_shaHSM(); - ~HMAC_shaHSM(); - - virtual CHIP_ERROR HMAC_SHA256(const uint8_t * key, size_t key_length, const uint8_t * message, size_t message_length, - uint8_t * out_buffer, size_t out_length) override; - -private: - uint32_t keyid; -}; - -#endif //#if ENABLE_HSM_HMAC_SHA256 - -} // namespace Crypto -} // namespace chip diff --git a/src/crypto/hsm/CHIPCryptoPALHsm_config.h b/src/crypto/hsm/CHIPCryptoPALHsm_config.h deleted file mode 100644 index 27d6eb2e1e33d2..00000000000000 --- a/src/crypto/hsm/CHIPCryptoPALHsm_config.h +++ /dev/null @@ -1,75 +0,0 @@ -/* - * - * Copyright (c) 2020 Project CHIP Authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -/** - * @file - * Header that exposes the options to enable HSM for required crypto operations. - */ - -#pragma once - -/* - * Enable HSM for SPAKE VERIFIER - */ -#define ENABLE_HSM_SPAKE_VERIFIER 0 - -/* - * Enable HSM for SPAKE PROVER - */ -#define ENABLE_HSM_SPAKE_PROVER 0 - -/* - * Enable HSM for Generate EC Key - */ -#define ENABLE_HSM_GENERATE_EC_KEY 1 - -/* - * Enable HSM for PBKDF SHA256 - */ -#define ENABLE_HSM_PBKDF2_SHA256 0 - -/* - * Enable HSM for HKDF SHA256 - */ -#define ENABLE_HSM_HKDF_SHA256 0 - -/* - * Enable HSM for HMAC SHA256 - */ -#define ENABLE_HSM_HMAC_SHA256 0 - -#if ((CHIP_CRYPTO_HSM) && ((ENABLE_HSM_SPAKE_VERIFIER) || (ENABLE_HSM_SPAKE_PROVER))) -#define ENABLE_HSM_SPAKE -#endif - -#if ((CHIP_CRYPTO_HSM) && (ENABLE_HSM_GENERATE_EC_KEY)) -#define ENABLE_HSM_EC_KEY -//#define ENABLE_HSM_ECDSA_VERIFY -//#define ENABLE_HSM_DEVICE_ATTESTATION -#endif - -#if ((CHIP_CRYPTO_HSM) && (ENABLE_HSM_PBKDF2_SHA256)) -#define ENABLE_HSM_PBKDF2 -#endif - -#if ((CHIP_CRYPTO_HSM) && (ENABLE_HSM_HKDF_SHA256)) -#define ENABLE_HSM_HKDF -#endif - -#if ((CHIP_CRYPTO_HSM) && (ENABLE_HSM_HMAC_SHA256)) -#define ENABLE_HSM_HMAC -#endif diff --git a/src/crypto/hsm/nxp/PersistentStorageOperationalKeystoreHSM.cpp b/src/crypto/hsm/nxp/PersistentStorageOperationalKeystoreHSM.cpp deleted file mode 100644 index 3b0185b03f9250..00000000000000 --- a/src/crypto/hsm/nxp/PersistentStorageOperationalKeystoreHSM.cpp +++ /dev/null @@ -1,274 +0,0 @@ -/* - * Copyright (c) 2022 Project CHIP Authors - * All rights reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include "PersistentStorageOperationalKeystoreHSM.h" -#include "CHIPCryptoPALHsm_SE05X_utils.h" -#include - -#if ENABLE_HSM_GENERATE_EC_KEY - -namespace chip { - -using namespace chip::Crypto; - -#define MAX_KEYID_SLOTS_FOR_FABRICS 32 -#define FABRIC_SE05X_KEYID_START 0x7D100000 - -/** - * Known issues: - * 1. The current HSM keystore implementation is tested only with one fabric. To be tested with multiple fabrics. - * 2. Logic to read the HSM and create the fabricTable from the persistent keys after reboot is missing . - */ - -struct keyidFabIdMapping_t -{ - uint32_t keyId; - FabricIndex fabricIndex; - bool isPending; - Crypto::P256KeypairHSM * pkeyPair; -} keyidFabIdMapping[MAX_KEYID_SLOTS_FOR_FABRICS] = { - 0, -}; - -uint8_t getEmpytSlotId() -{ - uint8_t i = 0; - for (auto & mapping : keyidFabIdMapping) - { - if (mapping.keyId == kKeyId_NotInitialized && mapping.isPending == false) - { - break; - } - i++; - } - return i; -} - -void PersistentStorageOperationalKeystoreHSM::ResetPendingSlot() -{ - uint32_t slotId = mPendingKeypair->GetKeyId() - FABRIC_SE05X_KEYID_START; - if (slotId < MAX_KEYID_SLOTS_FOR_FABRICS) - { - keyidFabIdMapping[slotId].keyId = kKeyId_NotInitialized; - keyidFabIdMapping[slotId].fabricIndex = kUndefinedFabricIndex; - keyidFabIdMapping[slotId].isPending = false; - } -} - -bool PersistentStorageOperationalKeystoreHSM::HasOpKeypairForFabric(FabricIndex fabricIndex) const -{ - VerifyOrReturnError(IsValidFabricIndex(fabricIndex), false); - - // If there was a pending keypair, then there's really a usable key - if (mIsPendingKeypairActive && (fabricIndex == mPendingFabricIndex) && (mPendingKeypair != nullptr)) - { - ChipLogProgress(Crypto, "SE05x: HasOpKeypairForFabric ==> mPendingKeypair found"); - return true; - } - - for (auto & mapping : keyidFabIdMapping) - { - if (mapping.fabricIndex == fabricIndex) - { - ChipLogProgress(Crypto, "SE05x: HasOpKeypairForFabric ==> stored keyPair found"); - return true; - } - } - - ChipLogProgress(Crypto, "SE05x: HasOpKeypairForFabric ==> No key found"); - return false; -} - -CHIP_ERROR PersistentStorageOperationalKeystoreHSM::NewOpKeypairForFabric(FabricIndex fabricIndex, - MutableByteSpan & outCertificateSigningRequest) -{ - CHIP_ERROR err = CHIP_NO_ERROR; - - VerifyOrReturnError(IsValidFabricIndex(fabricIndex), CHIP_ERROR_INVALID_FABRIC_INDEX); - - ChipLogProgress(Crypto, "SE05x: New Op Keypair for Fabric %02x", fabricIndex); - - // Replace previous pending keypair, if any was previously allocated - ResetPendingKey(); - - uint8_t slotId = getEmpytSlotId(); - VerifyOrReturnError(slotId < MAX_KEYID_SLOTS_FOR_FABRICS, CHIP_ERROR_NO_MEMORY); - - mPendingKeypair = Platform::New(); - VerifyOrReturnError(mPendingKeypair != nullptr, CHIP_ERROR_NO_MEMORY); - - // Key id is created as slotid + start offset of ops key id - mPendingKeypair->SetKeyId(FABRIC_SE05X_KEYID_START + slotId); - - err = mPendingKeypair->Initialize(Crypto::ECPKeyTarget::ECDSA); - VerifyOrReturnError(err == CHIP_NO_ERROR, CHIP_ERROR_NO_MEMORY); - - mPendingFabricIndex = fabricIndex; - - keyidFabIdMapping[slotId].isPending = true; - - size_t csrLength = outCertificateSigningRequest.size(); - err = mPendingKeypair->NewCertificateSigningRequest(outCertificateSigningRequest.data(), csrLength); - if (err != CHIP_NO_ERROR) - { - ResetPendingKey(); - return err; - } - outCertificateSigningRequest.reduce_size(csrLength); - - return CHIP_NO_ERROR; -} - -CHIP_ERROR PersistentStorageOperationalKeystoreHSM::ActivateOpKeypairForFabric(FabricIndex fabricIndex, - const Crypto::P256PublicKey & nocPublicKey) -{ - ChipLogProgress(Crypto, "SE05x: ActivateOpKeypair for Fabric %02x", fabricIndex); - - VerifyOrReturnError(mPendingKeypair != nullptr, CHIP_ERROR_INVALID_FABRIC_INDEX); - VerifyOrReturnError(IsValidFabricIndex(fabricIndex) && (fabricIndex == mPendingFabricIndex), CHIP_ERROR_INVALID_FABRIC_INDEX); - - // Validate public key being activated matches last generated pending keypair - VerifyOrReturnError(mPendingKeypair->Pubkey().Matches(nocPublicKey), CHIP_ERROR_INVALID_PUBLIC_KEY); - - mIsPendingKeypairActive = true; - - return CHIP_NO_ERROR; -} - -CHIP_ERROR PersistentStorageOperationalKeystoreHSM::CommitOpKeypairForFabric(FabricIndex fabricIndex) -{ - VerifyOrReturnError(mPendingKeypair != nullptr, CHIP_ERROR_INVALID_FABRIC_INDEX); - VerifyOrReturnError(IsValidFabricIndex(fabricIndex) && (fabricIndex == mPendingFabricIndex), CHIP_ERROR_INVALID_FABRIC_INDEX); - VerifyOrReturnError(mIsPendingKeypairActive == true, CHIP_ERROR_INCORRECT_STATE); - - uint32_t slotId = mPendingKeypair->GetKeyId() - FABRIC_SE05X_KEYID_START; - - VerifyOrReturnError(slotId < MAX_KEYID_SLOTS_FOR_FABRICS, CHIP_ERROR_NO_MEMORY); - - ChipLogProgress(Crypto, "SE05x: CommitOpKeypair for Fabric %02x", fabricIndex); - - for (auto & mapping : keyidFabIdMapping) - { - if (mapping.fabricIndex == fabricIndex) - { - // Delete the previous keyPair associated with the fabric - mapping.isPending = false; - Platform::Delete(mapping.pkeyPair); - mapping.pkeyPair = NULL; - mapping.keyId = kKeyId_NotInitialized; - mapping.fabricIndex = kUndefinedFabricIndex; - } - } - - keyidFabIdMapping[slotId].pkeyPair = mPendingKeypair; - keyidFabIdMapping[slotId].keyId = mPendingKeypair->GetKeyId(); - keyidFabIdMapping[slotId].fabricIndex = mPendingFabricIndex; - keyidFabIdMapping[slotId].isPending = false; - - // If we got here, we succeeded and can reset the pending key: next `SignWithOpKeypair` will use the stored key. - mPendingKeypair = nullptr; - mIsPendingKeypairActive = false; - mPendingFabricIndex = kUndefinedFabricIndex; - - return CHIP_NO_ERROR; -} - -CHIP_ERROR PersistentStorageOperationalKeystoreHSM::RemoveOpKeypairForFabric(FabricIndex fabricIndex) -{ - VerifyOrReturnError(IsValidFabricIndex(fabricIndex), CHIP_ERROR_INVALID_FABRIC_INDEX); - - ChipLogProgress(Crypto, "SE05x: RemoveOpKeypair for Fabric %02x", fabricIndex); - - // Remove pending state if matching - if ((mPendingKeypair != nullptr) && (fabricIndex == mPendingFabricIndex)) - { - RevertPendingKeypair(); - } - - for (auto & mapping : keyidFabIdMapping) - { - if (mapping.fabricIndex == fabricIndex) - { - // Delete the keyPair associated with the fabric - mapping.isPending = false; - Platform::Delete(mapping.pkeyPair); - mapping.pkeyPair = NULL; - mapping.keyId = kKeyId_NotInitialized; - mapping.fabricIndex = kUndefinedFabricIndex; - } - } - - return CHIP_NO_ERROR; -} - -void PersistentStorageOperationalKeystoreHSM::RevertPendingKeypair() -{ - ChipLogProgress(Crypto, "SE05x: RevertPendingKeypair"); - // Just reset the pending key, we never stored anything - ResetPendingKey(); -} - -CHIP_ERROR PersistentStorageOperationalKeystoreHSM::SignWithOpKeypair(FabricIndex fabricIndex, const ByteSpan & message, - Crypto::P256ECDSASignature & outSignature) const -{ - ChipLogProgress(Crypto, "SE05x: SignWithOpKeypair"); - - if (mIsPendingKeypairActive && (fabricIndex == mPendingFabricIndex)) - { - VerifyOrReturnError(mPendingKeypair != nullptr, CHIP_ERROR_INTERNAL); - // We have an override key: sign with it! - ChipLogProgress(Crypto, "SE05x: SignWithOpKeypair ==> using mPendingKeypair"); - return mPendingKeypair->ECDSA_sign_msg(message.data(), message.size(), outSignature); - } - else - { - for (auto & mapping : keyidFabIdMapping) - { - if ((mapping.fabricIndex == fabricIndex) && (mapping.isPending == false)) - { - ChipLogProgress(Crypto, "SE05x: SignWithOpKeypair ==> using stored keyPair"); - return mapping.pkeyPair->ECDSA_sign_msg(message.data(), message.size(), outSignature); - } - } - } - - ChipLogProgress(Crypto, "SE05x: SignWithOpKeypair ==> No keyPair found"); - return CHIP_ERROR_INVALID_FABRIC_INDEX; -} - -Crypto::P256Keypair * PersistentStorageOperationalKeystoreHSM::AllocateEphemeralKeypairForCASE() -{ - ChipLogProgress(Crypto, "SE05x: AllocateEphemeralKeypairForCASE using se05x"); - Crypto::P256KeypairHSM * pkeyPair = Platform::New(); - - if (pkeyPair != nullptr) - { - pkeyPair->SetKeyId(kKeyId_case_ephemeral_keyid); - } - - return pkeyPair; -} - -void PersistentStorageOperationalKeystoreHSM::ReleaseEphemeralKeypair(Crypto::P256Keypair * keypair) -{ - ChipLogProgress(Crypto, "SE05x: ReleaseEphemeralKeypair using se05x"); - Platform::Delete(static_cast(keypair)); -} - -} // namespace chip - -#endif //#if ENABLE_HSM_GENERATE_EC_KEY diff --git a/src/crypto/hsm/nxp/PersistentStorageOperationalKeystoreHSM.h b/src/crypto/hsm/nxp/PersistentStorageOperationalKeystoreHSM.h deleted file mode 100644 index bc00feaa8bb8d0..00000000000000 --- a/src/crypto/hsm/nxp/PersistentStorageOperationalKeystoreHSM.h +++ /dev/null @@ -1,99 +0,0 @@ -/* - * Copyright (c) 2022 Project CHIP Authors - * All rights reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#pragma once - -#include "CHIPCryptoPALHsm_SE05X_utils.h" -#include -#include -#include -#include -#include -#include - -#if ENABLE_HSM_GENERATE_EC_KEY - -namespace chip { - -class PersistentStorageOperationalKeystoreHSM : public Crypto::OperationalKeystore -{ -public: - PersistentStorageOperationalKeystoreHSM() = default; - virtual ~PersistentStorageOperationalKeystoreHSM() { Finish(); } - - // Non-copyable - PersistentStorageOperationalKeystoreHSM(PersistentStorageOperationalKeystoreHSM const &) = delete; - void operator=(PersistentStorageOperationalKeystoreHSM const &) = delete; - - /** - * @brief Initialize the Operational Keystore for HSM. - * - * @param storage Pointer to persistent storage delegate to use. Must outlive this instance. - * @retval CHIP_NO_ERROR on success - * @retval CHIP_ERROR_INCORRECT_STATE if already initialized - */ - CHIP_ERROR Init(PersistentStorageDelegate * storage) - { - IgnoreUnusedVariable(storage); - mPendingFabricIndex = kUndefinedFabricIndex; - mPendingKeypair = nullptr; - mIsPendingKeypairActive = false; - return CHIP_NO_ERROR; - } - - /** - * @brief Finalize the keystore, so that subsequent operations fail - */ - void Finish() { ResetPendingKey(); } - - bool HasPendingOpKeypair() const override { return (mPendingKeypair != nullptr); } - - bool HasOpKeypairForFabric(FabricIndex fabricIndex) const override; - CHIP_ERROR NewOpKeypairForFabric(FabricIndex fabricIndex, MutableByteSpan & outCertificateSigningRequest) override; - CHIP_ERROR ActivateOpKeypairForFabric(FabricIndex fabricIndex, const Crypto::P256PublicKey & nocPublicKey) override; - CHIP_ERROR CommitOpKeypairForFabric(FabricIndex fabricIndex) override; - CHIP_ERROR RemoveOpKeypairForFabric(FabricIndex fabricIndex) override; - void RevertPendingKeypair() override; - CHIP_ERROR SignWithOpKeypair(FabricIndex fabricIndex, const ByteSpan & message, - Crypto::P256ECDSASignature & outSignature) const override; - Crypto::P256Keypair * AllocateEphemeralKeypairForCASE() override; - void ReleaseEphemeralKeypair(Crypto::P256Keypair * keypair) override; - -protected: - void ResetPendingSlot(); - - void ResetPendingKey() - { - if (mPendingKeypair != nullptr) - { - ResetPendingSlot(); - Platform::Delete(mPendingKeypair); - } - mPendingKeypair = nullptr; - mIsPendingKeypairActive = false; - mPendingFabricIndex = kUndefinedFabricIndex; - } - - // This pending fabric index is `kUndefinedFabricIndex` if there isn't a pending keypair override for a given fabric. - FabricIndex mPendingFabricIndex = kUndefinedFabricIndex; - Crypto::P256KeypairHSM * mPendingKeypair = nullptr; - bool mIsPendingKeypairActive = false; -}; - -} // namespace chip - -#endif //#if ENABLE_HSM_GENERATE_EC_KEY diff --git a/src/crypto/hsm/nxp/README.md b/src/crypto/hsm/nxp/README.md deleted file mode 100644 index 0a6d492cdf72d3..00000000000000 --- a/src/crypto/hsm/nxp/README.md +++ /dev/null @@ -1,31 +0,0 @@ -# Using SE05X for crypto operations - -## Introduction - -CHIPCryptoPALHsm*SE05X*\*.cpp file provides the integration of secure element -(SE05x) in crypto layer of CHIP stack. By enabling the required directives in -CHIPCryptoPALHsm_config.h header file, required crypto operations can be -performed using SE05x. By default, the secure element is enabled for PAKE -(Verifier), HKDF, HMAC (SHA256). - -Following are the list operations supported by secure element. - - 1. PAKE - 2. ECC KEY - P256 (Disabled by default) - 3. PBKDF (Disabled by default) - 4. HKDF - 5. HMAC (SHA256) - -## Build - -- Use the following gn build arguments to enable the secure element in crypto - layer, - -``` -chip_with_se05x=1 ==> To enable Se05x -host = "host_k32w" ==> To set host -``` - -## Known Limitations: - -- None diff --git a/src/crypto/tests/CHIPCryptoPALTest.cpp b/src/crypto/tests/CHIPCryptoPALTest.cpp index 3ceda243d2347d..5f377841935725 100644 --- a/src/crypto/tests/CHIPCryptoPALTest.cpp +++ b/src/crypto/tests/CHIPCryptoPALTest.cpp @@ -37,9 +37,6 @@ #include #include -#if CHIP_CRYPTO_HSM -#include -#endif #include #include #include @@ -62,8 +59,6 @@ #include #include -#define HSM_ECC_KEYID 0x11223344 - #include #include #include @@ -84,40 +79,11 @@ using namespace chip::TLV; namespace { -#ifdef ENABLE_HSM_EC_KEY -class Test_P256Keypair : public P256KeypairHSM -{ -public: - Test_P256Keypair() { SetKeyId(HSM_ECC_KEYID); } - Test_P256Keypair(uint32_t keyId) { SetKeyId(keyId); } -}; -#else using Test_P256Keypair = P256Keypair; -#endif - -#ifdef ENABLE_HSM_SPAKE -using TestSpake2p_P256_SHA256_HKDF_HMAC = Spake2pHSM_P256_SHA256_HKDF_HMAC; -#else using TestSpake2p_P256_SHA256_HKDF_HMAC = Spake2p_P256_SHA256_HKDF_HMAC; -#endif - -#ifdef ENABLE_HSM_PBKDF2 -using TestPBKDF2_sha256 = PBKDF2_sha256HSM; -#else using TestPBKDF2_sha256 = PBKDF2_sha256; -#endif - -#ifdef ENABLE_HSM_HKDF -using TestHKDF_sha = HKDF_shaHSM; -#else using TestHKDF_sha = HKDF_sha; -#endif - -#ifdef ENABLE_HSM_HMAC -using TestHMAC_sha = HMAC_shaHSM; -#else using TestHMAC_sha = HMAC_sha; -#endif // Helper class to verify that all mbedTLS heap objects are released at the end of a test. #if CHIP_CRYPTO_MBEDTLS && defined(MBEDTLS_MEMORY_DEBUG) @@ -1045,11 +1011,7 @@ static void TestECDH_EstablishSecret(nlTestSuite * inSuite, void * inContext) Test_P256Keypair keypair1; NL_TEST_ASSERT(inSuite, keypair1.Initialize(ECPKeyTarget::ECDH) == CHIP_NO_ERROR); -#ifdef ENABLE_HSM_EC_KEY - Test_P256Keypair keypair2(HSM_ECC_KEYID + 1); -#else Test_P256Keypair keypair2; -#endif NL_TEST_ASSERT(inSuite, keypair2.Initialize(ECPKeyTarget::ECDH) == CHIP_NO_ERROR); P256ECDHDerivedSecret out_secret1; @@ -1664,12 +1626,7 @@ static void TestSPAKE2P_spake2p_PointIsValid(nlTestSuite * inSuite, void * inCon // We need to "generate" specific field elements // to do so we need to override the specific method -class Test_Spake2p_P256_SHA256_HKDF_HMAC : -#ifdef ENABLE_HSM_SPAKE - public Spake2pHSM_P256_SHA256_HKDF_HMAC -#else - public Spake2p_P256_SHA256_HKDF_HMAC -#endif +class Test_Spake2p_P256_SHA256_HKDF_HMAC : public Spake2p_P256_SHA256_HKDF_HMAC { public: CHIP_ERROR TestSetFE(const uint8_t * fe_in, size_t fe_in_len) @@ -1962,6 +1919,7 @@ static void TestX509_VerifyAttestationCertificateFormat(nlTestSuite * inSuite, v { ByteSpan{kPaiPathLenMissing}, Crypto::AttestationCertType::kPAI, CHIP_ERROR_INTERNAL }, { ByteSpan{kPaiPathLen1}, Crypto::AttestationCertType::kPAI, CHIP_ERROR_INTERNAL }, { ByteSpan{kPaaPathLen2}, Crypto::AttestationCertType::kPAA, CHIP_ERROR_INTERNAL }, + { ByteSpan{kWrongPathLenFormat}, Crypto::AttestationCertType::kPAI, CHIP_ERROR_INTERNAL }, }; // clang-format on diff --git a/src/crypto/tests/DacValidationExplicitVectors.h b/src/crypto/tests/DacValidationExplicitVectors.h index ea1dc6d0584520..d55ba04a73de17 100644 --- a/src/crypto/tests/DacValidationExplicitVectors.h +++ b/src/crypto/tests/DacValidationExplicitVectors.h @@ -178,3 +178,42 @@ const uint8_t kPaaPathLen2[448] = { 0x1a, 0xfc, 0xfb, 0x51, 0x6f, 0x6b, 0x46, 0x47, 0xfc, 0xa7, 0xf4, 0x86, 0x35, 0xb2, 0xac, 0xb8, 0xb8, 0x8d, 0x9b, 0xc2, 0x39, 0x89, 0xd7, 0x2d, 0x42, 0x0d, 0xde, 0x6b, }; + +/* +-----BEGIN CERTIFICATE----- +MIIBuzCCAWKgAwIBAgIIEl3k+yzkQuowCgYIKoZIzj0EAwIwGjEYMBYGA1UEAwwP +TWF0dGVyIFRlc3QgUEFBMB4XDTIxMDYyODE0MjM0M1oXDTMzMDYyODE0MjM0Mlow +RjEYMBYGA1UEAwwPTWF0dGVyIFRlc3QgUEFJMRQwEgYKKwYBBAGConwCAQwERkZG +MjEUMBIGCisGAQQBgqJ8AgIMBDgwMDUwWTATBgcqhkjOPQIBBggqhkjOPQMBBwNC +AAQso3JRSRbamUuVk4C2aycB9M84CPOT9xaxI4nC+VqK8vSTJiploKPr+BvganEH +MqCqoC/1KO+Vi/0gMmMvvYhfo2YwZDASBgNVHRMBAf8ECDAGAQH/EwExMA4GA1Ud +DwEB/wQEAwIBBjAdBgNVHQ4EFgQU2tRnb1BtRUPblHbWGGkcZ0lyjQgwHwYDVR0j +BBgwFoAUeFznBbhrj05vx5OqYMtD6mlogtUwCgYIKoZIzj0EAwIDRwAwRAIgYreX +c1Ny+5HZRSxqT4gPVP5z5ZkhZXUSYW7GHaqs8VACID/8iIGshdedcjAbI6sQO+At +evcOqLypxnhGVlL2gQnf +-----END CERTIFICATE----- +*/ +const uint8_t kWrongPathLenFormat[447] = { + 0x30, 0x82, 0x01, 0xbb, 0x30, 0x82, 0x01, 0x62, 0xa0, 0x03, 0x02, 0x01, 0x02, 0x02, 0x08, 0x12, 0x5d, 0xe4, 0xfb, 0x2c, 0xe4, + 0x42, 0xea, 0x30, 0x0a, 0x06, 0x08, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x04, 0x03, 0x02, 0x30, 0x1a, 0x31, 0x18, 0x30, 0x16, 0x06, + 0x03, 0x55, 0x04, 0x03, 0x0c, 0x0f, 0x4d, 0x61, 0x74, 0x74, 0x65, 0x72, 0x20, 0x54, 0x65, 0x73, 0x74, 0x20, 0x50, 0x41, 0x41, + 0x30, 0x1e, 0x17, 0x0d, 0x32, 0x31, 0x30, 0x36, 0x32, 0x38, 0x31, 0x34, 0x32, 0x33, 0x34, 0x33, 0x5a, 0x17, 0x0d, 0x33, 0x33, + 0x30, 0x36, 0x32, 0x38, 0x31, 0x34, 0x32, 0x33, 0x34, 0x32, 0x5a, 0x30, 0x46, 0x31, 0x18, 0x30, 0x16, 0x06, 0x03, 0x55, 0x04, + 0x03, 0x0c, 0x0f, 0x4d, 0x61, 0x74, 0x74, 0x65, 0x72, 0x20, 0x54, 0x65, 0x73, 0x74, 0x20, 0x50, 0x41, 0x49, 0x31, 0x14, 0x30, + 0x12, 0x06, 0x0a, 0x2b, 0x06, 0x01, 0x04, 0x01, 0x82, 0xa2, 0x7c, 0x02, 0x01, 0x0c, 0x04, 0x46, 0x46, 0x46, 0x32, 0x31, 0x14, + 0x30, 0x12, 0x06, 0x0a, 0x2b, 0x06, 0x01, 0x04, 0x01, 0x82, 0xa2, 0x7c, 0x02, 0x02, 0x0c, 0x04, 0x38, 0x30, 0x30, 0x35, 0x30, + 0x59, 0x30, 0x13, 0x06, 0x07, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x02, 0x01, 0x06, 0x08, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x03, 0x01, + 0x07, 0x03, 0x42, 0x00, 0x04, 0x2c, 0xa3, 0x72, 0x51, 0x49, 0x16, 0xda, 0x99, 0x4b, 0x95, 0x93, 0x80, 0xb6, 0x6b, 0x27, 0x01, + 0xf4, 0xcf, 0x38, 0x08, 0xf3, 0x93, 0xf7, 0x16, 0xb1, 0x23, 0x89, 0xc2, 0xf9, 0x5a, 0x8a, 0xf2, 0xf4, 0x93, 0x26, 0x2a, 0x65, + 0xa0, 0xa3, 0xeb, 0xf8, 0x1b, 0xe0, 0x6a, 0x71, 0x07, 0x32, 0xa0, 0xaa, 0xa0, 0x2f, 0xf5, 0x28, 0xef, 0x95, 0x8b, 0xfd, 0x20, + 0x32, 0x63, 0x2f, 0xbd, 0x88, 0x5f, 0xa3, 0x66, 0x30, 0x64, 0x30, 0x12, 0x06, 0x03, 0x55, 0x1d, 0x13, 0x01, 0x01, 0xff, 0x04, + 0x08, 0x30, 0x06, 0x01, 0x01, 0xff, 0x13, 0x01, 0x31, 0x30, 0x0e, 0x06, 0x03, 0x55, 0x1d, 0x0f, 0x01, 0x01, 0xff, 0x04, 0x04, + 0x03, 0x02, 0x01, 0x06, 0x30, 0x1d, 0x06, 0x03, 0x55, 0x1d, 0x0e, 0x04, 0x16, 0x04, 0x14, 0xda, 0xd4, 0x67, 0x6f, 0x50, 0x6d, + 0x45, 0x43, 0xdb, 0x94, 0x76, 0xd6, 0x18, 0x69, 0x1c, 0x67, 0x49, 0x72, 0x8d, 0x08, 0x30, 0x1f, 0x06, 0x03, 0x55, 0x1d, 0x23, + 0x04, 0x18, 0x30, 0x16, 0x80, 0x14, 0x78, 0x5c, 0xe7, 0x05, 0xb8, 0x6b, 0x8f, 0x4e, 0x6f, 0xc7, 0x93, 0xaa, 0x60, 0xcb, 0x43, + 0xea, 0x69, 0x68, 0x82, 0xd5, 0x30, 0x0a, 0x06, 0x08, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x04, 0x03, 0x02, 0x03, 0x47, 0x00, 0x30, + 0x44, 0x02, 0x20, 0x62, 0xb7, 0x97, 0x73, 0x53, 0x72, 0xfb, 0x91, 0xd9, 0x45, 0x2c, 0x6a, 0x4f, 0x88, 0x0f, 0x54, 0xfe, 0x73, + 0xe5, 0x99, 0x21, 0x65, 0x75, 0x12, 0x61, 0x6e, 0xc6, 0x1d, 0xaa, 0xac, 0xf1, 0x50, 0x02, 0x20, 0x3f, 0xfc, 0x88, 0x81, 0xac, + 0x85, 0xd7, 0x9d, 0x72, 0x30, 0x1b, 0x23, 0xab, 0x10, 0x3b, 0xe0, 0x2d, 0x7a, 0xf7, 0x0e, 0xa8, 0xbc, 0xa9, 0xc6, 0x78, 0x46, + 0x56, 0x52, 0xf6, 0x81, 0x09, 0xdf, +}; diff --git a/src/darwin/Framework/CHIP/MTRCommissionableBrowser.h b/src/darwin/Framework/CHIP/MTRCommissionableBrowser.h new file mode 100644 index 00000000000000..9b6a639133fcea --- /dev/null +++ b/src/darwin/Framework/CHIP/MTRCommissionableBrowser.h @@ -0,0 +1,32 @@ +/** + * + * Copyright (c) 2023 Project CHIP Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import + +NS_ASSUME_NONNULL_BEGIN + +@protocol MTRCommissionableBrowserDelegate; + +@interface MTRCommissionableBrowser : NSObject +- (instancetype)init NS_UNAVAILABLE; ++ (instancetype)new NS_UNAVAILABLE; +- (instancetype)initWithDelegate:(id)delegate queue:(dispatch_queue_t)queue; +- (BOOL)start; +- (BOOL)stop; +@end + +NS_ASSUME_NONNULL_END diff --git a/src/darwin/Framework/CHIP/MTRCommissionableBrowser.mm b/src/darwin/Framework/CHIP/MTRCommissionableBrowser.mm new file mode 100644 index 00000000000000..3d1359895e23c6 --- /dev/null +++ b/src/darwin/Framework/CHIP/MTRCommissionableBrowser.mm @@ -0,0 +1,273 @@ +/** + * + * Copyright (c) 2023 Project CHIP Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "MTRCommissionableBrowser.h" +#import "MTRCommissionableBrowserDelegate.h" +#import "MTRCommissionableBrowserResult_Internal.h" +#import "MTRLogging_Internal.h" + +#include +#include +#include + +using namespace chip::Dnssd; +using namespace chip::DeviceLayer; + +#if CONFIG_NETWORK_LAYER_BLE +#include +using namespace chip::Ble; +constexpr const char * kBleKey = "BLE"; +#endif // CONFIG_NETWORK_LAYER_BLE + +@implementation MTRCommissionableBrowserResultInterfaces +@end + +@interface MTRCommissionableBrowserResult () +@property (nonatomic) NSString * serviceName; +@property (nonatomic) NSNumber * vendorId; +@property (nonatomic) NSNumber * productId; +@property (nonatomic) NSNumber * discriminator; +@end + +@implementation MTRCommissionableBrowserResult +@end + +class CommissionableBrowserInternal : public CommissioningResolveDelegate, + public DnssdBrowseDelegate +#if CONFIG_NETWORK_LAYER_BLE + , + public BleScannerDelegate +#endif // CONFIG_NETWORK_LAYER_BLE +{ +public: + CHIP_ERROR Start(id delegate, dispatch_queue_t queue) + { + VerifyOrReturnError(mDelegate == nil, CHIP_ERROR_INCORRECT_STATE); + VerifyOrReturnError(mDispatchQueue == nil, CHIP_ERROR_INCORRECT_STATE); + VerifyOrReturnError(mDiscoveredResults == nil, CHIP_ERROR_INCORRECT_STATE); + + mDelegate = delegate; + mDispatchQueue = queue; + mDiscoveredResults = [[NSMutableDictionary alloc] init]; + +#if CONFIG_NETWORK_LAYER_BLE + ReturnErrorOnFailure(PlatformMgrImpl().StartBleScan(this)); +#endif // CONFIG_NETWORK_LAYER_BLE + + ReturnErrorOnFailure(Resolver::Instance().Init(chip::DeviceLayer::UDPEndPointManager())); + + char serviceName[kMaxCommissionableServiceNameSize]; + auto filter = DiscoveryFilterType::kNone; + ReturnErrorOnFailure(MakeServiceTypeName(serviceName, sizeof(serviceName), filter, DiscoveryType::kCommissionableNode)); + + return ChipDnssdBrowse(serviceName, DnssdServiceProtocol::kDnssdProtocolUdp, chip::Inet::IPAddressType::kAny, + chip::Inet::InterfaceId::Null(), this); + } + + CHIP_ERROR Stop() + { + VerifyOrReturnError(mDelegate != nil, CHIP_ERROR_INCORRECT_STATE); + VerifyOrReturnError(mDispatchQueue != nil, CHIP_ERROR_INCORRECT_STATE); + VerifyOrReturnError(mDiscoveredResults != nil, CHIP_ERROR_INCORRECT_STATE); + + mDelegate = nil; + mDispatchQueue = nil; + mDiscoveredResults = nil; + +#if CONFIG_NETWORK_LAYER_BLE + ReturnErrorOnFailure(PlatformMgrImpl().StopBleScan()); +#endif // CONFIG_NETWORK_LAYER_BLE + + return ChipDnssdStopBrowse(this); + } + + /////////// CommissioningResolveDelegate Interface ///////// + void OnNodeDiscovered(const DiscoveredNodeData & nodeData) override + { + auto & commissionData = nodeData.commissionData; + auto key = [NSString stringWithUTF8String:commissionData.instanceName]; + if ([mDiscoveredResults objectForKey:key] == nil) { + // It should not happens. + return; + } + + auto result = mDiscoveredResults[key]; + result.serviceName = key; + result.vendorId = @(static_cast(commissionData.vendorId)); + result.productId = @(commissionData.productId); + result.discriminator = @(commissionData.longDiscriminator); + + auto & resolutionData = nodeData.resolutionData; + auto interfaces = result.interfaces; + interfaces[@(resolutionData.interfaceId.GetPlatformInterface())].resolutionData = chip::MakeOptional(resolutionData); + + // Check if any interface for the advertised service has been resolved already. If so, + // we don't need to inform the delegate about it since it already knows that something + // is available. + auto shouldDispatchToDelegate = YES; + for (id interfaceKey in interfaces) { + if (![interfaceKey isEqual:@(resolutionData.interfaceId.GetPlatformInterface())] + && interfaces[interfaceKey].resolutionData.HasValue()) { + shouldDispatchToDelegate = NO; + break; + } + } + + if (!shouldDispatchToDelegate) { + return; + } + + dispatch_async(mDispatchQueue, ^{ + [mDelegate didDiscoverCommissionable:result]; + }); + } + + /////////// DnssdBrowseDelegate Interface ///////// + void OnBrowseAdd(DnssdService service) override + { + auto key = [NSString stringWithUTF8String:service.mName]; + if ([mDiscoveredResults objectForKey:key] == nil) { + mDiscoveredResults[key] = [[MTRCommissionableBrowserResult alloc] init]; + mDiscoveredResults[key].interfaces = [[NSMutableDictionary alloc] init]; + } + + auto interfaces = mDiscoveredResults[key].interfaces; + auto interfaceKey = @(service.mInterface.GetPlatformInterface()); + interfaces[interfaceKey] = [[MTRCommissionableBrowserResultInterfaces alloc] init]; + + LogErrorOnFailure(ChipDnssdResolve(&service, service.mInterface, this)); + } + + void OnBrowseRemove(DnssdService service) override + { + auto key = [NSString stringWithUTF8String:service.mName]; + if ([mDiscoveredResults objectForKey:key] == nil) { + // It should not happens. + return; + } + + auto result = mDiscoveredResults[key]; + auto interfaces = result.interfaces; + auto interfaceKey = @(service.mInterface.GetPlatformInterface()); + + // Check if the interface data has been resolved already, otherwise, just inform the + // back end that we may not need it anymore. + if (!interfaces[interfaceKey].resolutionData.HasValue()) { + ChipDnssdResolveNoLongerNeeded(service.mName); + } + + // Delete the interface placeholder. + interfaces[interfaceKey] = nil; + + // If there is nothing else to resolve for the given instance name, just remove it + // too and informs the delegate that it is gone. + if ([interfaces count] == 0) { + dispatch_async(mDispatchQueue, ^{ + [mDelegate commissionableUnavailable:result]; + }); + + mDiscoveredResults[key] = nil; + } + } + + void OnBrowseStop(CHIP_ERROR error) override + { + for (id key in mDiscoveredResults) { + auto interfaces = mDiscoveredResults[key].interfaces; + for (id interfaceKey in interfaces) { + // Check if the interface data has been resolved already, otherwise, just inform the + // back end that we may not need it anymore. + if (!interfaces[interfaceKey].resolutionData.HasValue()) { + ChipDnssdResolveNoLongerNeeded([key UTF8String]); + } + } + } + } + +#if CONFIG_NETWORK_LAYER_BLE + /////////// BleScannerDelegate Interface ///////// + void OnBleScanAdd(BLE_CONNECTION_OBJECT connObj, const ChipBLEDeviceIdentificationInfo & info) override + { + auto result = [[MTRCommissionableBrowserResult alloc] init]; + result.serviceName = [NSString stringWithUTF8String:kBleKey]; + result.vendorId = @(static_cast(info.GetVendorId())); + result.productId = @(info.GetProductId()); + result.discriminator = @(info.GetDeviceDiscriminator()); + result.params = chip::MakeOptional(chip::Controller::SetUpCodePairerParameters(connObj, false /* connected */)); + + auto key = [NSString stringWithFormat:@"%@", connObj]; + mDiscoveredResults[key] = result; + + dispatch_async(mDispatchQueue, ^{ + [mDelegate didDiscoverCommissionable:result]; + }); + } + + void OnBleScanRemove(BLE_CONNECTION_OBJECT connObj) override + { + auto key = [NSString stringWithFormat:@"%@", connObj]; + if ([mDiscoveredResults objectForKey:key] == nil) { + // It should not happens. + return; + } + + auto result = mDiscoveredResults[key]; + mDiscoveredResults[key] = nil; + + dispatch_async(mDispatchQueue, ^{ + [mDelegate commissionableUnavailable:result]; + }); + } +#endif // CONFIG_NETWORK_LAYER_BLE + +private: + dispatch_queue_t mDispatchQueue; + id mDelegate; + NSMutableDictionary * mDiscoveredResults; +}; + +@interface MTRCommissionableBrowser () +@property (strong, nonatomic) dispatch_queue_t queue; +@property (nonatomic, readonly) id delegate; +@property (unsafe_unretained, nonatomic) CommissionableBrowserInternal browser; +@end + +@implementation MTRCommissionableBrowser +- (instancetype)initWithDelegate:(id)delegate queue:(dispatch_queue_t)queue +{ + if (self = [super init]) { + _delegate = delegate; + _queue = queue; + } + return self; +} + +- (BOOL)start +{ + VerifyOrReturnValue(CHIP_NO_ERROR == _browser.Start(_delegate, _queue), NO); + return YES; +} + +- (BOOL)stop +{ + VerifyOrReturnValue(CHIP_NO_ERROR == _browser.Stop(), NO); + _delegate = nil; + _queue = nil; + return YES; +} + +@end diff --git a/src/darwin/Framework/CHIP/MTRCommissionableBrowserDelegate.h b/src/darwin/Framework/CHIP/MTRCommissionableBrowserDelegate.h new file mode 100644 index 00000000000000..38ed6d3ad8bda6 --- /dev/null +++ b/src/darwin/Framework/CHIP/MTRCommissionableBrowserDelegate.h @@ -0,0 +1,37 @@ +/** + * + * Copyright (c) 2023 Project CHIP Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import + +@class MTRCommissionableBrowserResult; + +NS_ASSUME_NONNULL_BEGIN + +MTR_NEWLY_AVAILABLE +@protocol MTRCommissionableBrowserDelegate +/** + * Tells the delegate the commissionable manager discovered a device while scanning for devices. + */ +- (void)didDiscoverCommissionable:(MTRCommissionableBrowserResult *)device; + +/** + * Tells the delegate a previously discovered device is is no longer available. + */ +- (void)commissionableUnavailable:(MTRCommissionableBrowserResult *)device; +@end + +NS_ASSUME_NONNULL_END diff --git a/src/darwin/Framework/CHIP/MTRCommissionableBrowserResult.h b/src/darwin/Framework/CHIP/MTRCommissionableBrowserResult.h new file mode 100644 index 00000000000000..b83a314aa4c8cd --- /dev/null +++ b/src/darwin/Framework/CHIP/MTRCommissionableBrowserResult.h @@ -0,0 +1,32 @@ +/** + * + * Copyright (c) 2023 Project CHIP Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import + +NS_ASSUME_NONNULL_BEGIN + +MTR_NEWLY_AVAILABLE +@interface MTRCommissionableBrowserResult : NSObject + +@property (readonly, nonatomic) NSString * serviceName; +@property (readonly, nonatomic) NSNumber * vendorId; +@property (readonly, nonatomic) NSNumber * productId; +@property (readonly, nonatomic) NSNumber * discriminator; + +@end + +NS_ASSUME_NONNULL_END diff --git a/src/darwin/Framework/CHIP/MTRCommissionableBrowserResult_Internal.h b/src/darwin/Framework/CHIP/MTRCommissionableBrowserResult_Internal.h new file mode 100644 index 00000000000000..f60f50f74521fd --- /dev/null +++ b/src/darwin/Framework/CHIP/MTRCommissionableBrowserResult_Internal.h @@ -0,0 +1,39 @@ +/** + * + * Copyright (c) 2023 Project CHIP Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import + +#import "MTRCommissionableBrowserResult.h" + +#include + +NS_ASSUME_NONNULL_BEGIN + +@interface MTRCommissionableBrowserResultInterfaces : NSObject + +@property (nonatomic, readwrite) chip::Optional resolutionData; + +@end + +@interface MTRCommissionableBrowserResult () + +@property (nonatomic, readwrite) NSMutableDictionary * interfaces; +@property (nonatomic, readwrite) chip::Optional params; + +@end + +NS_ASSUME_NONNULL_END diff --git a/src/darwin/Framework/CHIP/MTRDeviceController.h b/src/darwin/Framework/CHIP/MTRDeviceController.h index c479442ab22582..84882c65257638 100644 --- a/src/darwin/Framework/CHIP/MTRDeviceController.h +++ b/src/darwin/Framework/CHIP/MTRDeviceController.h @@ -17,6 +17,7 @@ #import +#import #import @class MTRBaseDevice; @@ -27,6 +28,7 @@ MTR_DEPRECATED("Please use MTRBaseDevice deviceWithNodeID", ios(16.1, 16.4), mac typedef void (^MTRDeviceConnectionCallback)(MTRBaseDevice * _Nullable device, NSError * _Nullable error); @class MTRCommissioningParameters; +@class MTRCommissionableBrowserResult; @class MTRSetupPayload; @protocol MTRDevicePairingDelegate; @protocol MTRDeviceControllerDelegate; @@ -84,6 +86,39 @@ typedef void (^MTRDeviceConnectionCallback)(MTRBaseDevice * _Nullable device, NS error:(NSError * __autoreleasing *)error API_AVAILABLE(ios(16.2), macos(13.1), watchos(9.2), tvos(16.2)); +/** + * Set up a commissioning session for a device, using the provided discovered + * result to connect to it. + * + * @param discoveredDevice a previously discovered device. + * @param payload a setup payload (probably created from a QR code or numeric + * code onboarding payload). + * @param newNodeID the planned node id for the node. + * @error error indication if the commissioning session establishment can't start at all. + * + * The connection information for the device will be retrieved from the discovered device. + * A device discovered over MDNS will use the discovered IPs/ports, while a device discovered + * over BLE will use the underlying CBPeripheral. + * + * Then a PASE session will be established with the device, unless an error + * occurs. MTRDeviceControllerDelegate will be notified as follows: + * + * * Invalid connection information: onStatusUpdate with MTRCommissioningStatusFailed. + * + * * Commissioning session setup fails: onPairingComplete with an error. + * + * * Commissioning session setup succeeds: onPairingComplete with no error. + * + * Once a commissioning session is set up, getDeviceBeingCommissioned + * can be used to get an MTRBaseDevice and discover what sort of network + * credentials the device might need, and commissionDevice can be used to + * commission the device. + */ +- (BOOL)setupCommissioningSessionWithDiscoveredDevice:(MTRCommissionableBrowserResult *)discoveredDevice + payload:(MTRSetupPayload *)payload + newNodeID:(NSNumber *)newNodeID + error:(NSError * __autoreleasing *)error MTR_NEWLY_AVAILABLE; + /** * Commission the node with the given node ID. The node ID must match the node * ID that was used to set up the commissioning session. @@ -139,6 +174,20 @@ typedef void (^MTRDeviceConnectionCallback)(MTRBaseDevice * _Nullable device, NS - (void)setDeviceControllerDelegate:(id)delegate queue:(dispatch_queue_t)queue API_AVAILABLE(ios(16.4), macos(13.3), watchos(9.4), tvos(16.4)); +/** + * Start scanning for commissionable devices. + * + * This method will fail if the controller factory is not running. + */ +- (BOOL)startScan:(id)delegate queue:(dispatch_queue_t)queue MTR_NEWLY_AVAILABLE; + +/** + * Stop scanning for commissionable devices. + * + * This method will fail if the controller factory is not running or the scan has not been started. + */ +- (BOOL)stopScan MTR_NEWLY_AVAILABLE; + /** * Return the attestation challenge for the secure session of the device being commissioned. * diff --git a/src/darwin/Framework/CHIP/MTRDeviceController.mm b/src/darwin/Framework/CHIP/MTRDeviceController.mm index 2f01e499ad55db..5c4ae26c1f92b6 100644 --- a/src/darwin/Framework/CHIP/MTRDeviceController.mm +++ b/src/darwin/Framework/CHIP/MTRDeviceController.mm @@ -17,6 +17,8 @@ #import "MTRDeviceController_Internal.h" #import "MTRBaseDevice_Internal.h" +#import "MTRCommissionableBrowser.h" +#import "MTRCommissionableBrowserResult_Internal.h" #import "MTRCommissioningParameters.h" #import "MTRDeviceControllerDelegateBridge.h" #import "MTRDeviceControllerFactory_Internal.h" @@ -104,6 +106,7 @@ @interface MTRDeviceController () { @property (readonly) MTRDeviceControllerFactory * factory; @property (readonly) NSMutableDictionary * nodeIDToDeviceMap; @property (readonly) os_unfair_lock deviceMapLock; // protects nodeIDToDeviceMap +@property (readonly) MTRCommissionableBrowser * commissionableBrowser; @end @implementation MTRDeviceController @@ -161,6 +164,7 @@ - (void)cleanupAfterStartup [device invalidate]; } [self.nodeIDToDeviceMap removeAllObjects]; + [self stopScan]; [_factory controllerShuttingDown:self]; } @@ -449,6 +453,53 @@ - (BOOL)setupCommissioningSessionWithPayload:(MTRSetupPayload *)payload return [self syncRunOnWorkQueueWithBoolReturnValue:block error:error]; } +- (BOOL)setupCommissioningSessionWithDiscoveredDevice:(MTRCommissionableBrowserResult *)discoveredDevice + payload:(MTRSetupPayload *)payload + newNodeID:(NSNumber *)newNodeID + error:(NSError * __autoreleasing *)error +{ + auto block = ^BOOL { + chip::NodeId nodeId = [newNodeID unsignedLongLongValue]; + self->_operationalCredentialsDelegate->SetDeviceID(nodeId); + + auto errorCode = CHIP_ERROR_INVALID_ARGUMENT; + if (discoveredDevice.params.HasValue()) { + auto params = discoveredDevice.params.Value(); + auto pinCode = static_cast([[payload setupPasscode] unsignedLongValue]); + params.SetSetupPINCode(pinCode); + + errorCode = self.cppCommissioner->EstablishPASEConnection(nodeId, params); + } else { + // Try to get a QR code if possible (because it has a better + // discriminator, etc), then fall back to manual code if that fails. + NSString * pairingCode = [payload qrCodeString:nil]; + if (pairingCode == nil) { + pairingCode = [payload manualEntryCode]; + } + if (pairingCode == nil) { + return ![MTRDeviceController checkForError:CHIP_ERROR_INVALID_ARGUMENT logMsg:kErrorSetupCodeGen error:error]; + } + + for (id key in discoveredDevice.interfaces) { + auto resolutionData = discoveredDevice.interfaces[key].resolutionData; + if (!resolutionData.HasValue()) { + continue; + } + + errorCode = self.cppCommissioner->EstablishPASEConnection( + nodeId, [pairingCode UTF8String], chip::Controller::DiscoveryType::kDiscoveryNetworkOnly, resolutionData); + if (CHIP_NO_ERROR != errorCode) { + break; + } + } + } + + return ![MTRDeviceController checkForError:errorCode logMsg:kErrorPairDevice error:error]; + }; + + return [self syncRunOnWorkQueueWithBoolReturnValue:block error:error]; +} + - (BOOL)commissionNodeWithID:(NSNumber *)nodeID commissioningParams:(MTRCommissioningParameters *)commissioningParams error:(NSError * __autoreleasing *)error @@ -535,6 +586,28 @@ - (BOOL)cancelCommissioningForNodeID:(NSNumber *)nodeID error:(NSError * __autor return [self syncRunOnWorkQueueWithBoolReturnValue:block error:error]; } +- (BOOL)startScan:(id)delegate queue:(dispatch_queue_t)queue +{ + auto block = ^BOOL { + self->_commissionableBrowser = [[MTRCommissionableBrowser alloc] initWithDelegate:delegate queue:queue]; + return [self.commissionableBrowser start]; + }; + + return [self syncRunOnWorkQueueWithBoolReturnValue:block error:nil]; +} + +- (BOOL)stopScan +{ + auto block = ^BOOL { + auto commissionableBrowser = self.commissionableBrowser; + VerifyOrReturnValue(commissionableBrowser, NO); + self->_commissionableBrowser = nil; + return [commissionableBrowser stop]; + }; + + return [self syncRunOnWorkQueueWithBoolReturnValue:block error:nil]; +} + - (void)preWarmCommissioningSession { auto block = ^{ diff --git a/src/darwin/Framework/CHIP/Matter.h b/src/darwin/Framework/CHIP/Matter.h index a9da6744c08285..9a5ce73864f2c2 100644 --- a/src/darwin/Framework/CHIP/Matter.h +++ b/src/darwin/Framework/CHIP/Matter.h @@ -29,6 +29,8 @@ #import #import #import +#import +#import #import #import #import diff --git a/src/darwin/Framework/CHIP/templates/availability.yaml b/src/darwin/Framework/CHIP/templates/availability.yaml index 6a797e9185dddf..60e34d08604360 100644 --- a/src/darwin/Framework/CHIP/templates/availability.yaml +++ b/src/darwin/Framework/CHIP/templates/availability.yaml @@ -8390,6 +8390,7 @@ - RVCCleanMode - DishwasherMode - WasherControls + - RVCOperationalState # Once we actually unmark TimeSynchronization as provisional, all these bits should go away too, and we should instead # mark things as introduced/deprecated as needed. The "ids" entries should go away, in particular. ids: diff --git a/src/darwin/Framework/CHIP/zap-generated/MTRAttributeSpecifiedCheck.mm b/src/darwin/Framework/CHIP/zap-generated/MTRAttributeSpecifiedCheck.mm index 1b4bb1c6785da1..0920c65ca69499 100644 --- a/src/darwin/Framework/CHIP/zap-generated/MTRAttributeSpecifiedCheck.mm +++ b/src/darwin/Framework/CHIP/zap-generated/MTRAttributeSpecifiedCheck.mm @@ -2018,51 +2018,6 @@ static BOOL AttributeIsSpecifiedInOperationalStateCluster(AttributeId aAttribute } } } -static BOOL AttributeIsSpecifiedInRVCOperationalStateCluster(AttributeId aAttributeId) -{ - using namespace Clusters::RvcOperationalState; - switch (aAttributeId) { - case Attributes::PhaseList::Id: { - return YES; - } - case Attributes::CurrentPhase::Id: { - return YES; - } - case Attributes::CountdownTime::Id: { - return YES; - } - case Attributes::OperationalStateList::Id: { - return YES; - } - case Attributes::OperationalState::Id: { - return YES; - } - case Attributes::OperationalError::Id: { - return YES; - } - case Attributes::GeneratedCommandList::Id: { - return YES; - } - case Attributes::AcceptedCommandList::Id: { - return YES; - } - case Attributes::EventList::Id: { - return YES; - } - case Attributes::AttributeList::Id: { - return YES; - } - case Attributes::FeatureMap::Id: { - return YES; - } - case Attributes::ClusterRevision::Id: { - return YES; - } - default: { - return NO; - } - } -} static BOOL AttributeIsSpecifiedInHEPAFilterMonitoringCluster(AttributeId aAttributeId) { using namespace Clusters::HepaFilterMonitoring; @@ -5145,9 +5100,6 @@ BOOL MTRAttributeIsSpecified(ClusterId aClusterId, AttributeId aAttributeId) case Clusters::OperationalState::Id: { return AttributeIsSpecifiedInOperationalStateCluster(aAttributeId); } - case Clusters::RvcOperationalState::Id: { - return AttributeIsSpecifiedInRVCOperationalStateCluster(aAttributeId); - } case Clusters::HepaFilterMonitoring::Id: { return AttributeIsSpecifiedInHEPAFilterMonitoringCluster(aAttributeId); } diff --git a/src/darwin/Framework/CHIP/zap-generated/MTRAttributeTLVValueDecoder.mm b/src/darwin/Framework/CHIP/zap-generated/MTRAttributeTLVValueDecoder.mm index fe3c110ea46a02..02563e2e41ee49 100644 --- a/src/darwin/Framework/CHIP/zap-generated/MTRAttributeTLVValueDecoder.mm +++ b/src/darwin/Framework/CHIP/zap-generated/MTRAttributeTLVValueDecoder.mm @@ -10352,301 +10352,6 @@ static id _Nullable DecodeAttributeValueForOperationalStateCluster( *aError = CHIP_ERROR_IM_MALFORMED_ATTRIBUTE_PATH_IB; return nil; } -static id _Nullable DecodeAttributeValueForRVCOperationalStateCluster( - AttributeId aAttributeId, TLV::TLVReader & aReader, CHIP_ERROR * aError) -{ - using namespace Clusters::RvcOperationalState; - switch (aAttributeId) { - case Attributes::PhaseList::Id: { - using TypeInfo = Attributes::PhaseList::TypeInfo; - TypeInfo::DecodableType cppValue; - *aError = DataModel::Decode(aReader, cppValue); - if (*aError != CHIP_NO_ERROR) { - return nil; - } - NSArray * _Nullable value; - if (cppValue.IsNull()) { - value = nil; - } else { - { // Scope for our temporary variables - auto * array_1 = [NSMutableArray new]; - auto iter_1 = cppValue.Value().begin(); - while (iter_1.Next()) { - auto & entry_1 = iter_1.GetValue(); - NSString * newElement_1; - newElement_1 = AsString(entry_1); - if (newElement_1 == nil) { - CHIP_ERROR err = CHIP_ERROR_INVALID_ARGUMENT; - *aError = err; - return nil; - } - [array_1 addObject:newElement_1]; - } - CHIP_ERROR err = iter_1.GetStatus(); - if (err != CHIP_NO_ERROR) { - *aError = err; - return nil; - } - value = array_1; - } - } - return value; - } - case Attributes::CurrentPhase::Id: { - using TypeInfo = Attributes::CurrentPhase::TypeInfo; - TypeInfo::DecodableType cppValue; - *aError = DataModel::Decode(aReader, cppValue); - if (*aError != CHIP_NO_ERROR) { - return nil; - } - NSNumber * _Nullable value; - if (cppValue.IsNull()) { - value = nil; - } else { - value = [NSNumber numberWithUnsignedChar:cppValue.Value()]; - } - return value; - } - case Attributes::CountdownTime::Id: { - using TypeInfo = Attributes::CountdownTime::TypeInfo; - TypeInfo::DecodableType cppValue; - *aError = DataModel::Decode(aReader, cppValue); - if (*aError != CHIP_NO_ERROR) { - return nil; - } - NSNumber * _Nullable value; - if (cppValue.IsNull()) { - value = nil; - } else { - value = [NSNumber numberWithUnsignedInt:cppValue.Value()]; - } - return value; - } - case Attributes::OperationalStateList::Id: { - using TypeInfo = Attributes::OperationalStateList::TypeInfo; - TypeInfo::DecodableType cppValue; - *aError = DataModel::Decode(aReader, cppValue); - if (*aError != CHIP_NO_ERROR) { - return nil; - } - NSArray * _Nonnull value; - { // Scope for our temporary variables - auto * array_0 = [NSMutableArray new]; - auto iter_0 = cppValue.begin(); - while (iter_0.Next()) { - auto & entry_0 = iter_0.GetValue(); - MTRRVCOperationalStateClusterOperationalStateStruct * newElement_0; - newElement_0 = [MTRRVCOperationalStateClusterOperationalStateStruct new]; - newElement_0.operationalStateID = [NSNumber numberWithUnsignedChar:entry_0.operationalStateID]; - if (entry_0.operationalStateLabel.HasValue()) { - newElement_0.operationalStateLabel = AsString(entry_0.operationalStateLabel.Value()); - if (newElement_0.operationalStateLabel == nil) { - CHIP_ERROR err = CHIP_ERROR_INVALID_ARGUMENT; - *aError = err; - return nil; - } - } else { - newElement_0.operationalStateLabel = nil; - } - [array_0 addObject:newElement_0]; - } - CHIP_ERROR err = iter_0.GetStatus(); - if (err != CHIP_NO_ERROR) { - *aError = err; - return nil; - } - value = array_0; - } - return value; - } - case Attributes::OperationalState::Id: { - using TypeInfo = Attributes::OperationalState::TypeInfo; - TypeInfo::DecodableType cppValue; - *aError = DataModel::Decode(aReader, cppValue); - if (*aError != CHIP_NO_ERROR) { - return nil; - } - MTRRVCOperationalStateClusterOperationalStateStruct * _Nonnull value; - value = [MTRRVCOperationalStateClusterOperationalStateStruct new]; - value.operationalStateID = [NSNumber numberWithUnsignedChar:cppValue.operationalStateID]; - if (cppValue.operationalStateLabel.HasValue()) { - value.operationalStateLabel = AsString(cppValue.operationalStateLabel.Value()); - if (value.operationalStateLabel == nil) { - CHIP_ERROR err = CHIP_ERROR_INVALID_ARGUMENT; - *aError = err; - return nil; - } - } else { - value.operationalStateLabel = nil; - } - return value; - } - case Attributes::OperationalError::Id: { - using TypeInfo = Attributes::OperationalError::TypeInfo; - TypeInfo::DecodableType cppValue; - *aError = DataModel::Decode(aReader, cppValue); - if (*aError != CHIP_NO_ERROR) { - return nil; - } - MTRRVCOperationalStateClusterErrorStateStruct * _Nonnull value; - value = [MTRRVCOperationalStateClusterErrorStateStruct new]; - value.errorStateID = [NSNumber numberWithUnsignedChar:cppValue.errorStateID]; - if (cppValue.errorStateLabel.HasValue()) { - value.errorStateLabel = AsString(cppValue.errorStateLabel.Value()); - if (value.errorStateLabel == nil) { - CHIP_ERROR err = CHIP_ERROR_INVALID_ARGUMENT; - *aError = err; - return nil; - } - } else { - value.errorStateLabel = nil; - } - if (cppValue.errorStateDetails.HasValue()) { - value.errorStateDetails = AsString(cppValue.errorStateDetails.Value()); - if (value.errorStateDetails == nil) { - CHIP_ERROR err = CHIP_ERROR_INVALID_ARGUMENT; - *aError = err; - return nil; - } - } else { - value.errorStateDetails = nil; - } - return value; - } - case Attributes::GeneratedCommandList::Id: { - using TypeInfo = Attributes::GeneratedCommandList::TypeInfo; - TypeInfo::DecodableType cppValue; - *aError = DataModel::Decode(aReader, cppValue); - if (*aError != CHIP_NO_ERROR) { - return nil; - } - NSArray * _Nonnull value; - { // Scope for our temporary variables - auto * array_0 = [NSMutableArray new]; - auto iter_0 = cppValue.begin(); - while (iter_0.Next()) { - auto & entry_0 = iter_0.GetValue(); - NSNumber * newElement_0; - newElement_0 = [NSNumber numberWithUnsignedInt:entry_0]; - [array_0 addObject:newElement_0]; - } - CHIP_ERROR err = iter_0.GetStatus(); - if (err != CHIP_NO_ERROR) { - *aError = err; - return nil; - } - value = array_0; - } - return value; - } - case Attributes::AcceptedCommandList::Id: { - using TypeInfo = Attributes::AcceptedCommandList::TypeInfo; - TypeInfo::DecodableType cppValue; - *aError = DataModel::Decode(aReader, cppValue); - if (*aError != CHIP_NO_ERROR) { - return nil; - } - NSArray * _Nonnull value; - { // Scope for our temporary variables - auto * array_0 = [NSMutableArray new]; - auto iter_0 = cppValue.begin(); - while (iter_0.Next()) { - auto & entry_0 = iter_0.GetValue(); - NSNumber * newElement_0; - newElement_0 = [NSNumber numberWithUnsignedInt:entry_0]; - [array_0 addObject:newElement_0]; - } - CHIP_ERROR err = iter_0.GetStatus(); - if (err != CHIP_NO_ERROR) { - *aError = err; - return nil; - } - value = array_0; - } - return value; - } - case Attributes::EventList::Id: { - using TypeInfo = Attributes::EventList::TypeInfo; - TypeInfo::DecodableType cppValue; - *aError = DataModel::Decode(aReader, cppValue); - if (*aError != CHIP_NO_ERROR) { - return nil; - } - NSArray * _Nonnull value; - { // Scope for our temporary variables - auto * array_0 = [NSMutableArray new]; - auto iter_0 = cppValue.begin(); - while (iter_0.Next()) { - auto & entry_0 = iter_0.GetValue(); - NSNumber * newElement_0; - newElement_0 = [NSNumber numberWithUnsignedInt:entry_0]; - [array_0 addObject:newElement_0]; - } - CHIP_ERROR err = iter_0.GetStatus(); - if (err != CHIP_NO_ERROR) { - *aError = err; - return nil; - } - value = array_0; - } - return value; - } - case Attributes::AttributeList::Id: { - using TypeInfo = Attributes::AttributeList::TypeInfo; - TypeInfo::DecodableType cppValue; - *aError = DataModel::Decode(aReader, cppValue); - if (*aError != CHIP_NO_ERROR) { - return nil; - } - NSArray * _Nonnull value; - { // Scope for our temporary variables - auto * array_0 = [NSMutableArray new]; - auto iter_0 = cppValue.begin(); - while (iter_0.Next()) { - auto & entry_0 = iter_0.GetValue(); - NSNumber * newElement_0; - newElement_0 = [NSNumber numberWithUnsignedInt:entry_0]; - [array_0 addObject:newElement_0]; - } - CHIP_ERROR err = iter_0.GetStatus(); - if (err != CHIP_NO_ERROR) { - *aError = err; - return nil; - } - value = array_0; - } - return value; - } - case Attributes::FeatureMap::Id: { - using TypeInfo = Attributes::FeatureMap::TypeInfo; - TypeInfo::DecodableType cppValue; - *aError = DataModel::Decode(aReader, cppValue); - if (*aError != CHIP_NO_ERROR) { - return nil; - } - NSNumber * _Nonnull value; - value = [NSNumber numberWithUnsignedInt:cppValue]; - return value; - } - case Attributes::ClusterRevision::Id: { - using TypeInfo = Attributes::ClusterRevision::TypeInfo; - TypeInfo::DecodableType cppValue; - *aError = DataModel::Decode(aReader, cppValue); - if (*aError != CHIP_NO_ERROR) { - return nil; - } - NSNumber * _Nonnull value; - value = [NSNumber numberWithUnsignedShort:cppValue]; - return value; - } - default: { - break; - } - } - - *aError = CHIP_ERROR_IM_MALFORMED_ATTRIBUTE_PATH_IB; - return nil; -} static id _Nullable DecodeAttributeValueForHEPAFilterMonitoringCluster( AttributeId aAttributeId, TLV::TLVReader & aReader, CHIP_ERROR * aError) { @@ -24587,9 +24292,6 @@ id _Nullable MTRDecodeAttributeValue(const ConcreteAttributePath & aPath, TLV::T case Clusters::OperationalState::Id: { return DecodeAttributeValueForOperationalStateCluster(aPath.mAttributeId, aReader, aError); } - case Clusters::RvcOperationalState::Id: { - return DecodeAttributeValueForRVCOperationalStateCluster(aPath.mAttributeId, aReader, aError); - } case Clusters::HepaFilterMonitoring::Id: { return DecodeAttributeValueForHEPAFilterMonitoringCluster(aPath.mAttributeId, aReader, aError); } diff --git a/src/darwin/Framework/CHIP/zap-generated/MTRBaseClusters.h b/src/darwin/Framework/CHIP/zap-generated/MTRBaseClusters.h index 6e21a62b8e0a73..bf303f85568dca 100644 --- a/src/darwin/Framework/CHIP/zap-generated/MTRBaseClusters.h +++ b/src/darwin/Framework/CHIP/zap-generated/MTRBaseClusters.h @@ -8733,213 +8733,6 @@ MTR_NEWLY_AVAILABLE @end -/** - * Cluster RVC Operational State - * - * This cluster supports remotely monitoring and, where supported, changing the operational state of a Robotic Vacuum. - */ -MTR_NEWLY_AVAILABLE -@interface MTRBaseClusterRVCOperationalState : MTRCluster - -- (instancetype _Nullable)initWithDevice:(MTRBaseDevice *)device - endpointID:(NSNumber *)endpointID - queue:(dispatch_queue_t)queue NS_DESIGNATED_INITIALIZER MTR_NEWLY_AVAILABLE; - -/** - * Command Pause - * - * Upon receipt, the device SHALL pause its operation if it is possible based on the current function of the server. - */ -- (void)pauseWithParams:(MTRRVCOperationalStateClusterPauseParams * _Nullable)params - completion:(void (^)(MTRRVCOperationalStateClusterOperationalCommandResponseParams * _Nullable data, - NSError * _Nullable error))completion MTR_NEWLY_AVAILABLE; -- (void)pauseWithCompletion:(void (^)(MTRRVCOperationalStateClusterOperationalCommandResponseParams * _Nullable data, - NSError * _Nullable error))completion MTR_NEWLY_AVAILABLE; -/** - * Command Stop - * - * Upon receipt, the device SHALL stop its operation if it is at a position where it is safe to do so and/or permitted. - */ -- (void)stopWithParams:(MTRRVCOperationalStateClusterStopParams * _Nullable)params - completion:(void (^)(MTRRVCOperationalStateClusterOperationalCommandResponseParams * _Nullable data, - NSError * _Nullable error))completion MTR_NEWLY_AVAILABLE; -- (void)stopWithCompletion:(void (^)(MTRRVCOperationalStateClusterOperationalCommandResponseParams * _Nullable data, - NSError * _Nullable error))completion MTR_NEWLY_AVAILABLE; -/** - * Command Start - * - * Upon receipt, the device SHALL start its operation if it is safe to do so and the device is in an operational state from which it - * can be started. - */ -- (void)startWithParams:(MTRRVCOperationalStateClusterStartParams * _Nullable)params - completion:(void (^)(MTRRVCOperationalStateClusterOperationalCommandResponseParams * _Nullable data, - NSError * _Nullable error))completion MTR_NEWLY_AVAILABLE; -- (void)startWithCompletion:(void (^)(MTRRVCOperationalStateClusterOperationalCommandResponseParams * _Nullable data, - NSError * _Nullable error))completion MTR_NEWLY_AVAILABLE; -/** - * Command Resume - * - * Upon receipt, the device SHALL resume its operation from the point it was at when it received the Pause command, or from the - * point when it was paused by means outside of this cluster (for example by manual button press). - */ -- (void)resumeWithParams:(MTRRVCOperationalStateClusterResumeParams * _Nullable)params - completion:(void (^)(MTRRVCOperationalStateClusterOperationalCommandResponseParams * _Nullable data, - NSError * _Nullable error))completion MTR_NEWLY_AVAILABLE; -- (void)resumeWithCompletion:(void (^)(MTRRVCOperationalStateClusterOperationalCommandResponseParams * _Nullable data, - NSError * _Nullable error))completion MTR_NEWLY_AVAILABLE; - -- (void)readAttributePhaseListWithCompletion:(void (^)(NSArray * _Nullable value, NSError * _Nullable error))completion - MTR_NEWLY_AVAILABLE; -- (void)subscribeAttributePhaseListWithParams:(MTRSubscribeParams *)params - subscriptionEstablished:(MTRSubscriptionEstablishedHandler _Nullable)subscriptionEstablished - reportHandler:(void (^)(NSArray * _Nullable value, NSError * _Nullable error))reportHandler - MTR_NEWLY_AVAILABLE; -+ (void)readAttributePhaseListWithClusterStateCache:(MTRClusterStateCacheContainer *)clusterStateCacheContainer - endpoint:(NSNumber *)endpoint - queue:(dispatch_queue_t)queue - completion:(void (^)(NSArray * _Nullable value, NSError * _Nullable error))completion - MTR_NEWLY_AVAILABLE; - -- (void)readAttributeCurrentPhaseWithCompletion:(void (^)(NSNumber * _Nullable value, NSError * _Nullable error))completion - MTR_NEWLY_AVAILABLE; -- (void)subscribeAttributeCurrentPhaseWithParams:(MTRSubscribeParams *)params - subscriptionEstablished:(MTRSubscriptionEstablishedHandler _Nullable)subscriptionEstablished - reportHandler:(void (^)(NSNumber * _Nullable value, NSError * _Nullable error))reportHandler - MTR_NEWLY_AVAILABLE; -+ (void)readAttributeCurrentPhaseWithClusterStateCache:(MTRClusterStateCacheContainer *)clusterStateCacheContainer - endpoint:(NSNumber *)endpoint - queue:(dispatch_queue_t)queue - completion:(void (^)(NSNumber * _Nullable value, NSError * _Nullable error))completion - MTR_NEWLY_AVAILABLE; - -- (void)readAttributeCountdownTimeWithCompletion:(void (^)(NSNumber * _Nullable value, NSError * _Nullable error))completion - MTR_NEWLY_AVAILABLE; -- (void)subscribeAttributeCountdownTimeWithParams:(MTRSubscribeParams *)params - subscriptionEstablished:(MTRSubscriptionEstablishedHandler _Nullable)subscriptionEstablished - reportHandler:(void (^)(NSNumber * _Nullable value, NSError * _Nullable error))reportHandler - MTR_NEWLY_AVAILABLE; -+ (void)readAttributeCountdownTimeWithClusterStateCache:(MTRClusterStateCacheContainer *)clusterStateCacheContainer - endpoint:(NSNumber *)endpoint - queue:(dispatch_queue_t)queue - completion:(void (^)(NSNumber * _Nullable value, NSError * _Nullable error))completion - MTR_NEWLY_AVAILABLE; - -- (void)readAttributeOperationalStateListWithCompletion:(void (^)(NSArray * _Nullable value, NSError * _Nullable error))completion - MTR_NEWLY_AVAILABLE; -- (void)subscribeAttributeOperationalStateListWithParams:(MTRSubscribeParams *)params - subscriptionEstablished:(MTRSubscriptionEstablishedHandler _Nullable)subscriptionEstablished - reportHandler:(void (^)(NSArray * _Nullable value, - NSError * _Nullable error))reportHandler MTR_NEWLY_AVAILABLE; -+ (void)readAttributeOperationalStateListWithClusterStateCache:(MTRClusterStateCacheContainer *)clusterStateCacheContainer - endpoint:(NSNumber *)endpoint - queue:(dispatch_queue_t)queue - completion:(void (^)(NSArray * _Nullable value, - NSError * _Nullable error))completion MTR_NEWLY_AVAILABLE; - -- (void)readAttributeOperationalStateWithCompletion:(void (^)(MTRRVCOperationalStateClusterOperationalStateStruct * _Nullable value, - NSError * _Nullable error))completion MTR_NEWLY_AVAILABLE; -- (void)subscribeAttributeOperationalStateWithParams:(MTRSubscribeParams *)params - subscriptionEstablished:(MTRSubscriptionEstablishedHandler _Nullable)subscriptionEstablished - reportHandler: - (void (^)(MTRRVCOperationalStateClusterOperationalStateStruct * _Nullable value, - NSError * _Nullable error))reportHandler MTR_NEWLY_AVAILABLE; -+ (void)readAttributeOperationalStateWithClusterStateCache:(MTRClusterStateCacheContainer *)clusterStateCacheContainer - endpoint:(NSNumber *)endpoint - queue:(dispatch_queue_t)queue - completion: - (void (^)(MTRRVCOperationalStateClusterOperationalStateStruct * _Nullable value, - NSError * _Nullable error))completion MTR_NEWLY_AVAILABLE; - -- (void)readAttributeOperationalErrorWithCompletion:(void (^)(MTRRVCOperationalStateClusterErrorStateStruct * _Nullable value, - NSError * _Nullable error))completion MTR_NEWLY_AVAILABLE; -- (void)subscribeAttributeOperationalErrorWithParams:(MTRSubscribeParams *)params - subscriptionEstablished:(MTRSubscriptionEstablishedHandler _Nullable)subscriptionEstablished - reportHandler:(void (^)(MTRRVCOperationalStateClusterErrorStateStruct * _Nullable value, - NSError * _Nullable error))reportHandler MTR_NEWLY_AVAILABLE; -+ (void)readAttributeOperationalErrorWithClusterStateCache:(MTRClusterStateCacheContainer *)clusterStateCacheContainer - endpoint:(NSNumber *)endpoint - queue:(dispatch_queue_t)queue - completion: - (void (^)(MTRRVCOperationalStateClusterErrorStateStruct * _Nullable value, - NSError * _Nullable error))completion MTR_NEWLY_AVAILABLE; - -- (void)readAttributeGeneratedCommandListWithCompletion:(void (^)(NSArray * _Nullable value, NSError * _Nullable error))completion - MTR_NEWLY_AVAILABLE; -- (void)subscribeAttributeGeneratedCommandListWithParams:(MTRSubscribeParams *)params - subscriptionEstablished:(MTRSubscriptionEstablishedHandler _Nullable)subscriptionEstablished - reportHandler:(void (^)(NSArray * _Nullable value, - NSError * _Nullable error))reportHandler MTR_NEWLY_AVAILABLE; -+ (void)readAttributeGeneratedCommandListWithClusterStateCache:(MTRClusterStateCacheContainer *)clusterStateCacheContainer - endpoint:(NSNumber *)endpoint - queue:(dispatch_queue_t)queue - completion:(void (^)(NSArray * _Nullable value, - NSError * _Nullable error))completion MTR_NEWLY_AVAILABLE; - -- (void)readAttributeAcceptedCommandListWithCompletion:(void (^)(NSArray * _Nullable value, NSError * _Nullable error))completion - MTR_NEWLY_AVAILABLE; -- (void)subscribeAttributeAcceptedCommandListWithParams:(MTRSubscribeParams *)params - subscriptionEstablished:(MTRSubscriptionEstablishedHandler _Nullable)subscriptionEstablished - reportHandler:(void (^)(NSArray * _Nullable value, - NSError * _Nullable error))reportHandler MTR_NEWLY_AVAILABLE; -+ (void)readAttributeAcceptedCommandListWithClusterStateCache:(MTRClusterStateCacheContainer *)clusterStateCacheContainer - endpoint:(NSNumber *)endpoint - queue:(dispatch_queue_t)queue - completion:(void (^)(NSArray * _Nullable value, - NSError * _Nullable error))completion MTR_NEWLY_AVAILABLE; - -- (void)readAttributeEventListWithCompletion:(void (^)(NSArray * _Nullable value, NSError * _Nullable error))completion - MTR_NEWLY_AVAILABLE; -- (void)subscribeAttributeEventListWithParams:(MTRSubscribeParams *)params - subscriptionEstablished:(MTRSubscriptionEstablishedHandler _Nullable)subscriptionEstablished - reportHandler:(void (^)(NSArray * _Nullable value, NSError * _Nullable error))reportHandler - MTR_NEWLY_AVAILABLE; -+ (void)readAttributeEventListWithClusterStateCache:(MTRClusterStateCacheContainer *)clusterStateCacheContainer - endpoint:(NSNumber *)endpoint - queue:(dispatch_queue_t)queue - completion:(void (^)(NSArray * _Nullable value, NSError * _Nullable error))completion - MTR_NEWLY_AVAILABLE; - -- (void)readAttributeAttributeListWithCompletion:(void (^)(NSArray * _Nullable value, NSError * _Nullable error))completion - MTR_NEWLY_AVAILABLE; -- (void)subscribeAttributeAttributeListWithParams:(MTRSubscribeParams *)params - subscriptionEstablished:(MTRSubscriptionEstablishedHandler _Nullable)subscriptionEstablished - reportHandler:(void (^)(NSArray * _Nullable value, NSError * _Nullable error))reportHandler - MTR_NEWLY_AVAILABLE; -+ (void)readAttributeAttributeListWithClusterStateCache:(MTRClusterStateCacheContainer *)clusterStateCacheContainer - endpoint:(NSNumber *)endpoint - queue:(dispatch_queue_t)queue - completion:(void (^)(NSArray * _Nullable value, NSError * _Nullable error))completion - MTR_NEWLY_AVAILABLE; - -- (void)readAttributeFeatureMapWithCompletion:(void (^)(NSNumber * _Nullable value, NSError * _Nullable error))completion - MTR_NEWLY_AVAILABLE; -- (void)subscribeAttributeFeatureMapWithParams:(MTRSubscribeParams *)params - subscriptionEstablished:(MTRSubscriptionEstablishedHandler _Nullable)subscriptionEstablished - reportHandler:(void (^)(NSNumber * _Nullable value, NSError * _Nullable error))reportHandler - MTR_NEWLY_AVAILABLE; -+ (void)readAttributeFeatureMapWithClusterStateCache:(MTRClusterStateCacheContainer *)clusterStateCacheContainer - endpoint:(NSNumber *)endpoint - queue:(dispatch_queue_t)queue - completion:(void (^)(NSNumber * _Nullable value, NSError * _Nullable error))completion - MTR_NEWLY_AVAILABLE; - -- (void)readAttributeClusterRevisionWithCompletion:(void (^)(NSNumber * _Nullable value, NSError * _Nullable error))completion - MTR_NEWLY_AVAILABLE; -- (void)subscribeAttributeClusterRevisionWithParams:(MTRSubscribeParams *)params - subscriptionEstablished:(MTRSubscriptionEstablishedHandler _Nullable)subscriptionEstablished - reportHandler:(void (^)(NSNumber * _Nullable value, NSError * _Nullable error))reportHandler - MTR_NEWLY_AVAILABLE; -+ (void)readAttributeClusterRevisionWithClusterStateCache:(MTRClusterStateCacheContainer *)clusterStateCacheContainer - endpoint:(NSNumber *)endpoint - queue:(dispatch_queue_t)queue - completion:(void (^)(NSNumber * _Nullable value, - NSError * _Nullable error))completion MTR_NEWLY_AVAILABLE; - -- (instancetype)init NS_UNAVAILABLE; -+ (instancetype)new NS_UNAVAILABLE; - -@end - /** * Cluster HEPA Filter Monitoring * @@ -24643,23 +24436,6 @@ typedef NS_ENUM(uint8_t, MTROperationalState) { MTROperationalStateError MTR_NEWLY_AVAILABLE = 0x03, } MTR_NEWLY_AVAILABLE; -typedef NS_ENUM(uint8_t, MTRRVCOperationalStateErrorState) { - MTRRVCOperationalStateErrorStateFailedToFindChargingDock MTR_NEWLY_AVAILABLE = 0x40, - MTRRVCOperationalStateErrorStateStuck MTR_NEWLY_AVAILABLE = 0x41, - MTRRVCOperationalStateErrorStateDustBinMissing MTR_NEWLY_AVAILABLE = 0x42, - MTRRVCOperationalStateErrorStateDustBinFull MTR_NEWLY_AVAILABLE = 0x43, - MTRRVCOperationalStateErrorStateWaterTankEmpty MTR_NEWLY_AVAILABLE = 0x44, - MTRRVCOperationalStateErrorStateWaterTankMissing MTR_NEWLY_AVAILABLE = 0x45, - MTRRVCOperationalStateErrorStateWaterTankLidOpen MTR_NEWLY_AVAILABLE = 0x46, - MTRRVCOperationalStateErrorStateMopCleaningPadMissing MTR_NEWLY_AVAILABLE = 0x47, -} MTR_NEWLY_AVAILABLE; - -typedef NS_ENUM(uint8_t, MTRRVCOperationalStateOperationalState) { - MTRRVCOperationalStateOperationalStateSeekingCharger MTR_NEWLY_AVAILABLE = 0x40, - MTRRVCOperationalStateOperationalStateCharging MTR_NEWLY_AVAILABLE = 0x41, - MTRRVCOperationalStateOperationalStateDocked MTR_NEWLY_AVAILABLE = 0x42, -} MTR_NEWLY_AVAILABLE; - typedef NS_ENUM(uint8_t, MTRHEPAFilterMonitoringChangeIndication) { MTRHEPAFilterMonitoringChangeIndicationOK MTR_NEWLY_AVAILABLE = 0x00, MTRHEPAFilterMonitoringChangeIndicationWarning MTR_NEWLY_AVAILABLE = 0x01, diff --git a/src/darwin/Framework/CHIP/zap-generated/MTRBaseClusters.mm b/src/darwin/Framework/CHIP/zap-generated/MTRBaseClusters.mm index eb201d04621037..cdf9f56791411a 100644 --- a/src/darwin/Framework/CHIP/zap-generated/MTRBaseClusters.mm +++ b/src/darwin/Framework/CHIP/zap-generated/MTRBaseClusters.mm @@ -50705,715 +50705,6 @@ + (void)readAttributeClusterRevisionWithClusterStateCache:(MTRClusterStateCacheC @end -@implementation MTRBaseClusterRVCOperationalState - -- (instancetype)initWithDevice:(MTRBaseDevice *)device endpointID:(NSNumber *)endpointID queue:(dispatch_queue_t)queue -{ - if (self = [super initWithQueue:queue]) { - if (device == nil) { - return nil; - } - - _device = device; - _endpoint = [endpointID unsignedShortValue]; - } - return self; -} - -- (void)pauseWithCompletion:(void (^)(MTRRVCOperationalStateClusterOperationalCommandResponseParams * _Nullable data, - NSError * _Nullable error))completion -{ - [self pauseWithParams:nil completion:completion]; -} -- (void)pauseWithParams:(MTRRVCOperationalStateClusterPauseParams * _Nullable)params - completion:(void (^)(MTRRVCOperationalStateClusterOperationalCommandResponseParams * _Nullable data, - NSError * _Nullable error))completion -{ - // Make a copy of params before we go async. - params = [params copy]; - auto * bridge = new MTRRVCOperationalStateClusterOperationalCommandResponseCallbackBridge(self.callbackQueue, completion, - ^(ExchangeManager & exchangeManager, const SessionHandle & session, - RVCOperationalStateClusterOperationalCommandResponseCallbackType successCb, MTRErrorCallback failureCb, - MTRCallbackBridgeBase * bridge) { - auto * typedBridge = static_cast(bridge); - Optional timedInvokeTimeoutMs; - Optional invokeTimeout; - ListFreer listFreer; - RvcOperationalState::Commands::Pause::Type request; - if (params != nil) { - if (params.timedInvokeTimeoutMs != nil) { - params.timedInvokeTimeoutMs = MTRClampedNumber(params.timedInvokeTimeoutMs, @(1), @(UINT16_MAX)); - timedInvokeTimeoutMs.SetValue(params.timedInvokeTimeoutMs.unsignedShortValue); - } - if (params.serverSideProcessingTimeout != nil) { - // Clamp to a number of seconds that will not overflow 32-bit - // int when converted to ms. - auto * serverSideProcessingTimeout = MTRClampedNumber(params.serverSideProcessingTimeout, @(0), @(UINT16_MAX)); - invokeTimeout.SetValue(Seconds16(serverSideProcessingTimeout.unsignedShortValue)); - } - } - - return MTRStartInvokeInteraction(typedBridge, request, exchangeManager, session, successCb, failureCb, self->_endpoint, - timedInvokeTimeoutMs, invokeTimeout); - }); - std::move(*bridge).DispatchAction(self.device); -} - -- (void)stopWithCompletion:(void (^)(MTRRVCOperationalStateClusterOperationalCommandResponseParams * _Nullable data, - NSError * _Nullable error))completion -{ - [self stopWithParams:nil completion:completion]; -} -- (void)stopWithParams:(MTRRVCOperationalStateClusterStopParams * _Nullable)params - completion:(void (^)(MTRRVCOperationalStateClusterOperationalCommandResponseParams * _Nullable data, - NSError * _Nullable error))completion -{ - // Make a copy of params before we go async. - params = [params copy]; - auto * bridge = new MTRRVCOperationalStateClusterOperationalCommandResponseCallbackBridge(self.callbackQueue, completion, - ^(ExchangeManager & exchangeManager, const SessionHandle & session, - RVCOperationalStateClusterOperationalCommandResponseCallbackType successCb, MTRErrorCallback failureCb, - MTRCallbackBridgeBase * bridge) { - auto * typedBridge = static_cast(bridge); - Optional timedInvokeTimeoutMs; - Optional invokeTimeout; - ListFreer listFreer; - RvcOperationalState::Commands::Stop::Type request; - if (params != nil) { - if (params.timedInvokeTimeoutMs != nil) { - params.timedInvokeTimeoutMs = MTRClampedNumber(params.timedInvokeTimeoutMs, @(1), @(UINT16_MAX)); - timedInvokeTimeoutMs.SetValue(params.timedInvokeTimeoutMs.unsignedShortValue); - } - if (params.serverSideProcessingTimeout != nil) { - // Clamp to a number of seconds that will not overflow 32-bit - // int when converted to ms. - auto * serverSideProcessingTimeout = MTRClampedNumber(params.serverSideProcessingTimeout, @(0), @(UINT16_MAX)); - invokeTimeout.SetValue(Seconds16(serverSideProcessingTimeout.unsignedShortValue)); - } - } - - return MTRStartInvokeInteraction(typedBridge, request, exchangeManager, session, successCb, failureCb, self->_endpoint, - timedInvokeTimeoutMs, invokeTimeout); - }); - std::move(*bridge).DispatchAction(self.device); -} - -- (void)startWithCompletion:(void (^)(MTRRVCOperationalStateClusterOperationalCommandResponseParams * _Nullable data, - NSError * _Nullable error))completion -{ - [self startWithParams:nil completion:completion]; -} -- (void)startWithParams:(MTRRVCOperationalStateClusterStartParams * _Nullable)params - completion:(void (^)(MTRRVCOperationalStateClusterOperationalCommandResponseParams * _Nullable data, - NSError * _Nullable error))completion -{ - // Make a copy of params before we go async. - params = [params copy]; - auto * bridge = new MTRRVCOperationalStateClusterOperationalCommandResponseCallbackBridge(self.callbackQueue, completion, - ^(ExchangeManager & exchangeManager, const SessionHandle & session, - RVCOperationalStateClusterOperationalCommandResponseCallbackType successCb, MTRErrorCallback failureCb, - MTRCallbackBridgeBase * bridge) { - auto * typedBridge = static_cast(bridge); - Optional timedInvokeTimeoutMs; - Optional invokeTimeout; - ListFreer listFreer; - RvcOperationalState::Commands::Start::Type request; - if (params != nil) { - if (params.timedInvokeTimeoutMs != nil) { - params.timedInvokeTimeoutMs = MTRClampedNumber(params.timedInvokeTimeoutMs, @(1), @(UINT16_MAX)); - timedInvokeTimeoutMs.SetValue(params.timedInvokeTimeoutMs.unsignedShortValue); - } - if (params.serverSideProcessingTimeout != nil) { - // Clamp to a number of seconds that will not overflow 32-bit - // int when converted to ms. - auto * serverSideProcessingTimeout = MTRClampedNumber(params.serverSideProcessingTimeout, @(0), @(UINT16_MAX)); - invokeTimeout.SetValue(Seconds16(serverSideProcessingTimeout.unsignedShortValue)); - } - } - - return MTRStartInvokeInteraction(typedBridge, request, exchangeManager, session, successCb, failureCb, self->_endpoint, - timedInvokeTimeoutMs, invokeTimeout); - }); - std::move(*bridge).DispatchAction(self.device); -} - -- (void)resumeWithCompletion:(void (^)(MTRRVCOperationalStateClusterOperationalCommandResponseParams * _Nullable data, - NSError * _Nullable error))completion -{ - [self resumeWithParams:nil completion:completion]; -} -- (void)resumeWithParams:(MTRRVCOperationalStateClusterResumeParams * _Nullable)params - completion:(void (^)(MTRRVCOperationalStateClusterOperationalCommandResponseParams * _Nullable data, - NSError * _Nullable error))completion -{ - // Make a copy of params before we go async. - params = [params copy]; - auto * bridge = new MTRRVCOperationalStateClusterOperationalCommandResponseCallbackBridge(self.callbackQueue, completion, - ^(ExchangeManager & exchangeManager, const SessionHandle & session, - RVCOperationalStateClusterOperationalCommandResponseCallbackType successCb, MTRErrorCallback failureCb, - MTRCallbackBridgeBase * bridge) { - auto * typedBridge = static_cast(bridge); - Optional timedInvokeTimeoutMs; - Optional invokeTimeout; - ListFreer listFreer; - RvcOperationalState::Commands::Resume::Type request; - if (params != nil) { - if (params.timedInvokeTimeoutMs != nil) { - params.timedInvokeTimeoutMs = MTRClampedNumber(params.timedInvokeTimeoutMs, @(1), @(UINT16_MAX)); - timedInvokeTimeoutMs.SetValue(params.timedInvokeTimeoutMs.unsignedShortValue); - } - if (params.serverSideProcessingTimeout != nil) { - // Clamp to a number of seconds that will not overflow 32-bit - // int when converted to ms. - auto * serverSideProcessingTimeout = MTRClampedNumber(params.serverSideProcessingTimeout, @(0), @(UINT16_MAX)); - invokeTimeout.SetValue(Seconds16(serverSideProcessingTimeout.unsignedShortValue)); - } - } - - return MTRStartInvokeInteraction(typedBridge, request, exchangeManager, session, successCb, failureCb, self->_endpoint, - timedInvokeTimeoutMs, invokeTimeout); - }); - std::move(*bridge).DispatchAction(self.device); -} - -- (void)readAttributePhaseListWithCompletion:(void (^)(NSArray * _Nullable value, NSError * _Nullable error))completion -{ - MTRReadParams * params = [[MTRReadParams alloc] init]; - using TypeInfo = RvcOperationalState::Attributes::PhaseList::TypeInfo; - return MTRReadAttribute( - params, completion, self.callbackQueue, self.device, self->_endpoint, TypeInfo::GetClusterId(), TypeInfo::GetAttributeId()); -} - -- (void)subscribeAttributePhaseListWithParams:(MTRSubscribeParams * _Nonnull)params - subscriptionEstablished:(MTRSubscriptionEstablishedHandler _Nullable)subscriptionEstablished - reportHandler:(void (^)(NSArray * _Nullable value, NSError * _Nullable error))reportHandler -{ - using TypeInfo = RvcOperationalState::Attributes::PhaseList::TypeInfo; - MTRSubscribeAttribute( - params, subscriptionEstablished, reportHandler, self.callbackQueue, self.device, self->_endpoint, TypeInfo::GetClusterId(), - TypeInfo::GetAttributeId()); -} - -+ (void)readAttributePhaseListWithClusterStateCache:(MTRClusterStateCacheContainer *)clusterStateCacheContainer - endpoint:(NSNumber *)endpoint - queue:(dispatch_queue_t)queue - completion:(void (^)(NSArray * _Nullable value, NSError * _Nullable error))completion -{ - auto * bridge = new MTRRVCOperationalStatePhaseListListAttributeCallbackBridge(queue, completion); - std::move(*bridge).DispatchLocalAction(clusterStateCacheContainer.baseDevice, - ^(RVCOperationalStatePhaseListListAttributeCallback successCb, MTRErrorCallback failureCb) { - if (clusterStateCacheContainer.cppClusterStateCache) { - chip::app::ConcreteAttributePath path; - using TypeInfo = RvcOperationalState::Attributes::PhaseList::TypeInfo; - path.mEndpointId = static_cast([endpoint unsignedShortValue]); - path.mClusterId = TypeInfo::GetClusterId(); - path.mAttributeId = TypeInfo::GetAttributeId(); - TypeInfo::DecodableType value; - CHIP_ERROR err = clusterStateCacheContainer.cppClusterStateCache->Get(path, value); - if (err == CHIP_NO_ERROR) { - successCb(bridge, value); - } - return err; - } - return CHIP_ERROR_NOT_FOUND; - }); -} - -- (void)readAttributeCurrentPhaseWithCompletion:(void (^)(NSNumber * _Nullable value, NSError * _Nullable error))completion -{ - MTRReadParams * params = [[MTRReadParams alloc] init]; - using TypeInfo = RvcOperationalState::Attributes::CurrentPhase::TypeInfo; - return MTRReadAttribute( - params, completion, self.callbackQueue, self.device, self->_endpoint, TypeInfo::GetClusterId(), TypeInfo::GetAttributeId()); -} - -- (void)subscribeAttributeCurrentPhaseWithParams:(MTRSubscribeParams * _Nonnull)params - subscriptionEstablished:(MTRSubscriptionEstablishedHandler _Nullable)subscriptionEstablished - reportHandler:(void (^)(NSNumber * _Nullable value, NSError * _Nullable error))reportHandler -{ - using TypeInfo = RvcOperationalState::Attributes::CurrentPhase::TypeInfo; - MTRSubscribeAttribute(params, - subscriptionEstablished, reportHandler, self.callbackQueue, self.device, self->_endpoint, TypeInfo::GetClusterId(), - TypeInfo::GetAttributeId()); -} - -+ (void)readAttributeCurrentPhaseWithClusterStateCache:(MTRClusterStateCacheContainer *)clusterStateCacheContainer - endpoint:(NSNumber *)endpoint - queue:(dispatch_queue_t)queue - completion:(void (^)(NSNumber * _Nullable value, NSError * _Nullable error))completion -{ - auto * bridge = new MTRNullableInt8uAttributeCallbackBridge(queue, completion); - std::move(*bridge).DispatchLocalAction( - clusterStateCacheContainer.baseDevice, ^(NullableInt8uAttributeCallback successCb, MTRErrorCallback failureCb) { - if (clusterStateCacheContainer.cppClusterStateCache) { - chip::app::ConcreteAttributePath path; - using TypeInfo = RvcOperationalState::Attributes::CurrentPhase::TypeInfo; - path.mEndpointId = static_cast([endpoint unsignedShortValue]); - path.mClusterId = TypeInfo::GetClusterId(); - path.mAttributeId = TypeInfo::GetAttributeId(); - TypeInfo::DecodableType value; - CHIP_ERROR err = clusterStateCacheContainer.cppClusterStateCache->Get(path, value); - if (err == CHIP_NO_ERROR) { - successCb(bridge, value); - } - return err; - } - return CHIP_ERROR_NOT_FOUND; - }); -} - -- (void)readAttributeCountdownTimeWithCompletion:(void (^)(NSNumber * _Nullable value, NSError * _Nullable error))completion -{ - MTRReadParams * params = [[MTRReadParams alloc] init]; - using TypeInfo = RvcOperationalState::Attributes::CountdownTime::TypeInfo; - return MTRReadAttribute( - params, completion, self.callbackQueue, self.device, self->_endpoint, TypeInfo::GetClusterId(), TypeInfo::GetAttributeId()); -} - -- (void)subscribeAttributeCountdownTimeWithParams:(MTRSubscribeParams * _Nonnull)params - subscriptionEstablished:(MTRSubscriptionEstablishedHandler _Nullable)subscriptionEstablished - reportHandler:(void (^)(NSNumber * _Nullable value, NSError * _Nullable error))reportHandler -{ - using TypeInfo = RvcOperationalState::Attributes::CountdownTime::TypeInfo; - MTRSubscribeAttribute(params, - subscriptionEstablished, reportHandler, self.callbackQueue, self.device, self->_endpoint, TypeInfo::GetClusterId(), - TypeInfo::GetAttributeId()); -} - -+ (void)readAttributeCountdownTimeWithClusterStateCache:(MTRClusterStateCacheContainer *)clusterStateCacheContainer - endpoint:(NSNumber *)endpoint - queue:(dispatch_queue_t)queue - completion:(void (^)(NSNumber * _Nullable value, NSError * _Nullable error))completion -{ - auto * bridge = new MTRNullableInt32uAttributeCallbackBridge(queue, completion); - std::move(*bridge).DispatchLocalAction( - clusterStateCacheContainer.baseDevice, ^(NullableInt32uAttributeCallback successCb, MTRErrorCallback failureCb) { - if (clusterStateCacheContainer.cppClusterStateCache) { - chip::app::ConcreteAttributePath path; - using TypeInfo = RvcOperationalState::Attributes::CountdownTime::TypeInfo; - path.mEndpointId = static_cast([endpoint unsignedShortValue]); - path.mClusterId = TypeInfo::GetClusterId(); - path.mAttributeId = TypeInfo::GetAttributeId(); - TypeInfo::DecodableType value; - CHIP_ERROR err = clusterStateCacheContainer.cppClusterStateCache->Get(path, value); - if (err == CHIP_NO_ERROR) { - successCb(bridge, value); - } - return err; - } - return CHIP_ERROR_NOT_FOUND; - }); -} - -- (void)readAttributeOperationalStateListWithCompletion:(void (^)(NSArray * _Nullable value, NSError * _Nullable error))completion -{ - MTRReadParams * params = [[MTRReadParams alloc] init]; - using TypeInfo = RvcOperationalState::Attributes::OperationalStateList::TypeInfo; - return MTRReadAttribute( - params, completion, self.callbackQueue, self.device, self->_endpoint, TypeInfo::GetClusterId(), TypeInfo::GetAttributeId()); -} - -- (void)subscribeAttributeOperationalStateListWithParams:(MTRSubscribeParams * _Nonnull)params - subscriptionEstablished:(MTRSubscriptionEstablishedHandler _Nullable)subscriptionEstablished - reportHandler: - (void (^)(NSArray * _Nullable value, NSError * _Nullable error))reportHandler -{ - using TypeInfo = RvcOperationalState::Attributes::OperationalStateList::TypeInfo; - MTRSubscribeAttribute(params, subscriptionEstablished, reportHandler, self.callbackQueue, self.device, self->_endpoint, - TypeInfo::GetClusterId(), TypeInfo::GetAttributeId()); -} - -+ (void)readAttributeOperationalStateListWithClusterStateCache:(MTRClusterStateCacheContainer *)clusterStateCacheContainer - endpoint:(NSNumber *)endpoint - queue:(dispatch_queue_t)queue - completion: - (void (^)(NSArray * _Nullable value, NSError * _Nullable error))completion -{ - auto * bridge = new MTRRVCOperationalStateOperationalStateListListAttributeCallbackBridge(queue, completion); - std::move(*bridge).DispatchLocalAction(clusterStateCacheContainer.baseDevice, - ^(RVCOperationalStateOperationalStateListListAttributeCallback successCb, MTRErrorCallback failureCb) { - if (clusterStateCacheContainer.cppClusterStateCache) { - chip::app::ConcreteAttributePath path; - using TypeInfo = RvcOperationalState::Attributes::OperationalStateList::TypeInfo; - path.mEndpointId = static_cast([endpoint unsignedShortValue]); - path.mClusterId = TypeInfo::GetClusterId(); - path.mAttributeId = TypeInfo::GetAttributeId(); - TypeInfo::DecodableType value; - CHIP_ERROR err = clusterStateCacheContainer.cppClusterStateCache->Get(path, value); - if (err == CHIP_NO_ERROR) { - successCb(bridge, value); - } - return err; - } - return CHIP_ERROR_NOT_FOUND; - }); -} - -- (void)readAttributeOperationalStateWithCompletion:(void (^)(MTRRVCOperationalStateClusterOperationalStateStruct * _Nullable value, - NSError * _Nullable error))completion -{ - MTRReadParams * params = [[MTRReadParams alloc] init]; - using TypeInfo = RvcOperationalState::Attributes::OperationalState::TypeInfo; - return MTRReadAttribute( - params, completion, self.callbackQueue, self.device, self->_endpoint, TypeInfo::GetClusterId(), TypeInfo::GetAttributeId()); -} - -- (void)subscribeAttributeOperationalStateWithParams:(MTRSubscribeParams * _Nonnull)params - subscriptionEstablished:(MTRSubscriptionEstablishedHandler _Nullable)subscriptionEstablished - reportHandler: - (void (^)(MTRRVCOperationalStateClusterOperationalStateStruct * _Nullable value, - NSError * _Nullable error))reportHandler -{ - using TypeInfo = RvcOperationalState::Attributes::OperationalState::TypeInfo; - MTRSubscribeAttribute(params, subscriptionEstablished, - reportHandler, self.callbackQueue, self.device, self->_endpoint, TypeInfo::GetClusterId(), TypeInfo::GetAttributeId()); -} - -+ (void)readAttributeOperationalStateWithClusterStateCache:(MTRClusterStateCacheContainer *)clusterStateCacheContainer - endpoint:(NSNumber *)endpoint - queue:(dispatch_queue_t)queue - completion: - (void (^)(MTRRVCOperationalStateClusterOperationalStateStruct * _Nullable value, - NSError * _Nullable error))completion -{ - auto * bridge = new MTRRVCOperationalStateOperationalStateStructAttributeCallbackBridge(queue, completion); - std::move(*bridge).DispatchLocalAction(clusterStateCacheContainer.baseDevice, - ^(RVCOperationalStateOperationalStateStructAttributeCallback successCb, MTRErrorCallback failureCb) { - if (clusterStateCacheContainer.cppClusterStateCache) { - chip::app::ConcreteAttributePath path; - using TypeInfo = RvcOperationalState::Attributes::OperationalState::TypeInfo; - path.mEndpointId = static_cast([endpoint unsignedShortValue]); - path.mClusterId = TypeInfo::GetClusterId(); - path.mAttributeId = TypeInfo::GetAttributeId(); - TypeInfo::DecodableType value; - CHIP_ERROR err = clusterStateCacheContainer.cppClusterStateCache->Get(path, value); - if (err == CHIP_NO_ERROR) { - successCb(bridge, value); - } - return err; - } - return CHIP_ERROR_NOT_FOUND; - }); -} - -- (void)readAttributeOperationalErrorWithCompletion:(void (^)(MTRRVCOperationalStateClusterErrorStateStruct * _Nullable value, - NSError * _Nullable error))completion -{ - MTRReadParams * params = [[MTRReadParams alloc] init]; - using TypeInfo = RvcOperationalState::Attributes::OperationalError::TypeInfo; - return MTRReadAttribute( - params, completion, self.callbackQueue, self.device, self->_endpoint, TypeInfo::GetClusterId(), TypeInfo::GetAttributeId()); -} - -- (void)subscribeAttributeOperationalErrorWithParams:(MTRSubscribeParams * _Nonnull)params - subscriptionEstablished:(MTRSubscriptionEstablishedHandler _Nullable)subscriptionEstablished - reportHandler:(void (^)(MTRRVCOperationalStateClusterErrorStateStruct * _Nullable value, - NSError * _Nullable error))reportHandler -{ - using TypeInfo = RvcOperationalState::Attributes::OperationalError::TypeInfo; - MTRSubscribeAttribute(params, subscriptionEstablished, reportHandler, - self.callbackQueue, self.device, self->_endpoint, TypeInfo::GetClusterId(), TypeInfo::GetAttributeId()); -} - -+ (void)readAttributeOperationalErrorWithClusterStateCache:(MTRClusterStateCacheContainer *)clusterStateCacheContainer - endpoint:(NSNumber *)endpoint - queue:(dispatch_queue_t)queue - completion: - (void (^)(MTRRVCOperationalStateClusterErrorStateStruct * _Nullable value, - NSError * _Nullable error))completion -{ - auto * bridge = new MTRRVCOperationalStateOperationalErrorStructAttributeCallbackBridge(queue, completion); - std::move(*bridge).DispatchLocalAction(clusterStateCacheContainer.baseDevice, - ^(RVCOperationalStateOperationalErrorStructAttributeCallback successCb, MTRErrorCallback failureCb) { - if (clusterStateCacheContainer.cppClusterStateCache) { - chip::app::ConcreteAttributePath path; - using TypeInfo = RvcOperationalState::Attributes::OperationalError::TypeInfo; - path.mEndpointId = static_cast([endpoint unsignedShortValue]); - path.mClusterId = TypeInfo::GetClusterId(); - path.mAttributeId = TypeInfo::GetAttributeId(); - TypeInfo::DecodableType value; - CHIP_ERROR err = clusterStateCacheContainer.cppClusterStateCache->Get(path, value); - if (err == CHIP_NO_ERROR) { - successCb(bridge, value); - } - return err; - } - return CHIP_ERROR_NOT_FOUND; - }); -} - -- (void)readAttributeGeneratedCommandListWithCompletion:(void (^)(NSArray * _Nullable value, NSError * _Nullable error))completion -{ - MTRReadParams * params = [[MTRReadParams alloc] init]; - using TypeInfo = RvcOperationalState::Attributes::GeneratedCommandList::TypeInfo; - return MTRReadAttribute( - params, completion, self.callbackQueue, self.device, self->_endpoint, TypeInfo::GetClusterId(), TypeInfo::GetAttributeId()); -} - -- (void)subscribeAttributeGeneratedCommandListWithParams:(MTRSubscribeParams * _Nonnull)params - subscriptionEstablished:(MTRSubscriptionEstablishedHandler _Nullable)subscriptionEstablished - reportHandler: - (void (^)(NSArray * _Nullable value, NSError * _Nullable error))reportHandler -{ - using TypeInfo = RvcOperationalState::Attributes::GeneratedCommandList::TypeInfo; - MTRSubscribeAttribute(params, subscriptionEstablished, reportHandler, self.callbackQueue, self.device, self->_endpoint, - TypeInfo::GetClusterId(), TypeInfo::GetAttributeId()); -} - -+ (void)readAttributeGeneratedCommandListWithClusterStateCache:(MTRClusterStateCacheContainer *)clusterStateCacheContainer - endpoint:(NSNumber *)endpoint - queue:(dispatch_queue_t)queue - completion: - (void (^)(NSArray * _Nullable value, NSError * _Nullable error))completion -{ - auto * bridge = new MTRRVCOperationalStateGeneratedCommandListListAttributeCallbackBridge(queue, completion); - std::move(*bridge).DispatchLocalAction(clusterStateCacheContainer.baseDevice, - ^(RVCOperationalStateGeneratedCommandListListAttributeCallback successCb, MTRErrorCallback failureCb) { - if (clusterStateCacheContainer.cppClusterStateCache) { - chip::app::ConcreteAttributePath path; - using TypeInfo = RvcOperationalState::Attributes::GeneratedCommandList::TypeInfo; - path.mEndpointId = static_cast([endpoint unsignedShortValue]); - path.mClusterId = TypeInfo::GetClusterId(); - path.mAttributeId = TypeInfo::GetAttributeId(); - TypeInfo::DecodableType value; - CHIP_ERROR err = clusterStateCacheContainer.cppClusterStateCache->Get(path, value); - if (err == CHIP_NO_ERROR) { - successCb(bridge, value); - } - return err; - } - return CHIP_ERROR_NOT_FOUND; - }); -} - -- (void)readAttributeAcceptedCommandListWithCompletion:(void (^)(NSArray * _Nullable value, NSError * _Nullable error))completion -{ - MTRReadParams * params = [[MTRReadParams alloc] init]; - using TypeInfo = RvcOperationalState::Attributes::AcceptedCommandList::TypeInfo; - return MTRReadAttribute( - params, completion, self.callbackQueue, self.device, self->_endpoint, TypeInfo::GetClusterId(), TypeInfo::GetAttributeId()); -} - -- (void)subscribeAttributeAcceptedCommandListWithParams:(MTRSubscribeParams * _Nonnull)params - subscriptionEstablished:(MTRSubscriptionEstablishedHandler _Nullable)subscriptionEstablished - reportHandler: - (void (^)(NSArray * _Nullable value, NSError * _Nullable error))reportHandler -{ - using TypeInfo = RvcOperationalState::Attributes::AcceptedCommandList::TypeInfo; - MTRSubscribeAttribute(params, subscriptionEstablished, reportHandler, self.callbackQueue, self.device, self->_endpoint, - TypeInfo::GetClusterId(), TypeInfo::GetAttributeId()); -} - -+ (void)readAttributeAcceptedCommandListWithClusterStateCache:(MTRClusterStateCacheContainer *)clusterStateCacheContainer - endpoint:(NSNumber *)endpoint - queue:(dispatch_queue_t)queue - completion: - (void (^)(NSArray * _Nullable value, NSError * _Nullable error))completion -{ - auto * bridge = new MTRRVCOperationalStateAcceptedCommandListListAttributeCallbackBridge(queue, completion); - std::move(*bridge).DispatchLocalAction(clusterStateCacheContainer.baseDevice, - ^(RVCOperationalStateAcceptedCommandListListAttributeCallback successCb, MTRErrorCallback failureCb) { - if (clusterStateCacheContainer.cppClusterStateCache) { - chip::app::ConcreteAttributePath path; - using TypeInfo = RvcOperationalState::Attributes::AcceptedCommandList::TypeInfo; - path.mEndpointId = static_cast([endpoint unsignedShortValue]); - path.mClusterId = TypeInfo::GetClusterId(); - path.mAttributeId = TypeInfo::GetAttributeId(); - TypeInfo::DecodableType value; - CHIP_ERROR err = clusterStateCacheContainer.cppClusterStateCache->Get(path, value); - if (err == CHIP_NO_ERROR) { - successCb(bridge, value); - } - return err; - } - return CHIP_ERROR_NOT_FOUND; - }); -} - -- (void)readAttributeEventListWithCompletion:(void (^)(NSArray * _Nullable value, NSError * _Nullable error))completion -{ - MTRReadParams * params = [[MTRReadParams alloc] init]; - using TypeInfo = RvcOperationalState::Attributes::EventList::TypeInfo; - return MTRReadAttribute( - params, completion, self.callbackQueue, self.device, self->_endpoint, TypeInfo::GetClusterId(), TypeInfo::GetAttributeId()); -} - -- (void)subscribeAttributeEventListWithParams:(MTRSubscribeParams * _Nonnull)params - subscriptionEstablished:(MTRSubscriptionEstablishedHandler _Nullable)subscriptionEstablished - reportHandler:(void (^)(NSArray * _Nullable value, NSError * _Nullable error))reportHandler -{ - using TypeInfo = RvcOperationalState::Attributes::EventList::TypeInfo; - MTRSubscribeAttribute( - params, subscriptionEstablished, reportHandler, self.callbackQueue, self.device, self->_endpoint, TypeInfo::GetClusterId(), - TypeInfo::GetAttributeId()); -} - -+ (void)readAttributeEventListWithClusterStateCache:(MTRClusterStateCacheContainer *)clusterStateCacheContainer - endpoint:(NSNumber *)endpoint - queue:(dispatch_queue_t)queue - completion:(void (^)(NSArray * _Nullable value, NSError * _Nullable error))completion -{ - auto * bridge = new MTRRVCOperationalStateEventListListAttributeCallbackBridge(queue, completion); - std::move(*bridge).DispatchLocalAction(clusterStateCacheContainer.baseDevice, - ^(RVCOperationalStateEventListListAttributeCallback successCb, MTRErrorCallback failureCb) { - if (clusterStateCacheContainer.cppClusterStateCache) { - chip::app::ConcreteAttributePath path; - using TypeInfo = RvcOperationalState::Attributes::EventList::TypeInfo; - path.mEndpointId = static_cast([endpoint unsignedShortValue]); - path.mClusterId = TypeInfo::GetClusterId(); - path.mAttributeId = TypeInfo::GetAttributeId(); - TypeInfo::DecodableType value; - CHIP_ERROR err = clusterStateCacheContainer.cppClusterStateCache->Get(path, value); - if (err == CHIP_NO_ERROR) { - successCb(bridge, value); - } - return err; - } - return CHIP_ERROR_NOT_FOUND; - }); -} - -- (void)readAttributeAttributeListWithCompletion:(void (^)(NSArray * _Nullable value, NSError * _Nullable error))completion -{ - MTRReadParams * params = [[MTRReadParams alloc] init]; - using TypeInfo = RvcOperationalState::Attributes::AttributeList::TypeInfo; - return MTRReadAttribute( - params, completion, self.callbackQueue, self.device, self->_endpoint, TypeInfo::GetClusterId(), TypeInfo::GetAttributeId()); -} - -- (void)subscribeAttributeAttributeListWithParams:(MTRSubscribeParams * _Nonnull)params - subscriptionEstablished:(MTRSubscriptionEstablishedHandler _Nullable)subscriptionEstablished - reportHandler:(void (^)(NSArray * _Nullable value, NSError * _Nullable error))reportHandler -{ - using TypeInfo = RvcOperationalState::Attributes::AttributeList::TypeInfo; - MTRSubscribeAttribute(params, subscriptionEstablished, reportHandler, self.callbackQueue, self.device, self->_endpoint, - TypeInfo::GetClusterId(), TypeInfo::GetAttributeId()); -} - -+ (void)readAttributeAttributeListWithClusterStateCache:(MTRClusterStateCacheContainer *)clusterStateCacheContainer - endpoint:(NSNumber *)endpoint - queue:(dispatch_queue_t)queue - completion:(void (^)(NSArray * _Nullable value, NSError * _Nullable error))completion -{ - auto * bridge = new MTRRVCOperationalStateAttributeListListAttributeCallbackBridge(queue, completion); - std::move(*bridge).DispatchLocalAction(clusterStateCacheContainer.baseDevice, - ^(RVCOperationalStateAttributeListListAttributeCallback successCb, MTRErrorCallback failureCb) { - if (clusterStateCacheContainer.cppClusterStateCache) { - chip::app::ConcreteAttributePath path; - using TypeInfo = RvcOperationalState::Attributes::AttributeList::TypeInfo; - path.mEndpointId = static_cast([endpoint unsignedShortValue]); - path.mClusterId = TypeInfo::GetClusterId(); - path.mAttributeId = TypeInfo::GetAttributeId(); - TypeInfo::DecodableType value; - CHIP_ERROR err = clusterStateCacheContainer.cppClusterStateCache->Get(path, value); - if (err == CHIP_NO_ERROR) { - successCb(bridge, value); - } - return err; - } - return CHIP_ERROR_NOT_FOUND; - }); -} - -- (void)readAttributeFeatureMapWithCompletion:(void (^)(NSNumber * _Nullable value, NSError * _Nullable error))completion -{ - MTRReadParams * params = [[MTRReadParams alloc] init]; - using TypeInfo = RvcOperationalState::Attributes::FeatureMap::TypeInfo; - return MTRReadAttribute( - params, completion, self.callbackQueue, self.device, self->_endpoint, TypeInfo::GetClusterId(), TypeInfo::GetAttributeId()); -} - -- (void)subscribeAttributeFeatureMapWithParams:(MTRSubscribeParams * _Nonnull)params - subscriptionEstablished:(MTRSubscriptionEstablishedHandler _Nullable)subscriptionEstablished - reportHandler:(void (^)(NSNumber * _Nullable value, NSError * _Nullable error))reportHandler -{ - using TypeInfo = RvcOperationalState::Attributes::FeatureMap::TypeInfo; - MTRSubscribeAttribute(params, - subscriptionEstablished, reportHandler, self.callbackQueue, self.device, self->_endpoint, TypeInfo::GetClusterId(), - TypeInfo::GetAttributeId()); -} - -+ (void)readAttributeFeatureMapWithClusterStateCache:(MTRClusterStateCacheContainer *)clusterStateCacheContainer - endpoint:(NSNumber *)endpoint - queue:(dispatch_queue_t)queue - completion:(void (^)(NSNumber * _Nullable value, NSError * _Nullable error))completion -{ - auto * bridge = new MTRInt32uAttributeCallbackBridge(queue, completion); - std::move(*bridge).DispatchLocalAction( - clusterStateCacheContainer.baseDevice, ^(Int32uAttributeCallback successCb, MTRErrorCallback failureCb) { - if (clusterStateCacheContainer.cppClusterStateCache) { - chip::app::ConcreteAttributePath path; - using TypeInfo = RvcOperationalState::Attributes::FeatureMap::TypeInfo; - path.mEndpointId = static_cast([endpoint unsignedShortValue]); - path.mClusterId = TypeInfo::GetClusterId(); - path.mAttributeId = TypeInfo::GetAttributeId(); - TypeInfo::DecodableType value; - CHIP_ERROR err = clusterStateCacheContainer.cppClusterStateCache->Get(path, value); - if (err == CHIP_NO_ERROR) { - successCb(bridge, value); - } - return err; - } - return CHIP_ERROR_NOT_FOUND; - }); -} - -- (void)readAttributeClusterRevisionWithCompletion:(void (^)(NSNumber * _Nullable value, NSError * _Nullable error))completion -{ - MTRReadParams * params = [[MTRReadParams alloc] init]; - using TypeInfo = RvcOperationalState::Attributes::ClusterRevision::TypeInfo; - return MTRReadAttribute( - params, completion, self.callbackQueue, self.device, self->_endpoint, TypeInfo::GetClusterId(), TypeInfo::GetAttributeId()); -} - -- (void)subscribeAttributeClusterRevisionWithParams:(MTRSubscribeParams * _Nonnull)params - subscriptionEstablished:(MTRSubscriptionEstablishedHandler _Nullable)subscriptionEstablished - reportHandler:(void (^)(NSNumber * _Nullable value, NSError * _Nullable error))reportHandler -{ - using TypeInfo = RvcOperationalState::Attributes::ClusterRevision::TypeInfo; - MTRSubscribeAttribute(params, - subscriptionEstablished, reportHandler, self.callbackQueue, self.device, self->_endpoint, TypeInfo::GetClusterId(), - TypeInfo::GetAttributeId()); -} - -+ (void)readAttributeClusterRevisionWithClusterStateCache:(MTRClusterStateCacheContainer *)clusterStateCacheContainer - endpoint:(NSNumber *)endpoint - queue:(dispatch_queue_t)queue - completion: - (void (^)(NSNumber * _Nullable value, NSError * _Nullable error))completion -{ - auto * bridge = new MTRInt16uAttributeCallbackBridge(queue, completion); - std::move(*bridge).DispatchLocalAction( - clusterStateCacheContainer.baseDevice, ^(Int16uAttributeCallback successCb, MTRErrorCallback failureCb) { - if (clusterStateCacheContainer.cppClusterStateCache) { - chip::app::ConcreteAttributePath path; - using TypeInfo = RvcOperationalState::Attributes::ClusterRevision::TypeInfo; - path.mEndpointId = static_cast([endpoint unsignedShortValue]); - path.mClusterId = TypeInfo::GetClusterId(); - path.mAttributeId = TypeInfo::GetAttributeId(); - TypeInfo::DecodableType value; - CHIP_ERROR err = clusterStateCacheContainer.cppClusterStateCache->Get(path, value); - if (err == CHIP_NO_ERROR) { - successCb(bridge, value); - } - return err; - } - return CHIP_ERROR_NOT_FOUND; - }); -} - -@end - @implementation MTRBaseClusterHEPAFilterMonitoring - (instancetype)initWithDevice:(MTRBaseDevice *)device endpointID:(NSNumber *)endpointID queue:(dispatch_queue_t)queue diff --git a/src/darwin/Framework/CHIP/zap-generated/MTRBaseClusters_Internal.h b/src/darwin/Framework/CHIP/zap-generated/MTRBaseClusters_Internal.h index d7135458fc7ec6..1063a353250da9 100644 --- a/src/darwin/Framework/CHIP/zap-generated/MTRBaseClusters_Internal.h +++ b/src/darwin/Framework/CHIP/zap-generated/MTRBaseClusters_Internal.h @@ -225,11 +225,6 @@ @property (nonatomic, assign, readonly) chip::EndpointId endpoint; @end -@interface MTRBaseClusterRVCOperationalState () -@property (nonatomic, strong, readonly) MTRBaseDevice * device; -@property (nonatomic, assign, readonly) chip::EndpointId endpoint; -@end - @interface MTRBaseClusterHEPAFilterMonitoring () @property (nonatomic, strong, readonly) MTRBaseDevice * device; @property (nonatomic, assign, readonly) chip::EndpointId endpoint; diff --git a/src/darwin/Framework/CHIP/zap-generated/MTRCallbackBridge.h b/src/darwin/Framework/CHIP/zap-generated/MTRCallbackBridge.h index 74d4cfe31063c5..e239e1f9d503eb 100644 --- a/src/darwin/Framework/CHIP/zap-generated/MTRCallbackBridge.h +++ b/src/darwin/Framework/CHIP/zap-generated/MTRCallbackBridge.h @@ -87,8 +87,6 @@ typedef void (*GroupKeyManagementClusterKeySetReadAllIndicesResponseCallbackType void *, const chip::app::Clusters::GroupKeyManagement::Commands::KeySetReadAllIndicesResponse::DecodableType &); typedef void (*OperationalStateClusterOperationalCommandResponseCallbackType)( void *, const chip::app::Clusters::OperationalState::Commands::OperationalCommandResponse::DecodableType &); -typedef void (*RVCOperationalStateClusterOperationalCommandResponseCallbackType)( - void *, const chip::app::Clusters::RvcOperationalState::Commands::OperationalCommandResponse::DecodableType &); typedef void (*DoorLockClusterGetWeekDayScheduleResponseCallbackType)( void *, const chip::app::Clusters::DoorLock::Commands::GetWeekDayScheduleResponse::DecodableType &); typedef void (*DoorLockClusterGetYearDayScheduleResponseCallbackType)( @@ -416,14 +414,6 @@ typedef void (*OperationalStateClusterOperationalStateEnumAttributeCallback)( void *, chip::app::Clusters::OperationalState::OperationalStateEnum); typedef void (*NullableOperationalStateClusterOperationalStateEnumAttributeCallback)( void *, const chip::app::DataModel::Nullable &); -typedef void (*RVCOperationalStateClusterErrorStateEnumAttributeCallback)(void *, - chip::app::Clusters::RvcOperationalState::ErrorStateEnum); -typedef void (*NullableRVCOperationalStateClusterErrorStateEnumAttributeCallback)( - void *, const chip::app::DataModel::Nullable &); -typedef void (*RVCOperationalStateClusterOperationalStateEnumAttributeCallback)( - void *, chip::app::Clusters::RvcOperationalState::OperationalStateEnum); -typedef void (*NullableRVCOperationalStateClusterOperationalStateEnumAttributeCallback)( - void *, const chip::app::DataModel::Nullable &); typedef void (*HEPAFilterMonitoringClusterChangeIndicationEnumAttributeCallback)( void *, chip::app::Clusters::HepaFilterMonitoring::ChangeIndicationEnum); typedef void (*NullableHEPAFilterMonitoringClusterChangeIndicationEnumAttributeCallback)( @@ -1231,24 +1221,6 @@ typedef void (*OperationalStateEventListListAttributeCallback)(void * context, const chip::app::DataModel::DecodableList & data); typedef void (*OperationalStateAttributeListListAttributeCallback)( void * context, const chip::app::DataModel::DecodableList & data); -typedef void (*RVCOperationalStatePhaseListListAttributeCallback)( - void * context, const chip::app::DataModel::Nullable> & data); -typedef void (*RVCOperationalStateOperationalStateListListAttributeCallback)( - void * context, - const chip::app::DataModel::DecodableList< - chip::app::Clusters::RvcOperationalState::Structs::OperationalStateStruct::DecodableType> & data); -typedef void (*RVCOperationalStateOperationalStateStructAttributeCallback)( - void *, const chip::app::Clusters::RvcOperationalState::Structs::OperationalStateStruct::DecodableType &); -typedef void (*RVCOperationalStateOperationalErrorStructAttributeCallback)( - void *, const chip::app::Clusters::RvcOperationalState::Structs::ErrorStateStruct::DecodableType &); -typedef void (*RVCOperationalStateGeneratedCommandListListAttributeCallback)( - void * context, const chip::app::DataModel::DecodableList & data); -typedef void (*RVCOperationalStateAcceptedCommandListListAttributeCallback)( - void * context, const chip::app::DataModel::DecodableList & data); -typedef void (*RVCOperationalStateEventListListAttributeCallback)(void * context, - const chip::app::DataModel::DecodableList & data); -typedef void (*RVCOperationalStateAttributeListListAttributeCallback)( - void * context, const chip::app::DataModel::DecodableList & data); typedef void (*HEPAFilterMonitoringGeneratedCommandListListAttributeCallback)( void * context, const chip::app::DataModel::DecodableList & data); typedef void (*HEPAFilterMonitoringAcceptedCommandListListAttributeCallback)( @@ -9619,275 +9591,6 @@ class MTROperationalStateAttributeListListAttributeCallbackSubscriptionBridge MTRSubscriptionEstablishedHandler mEstablishedHandler; }; -class MTRRVCOperationalStatePhaseListListAttributeCallbackBridge - : public MTRCallbackBridge -{ -public: - MTRRVCOperationalStatePhaseListListAttributeCallbackBridge(dispatch_queue_t queue, ResponseHandler handler) : - MTRCallbackBridge(queue, handler, OnSuccessFn){}; - - MTRRVCOperationalStatePhaseListListAttributeCallbackBridge(dispatch_queue_t queue, ResponseHandler handler, - MTRActionBlock action) : - MTRCallbackBridge(queue, handler, action, OnSuccessFn){}; - - static void OnSuccessFn(void * context, - const chip::app::DataModel::Nullable> & value); -}; - -class MTRRVCOperationalStatePhaseListListAttributeCallbackSubscriptionBridge - : public MTRRVCOperationalStatePhaseListListAttributeCallbackBridge -{ -public: - MTRRVCOperationalStatePhaseListListAttributeCallbackSubscriptionBridge(dispatch_queue_t queue, ResponseHandler handler, - MTRActionBlock action, - MTRSubscriptionEstablishedHandler establishedHandler) : - MTRRVCOperationalStatePhaseListListAttributeCallbackBridge(queue, handler, action), - mEstablishedHandler(establishedHandler) - {} - - void OnSubscriptionEstablished(); - using MTRRVCOperationalStatePhaseListListAttributeCallbackBridge::KeepAliveOnCallback; - using MTRRVCOperationalStatePhaseListListAttributeCallbackBridge::OnDone; - -private: - MTRSubscriptionEstablishedHandler mEstablishedHandler; -}; - -class MTRRVCOperationalStateOperationalStateListListAttributeCallbackBridge - : public MTRCallbackBridge -{ -public: - MTRRVCOperationalStateOperationalStateListListAttributeCallbackBridge(dispatch_queue_t queue, ResponseHandler handler) : - MTRCallbackBridge(queue, handler, OnSuccessFn){}; - - MTRRVCOperationalStateOperationalStateListListAttributeCallbackBridge(dispatch_queue_t queue, ResponseHandler handler, - MTRActionBlock action) : - MTRCallbackBridge(queue, handler, action, OnSuccessFn){}; - - static void OnSuccessFn(void * context, - const chip::app::DataModel::DecodableList< - chip::app::Clusters::RvcOperationalState::Structs::OperationalStateStruct::DecodableType> & value); -}; - -class MTRRVCOperationalStateOperationalStateListListAttributeCallbackSubscriptionBridge - : public MTRRVCOperationalStateOperationalStateListListAttributeCallbackBridge -{ -public: - MTRRVCOperationalStateOperationalStateListListAttributeCallbackSubscriptionBridge( - dispatch_queue_t queue, ResponseHandler handler, MTRActionBlock action, - MTRSubscriptionEstablishedHandler establishedHandler) : - MTRRVCOperationalStateOperationalStateListListAttributeCallbackBridge(queue, handler, action), - mEstablishedHandler(establishedHandler) - {} - - void OnSubscriptionEstablished(); - using MTRRVCOperationalStateOperationalStateListListAttributeCallbackBridge::KeepAliveOnCallback; - using MTRRVCOperationalStateOperationalStateListListAttributeCallbackBridge::OnDone; - -private: - MTRSubscriptionEstablishedHandler mEstablishedHandler; -}; - -class MTRRVCOperationalStateOperationalStateStructAttributeCallbackBridge - : public MTRCallbackBridge -{ -public: - MTRRVCOperationalStateOperationalStateStructAttributeCallbackBridge(dispatch_queue_t queue, ResponseHandler handler) : - MTRCallbackBridge(queue, handler, OnSuccessFn){}; - - MTRRVCOperationalStateOperationalStateStructAttributeCallbackBridge(dispatch_queue_t queue, ResponseHandler handler, - MTRActionBlock action) : - MTRCallbackBridge(queue, handler, action, OnSuccessFn){}; - - static void OnSuccessFn(void * context, - const chip::app::Clusters::RvcOperationalState::Structs::OperationalStateStruct::DecodableType & value); -}; - -class MTRRVCOperationalStateOperationalStateStructAttributeCallbackSubscriptionBridge - : public MTRRVCOperationalStateOperationalStateStructAttributeCallbackBridge -{ -public: - MTRRVCOperationalStateOperationalStateStructAttributeCallbackSubscriptionBridge( - dispatch_queue_t queue, ResponseHandler handler, MTRActionBlock action, - MTRSubscriptionEstablishedHandler establishedHandler) : - MTRRVCOperationalStateOperationalStateStructAttributeCallbackBridge(queue, handler, action), - mEstablishedHandler(establishedHandler) - {} - - void OnSubscriptionEstablished(); - using MTRRVCOperationalStateOperationalStateStructAttributeCallbackBridge::KeepAliveOnCallback; - using MTRRVCOperationalStateOperationalStateStructAttributeCallbackBridge::OnDone; - -private: - MTRSubscriptionEstablishedHandler mEstablishedHandler; -}; - -class MTRRVCOperationalStateOperationalErrorStructAttributeCallbackBridge - : public MTRCallbackBridge -{ -public: - MTRRVCOperationalStateOperationalErrorStructAttributeCallbackBridge(dispatch_queue_t queue, ResponseHandler handler) : - MTRCallbackBridge(queue, handler, OnSuccessFn){}; - - MTRRVCOperationalStateOperationalErrorStructAttributeCallbackBridge(dispatch_queue_t queue, ResponseHandler handler, - MTRActionBlock action) : - MTRCallbackBridge(queue, handler, action, OnSuccessFn){}; - - static void OnSuccessFn(void * context, - const chip::app::Clusters::RvcOperationalState::Structs::ErrorStateStruct::DecodableType & value); -}; - -class MTRRVCOperationalStateOperationalErrorStructAttributeCallbackSubscriptionBridge - : public MTRRVCOperationalStateOperationalErrorStructAttributeCallbackBridge -{ -public: - MTRRVCOperationalStateOperationalErrorStructAttributeCallbackSubscriptionBridge( - dispatch_queue_t queue, ResponseHandler handler, MTRActionBlock action, - MTRSubscriptionEstablishedHandler establishedHandler) : - MTRRVCOperationalStateOperationalErrorStructAttributeCallbackBridge(queue, handler, action), - mEstablishedHandler(establishedHandler) - {} - - void OnSubscriptionEstablished(); - using MTRRVCOperationalStateOperationalErrorStructAttributeCallbackBridge::KeepAliveOnCallback; - using MTRRVCOperationalStateOperationalErrorStructAttributeCallbackBridge::OnDone; - -private: - MTRSubscriptionEstablishedHandler mEstablishedHandler; -}; - -class MTRRVCOperationalStateGeneratedCommandListListAttributeCallbackBridge - : public MTRCallbackBridge -{ -public: - MTRRVCOperationalStateGeneratedCommandListListAttributeCallbackBridge(dispatch_queue_t queue, ResponseHandler handler) : - MTRCallbackBridge(queue, handler, OnSuccessFn){}; - - MTRRVCOperationalStateGeneratedCommandListListAttributeCallbackBridge(dispatch_queue_t queue, ResponseHandler handler, - MTRActionBlock action) : - MTRCallbackBridge(queue, handler, action, OnSuccessFn){}; - - static void OnSuccessFn(void * context, const chip::app::DataModel::DecodableList & value); -}; - -class MTRRVCOperationalStateGeneratedCommandListListAttributeCallbackSubscriptionBridge - : public MTRRVCOperationalStateGeneratedCommandListListAttributeCallbackBridge -{ -public: - MTRRVCOperationalStateGeneratedCommandListListAttributeCallbackSubscriptionBridge( - dispatch_queue_t queue, ResponseHandler handler, MTRActionBlock action, - MTRSubscriptionEstablishedHandler establishedHandler) : - MTRRVCOperationalStateGeneratedCommandListListAttributeCallbackBridge(queue, handler, action), - mEstablishedHandler(establishedHandler) - {} - - void OnSubscriptionEstablished(); - using MTRRVCOperationalStateGeneratedCommandListListAttributeCallbackBridge::KeepAliveOnCallback; - using MTRRVCOperationalStateGeneratedCommandListListAttributeCallbackBridge::OnDone; - -private: - MTRSubscriptionEstablishedHandler mEstablishedHandler; -}; - -class MTRRVCOperationalStateAcceptedCommandListListAttributeCallbackBridge - : public MTRCallbackBridge -{ -public: - MTRRVCOperationalStateAcceptedCommandListListAttributeCallbackBridge(dispatch_queue_t queue, ResponseHandler handler) : - MTRCallbackBridge(queue, handler, OnSuccessFn){}; - - MTRRVCOperationalStateAcceptedCommandListListAttributeCallbackBridge(dispatch_queue_t queue, ResponseHandler handler, - MTRActionBlock action) : - MTRCallbackBridge(queue, handler, action, OnSuccessFn){}; - - static void OnSuccessFn(void * context, const chip::app::DataModel::DecodableList & value); -}; - -class MTRRVCOperationalStateAcceptedCommandListListAttributeCallbackSubscriptionBridge - : public MTRRVCOperationalStateAcceptedCommandListListAttributeCallbackBridge -{ -public: - MTRRVCOperationalStateAcceptedCommandListListAttributeCallbackSubscriptionBridge( - dispatch_queue_t queue, ResponseHandler handler, MTRActionBlock action, - MTRSubscriptionEstablishedHandler establishedHandler) : - MTRRVCOperationalStateAcceptedCommandListListAttributeCallbackBridge(queue, handler, action), - mEstablishedHandler(establishedHandler) - {} - - void OnSubscriptionEstablished(); - using MTRRVCOperationalStateAcceptedCommandListListAttributeCallbackBridge::KeepAliveOnCallback; - using MTRRVCOperationalStateAcceptedCommandListListAttributeCallbackBridge::OnDone; - -private: - MTRSubscriptionEstablishedHandler mEstablishedHandler; -}; - -class MTRRVCOperationalStateEventListListAttributeCallbackBridge - : public MTRCallbackBridge -{ -public: - MTRRVCOperationalStateEventListListAttributeCallbackBridge(dispatch_queue_t queue, ResponseHandler handler) : - MTRCallbackBridge(queue, handler, OnSuccessFn){}; - - MTRRVCOperationalStateEventListListAttributeCallbackBridge(dispatch_queue_t queue, ResponseHandler handler, - MTRActionBlock action) : - MTRCallbackBridge(queue, handler, action, OnSuccessFn){}; - - static void OnSuccessFn(void * context, const chip::app::DataModel::DecodableList & value); -}; - -class MTRRVCOperationalStateEventListListAttributeCallbackSubscriptionBridge - : public MTRRVCOperationalStateEventListListAttributeCallbackBridge -{ -public: - MTRRVCOperationalStateEventListListAttributeCallbackSubscriptionBridge(dispatch_queue_t queue, ResponseHandler handler, - MTRActionBlock action, - MTRSubscriptionEstablishedHandler establishedHandler) : - MTRRVCOperationalStateEventListListAttributeCallbackBridge(queue, handler, action), - mEstablishedHandler(establishedHandler) - {} - - void OnSubscriptionEstablished(); - using MTRRVCOperationalStateEventListListAttributeCallbackBridge::KeepAliveOnCallback; - using MTRRVCOperationalStateEventListListAttributeCallbackBridge::OnDone; - -private: - MTRSubscriptionEstablishedHandler mEstablishedHandler; -}; - -class MTRRVCOperationalStateAttributeListListAttributeCallbackBridge - : public MTRCallbackBridge -{ -public: - MTRRVCOperationalStateAttributeListListAttributeCallbackBridge(dispatch_queue_t queue, ResponseHandler handler) : - MTRCallbackBridge(queue, handler, OnSuccessFn){}; - - MTRRVCOperationalStateAttributeListListAttributeCallbackBridge(dispatch_queue_t queue, ResponseHandler handler, - MTRActionBlock action) : - MTRCallbackBridge(queue, handler, action, OnSuccessFn){}; - - static void OnSuccessFn(void * context, const chip::app::DataModel::DecodableList & value); -}; - -class MTRRVCOperationalStateAttributeListListAttributeCallbackSubscriptionBridge - : public MTRRVCOperationalStateAttributeListListAttributeCallbackBridge -{ -public: - MTRRVCOperationalStateAttributeListListAttributeCallbackSubscriptionBridge( - dispatch_queue_t queue, ResponseHandler handler, MTRActionBlock action, - MTRSubscriptionEstablishedHandler establishedHandler) : - MTRRVCOperationalStateAttributeListListAttributeCallbackBridge(queue, handler, action), - mEstablishedHandler(establishedHandler) - {} - - void OnSubscriptionEstablished(); - using MTRRVCOperationalStateAttributeListListAttributeCallbackBridge::KeepAliveOnCallback; - using MTRRVCOperationalStateAttributeListListAttributeCallbackBridge::OnDone; - -private: - MTRSubscriptionEstablishedHandler mEstablishedHandler; -}; - class MTRHEPAFilterMonitoringGeneratedCommandListListAttributeCallbackBridge : public MTRCallbackBridge { @@ -17061,22 +16764,6 @@ class MTROperationalStateClusterOperationalCommandResponseCallbackBridge const chip::app::Clusters::OperationalState::Commands::OperationalCommandResponse::DecodableType & data); }; -class MTRRVCOperationalStateClusterOperationalCommandResponseCallbackBridge - : public MTRCallbackBridge -{ -public: - MTRRVCOperationalStateClusterOperationalCommandResponseCallbackBridge(dispatch_queue_t queue, ResponseHandler handler) : - MTRCallbackBridge(queue, handler, OnSuccessFn){}; - - MTRRVCOperationalStateClusterOperationalCommandResponseCallbackBridge(dispatch_queue_t queue, ResponseHandler handler, - MTRActionBlock action) : - MTRCallbackBridge(queue, handler, action, OnSuccessFn){}; - - static void - OnSuccessFn(void * context, - const chip::app::Clusters::RvcOperationalState::Commands::OperationalCommandResponse::DecodableType & data); -}; - class MTRDoorLockClusterGetWeekDayScheduleResponseCallbackBridge : public MTRCallbackBridge { @@ -22658,144 +22345,6 @@ class MTRNullableOperationalStateClusterOperationalStateEnumAttributeCallbackSub MTRSubscriptionEstablishedHandler mEstablishedHandler; }; -class MTRRVCOperationalStateClusterErrorStateEnumAttributeCallbackBridge - : public MTRCallbackBridge -{ -public: - MTRRVCOperationalStateClusterErrorStateEnumAttributeCallbackBridge(dispatch_queue_t queue, ResponseHandler handler) : - MTRCallbackBridge(queue, handler, OnSuccessFn){}; - - MTRRVCOperationalStateClusterErrorStateEnumAttributeCallbackBridge(dispatch_queue_t queue, ResponseHandler handler, - MTRActionBlock action) : - MTRCallbackBridge(queue, handler, action, OnSuccessFn){}; - - static void OnSuccessFn(void * context, chip::app::Clusters::RvcOperationalState::ErrorStateEnum value); -}; - -class MTRRVCOperationalStateClusterErrorStateEnumAttributeCallbackSubscriptionBridge - : public MTRRVCOperationalStateClusterErrorStateEnumAttributeCallbackBridge -{ -public: - MTRRVCOperationalStateClusterErrorStateEnumAttributeCallbackSubscriptionBridge( - dispatch_queue_t queue, ResponseHandler handler, MTRActionBlock action, - MTRSubscriptionEstablishedHandler establishedHandler) : - MTRRVCOperationalStateClusterErrorStateEnumAttributeCallbackBridge(queue, handler, action), - mEstablishedHandler(establishedHandler) - {} - - void OnSubscriptionEstablished(); - using MTRRVCOperationalStateClusterErrorStateEnumAttributeCallbackBridge::KeepAliveOnCallback; - using MTRRVCOperationalStateClusterErrorStateEnumAttributeCallbackBridge::OnDone; - -private: - MTRSubscriptionEstablishedHandler mEstablishedHandler; -}; - -class MTRNullableRVCOperationalStateClusterErrorStateEnumAttributeCallbackBridge - : public MTRCallbackBridge -{ -public: - MTRNullableRVCOperationalStateClusterErrorStateEnumAttributeCallbackBridge(dispatch_queue_t queue, ResponseHandler handler) : - MTRCallbackBridge(queue, handler, OnSuccessFn){}; - - MTRNullableRVCOperationalStateClusterErrorStateEnumAttributeCallbackBridge(dispatch_queue_t queue, ResponseHandler handler, - MTRActionBlock action) : - MTRCallbackBridge(queue, handler, action, OnSuccessFn){}; - - static void OnSuccessFn(void * context, - const chip::app::DataModel::Nullable & value); -}; - -class MTRNullableRVCOperationalStateClusterErrorStateEnumAttributeCallbackSubscriptionBridge - : public MTRNullableRVCOperationalStateClusterErrorStateEnumAttributeCallbackBridge -{ -public: - MTRNullableRVCOperationalStateClusterErrorStateEnumAttributeCallbackSubscriptionBridge( - dispatch_queue_t queue, ResponseHandler handler, MTRActionBlock action, - MTRSubscriptionEstablishedHandler establishedHandler) : - MTRNullableRVCOperationalStateClusterErrorStateEnumAttributeCallbackBridge(queue, handler, action), - mEstablishedHandler(establishedHandler) - {} - - void OnSubscriptionEstablished(); - using MTRNullableRVCOperationalStateClusterErrorStateEnumAttributeCallbackBridge::KeepAliveOnCallback; - using MTRNullableRVCOperationalStateClusterErrorStateEnumAttributeCallbackBridge::OnDone; - -private: - MTRSubscriptionEstablishedHandler mEstablishedHandler; -}; - -class MTRRVCOperationalStateClusterOperationalStateEnumAttributeCallbackBridge - : public MTRCallbackBridge -{ -public: - MTRRVCOperationalStateClusterOperationalStateEnumAttributeCallbackBridge(dispatch_queue_t queue, ResponseHandler handler) : - MTRCallbackBridge(queue, handler, OnSuccessFn){}; - - MTRRVCOperationalStateClusterOperationalStateEnumAttributeCallbackBridge(dispatch_queue_t queue, ResponseHandler handler, - MTRActionBlock action) : - MTRCallbackBridge(queue, handler, action, OnSuccessFn){}; - - static void OnSuccessFn(void * context, chip::app::Clusters::RvcOperationalState::OperationalStateEnum value); -}; - -class MTRRVCOperationalStateClusterOperationalStateEnumAttributeCallbackSubscriptionBridge - : public MTRRVCOperationalStateClusterOperationalStateEnumAttributeCallbackBridge -{ -public: - MTRRVCOperationalStateClusterOperationalStateEnumAttributeCallbackSubscriptionBridge( - dispatch_queue_t queue, ResponseHandler handler, MTRActionBlock action, - MTRSubscriptionEstablishedHandler establishedHandler) : - MTRRVCOperationalStateClusterOperationalStateEnumAttributeCallbackBridge(queue, handler, action), - mEstablishedHandler(establishedHandler) - {} - - void OnSubscriptionEstablished(); - using MTRRVCOperationalStateClusterOperationalStateEnumAttributeCallbackBridge::KeepAliveOnCallback; - using MTRRVCOperationalStateClusterOperationalStateEnumAttributeCallbackBridge::OnDone; - -private: - MTRSubscriptionEstablishedHandler mEstablishedHandler; -}; - -class MTRNullableRVCOperationalStateClusterOperationalStateEnumAttributeCallbackBridge - : public MTRCallbackBridge -{ -public: - MTRNullableRVCOperationalStateClusterOperationalStateEnumAttributeCallbackBridge(dispatch_queue_t queue, - ResponseHandler handler) : - MTRCallbackBridge(queue, handler, OnSuccessFn){}; - - MTRNullableRVCOperationalStateClusterOperationalStateEnumAttributeCallbackBridge(dispatch_queue_t queue, - ResponseHandler handler, - MTRActionBlock action) : - MTRCallbackBridge(queue, handler, action, - OnSuccessFn){}; - - static void - OnSuccessFn(void * context, - const chip::app::DataModel::Nullable & value); -}; - -class MTRNullableRVCOperationalStateClusterOperationalStateEnumAttributeCallbackSubscriptionBridge - : public MTRNullableRVCOperationalStateClusterOperationalStateEnumAttributeCallbackBridge -{ -public: - MTRNullableRVCOperationalStateClusterOperationalStateEnumAttributeCallbackSubscriptionBridge( - dispatch_queue_t queue, ResponseHandler handler, MTRActionBlock action, - MTRSubscriptionEstablishedHandler establishedHandler) : - MTRNullableRVCOperationalStateClusterOperationalStateEnumAttributeCallbackBridge(queue, handler, action), - mEstablishedHandler(establishedHandler) - {} - - void OnSubscriptionEstablished(); - using MTRNullableRVCOperationalStateClusterOperationalStateEnumAttributeCallbackBridge::KeepAliveOnCallback; - using MTRNullableRVCOperationalStateClusterOperationalStateEnumAttributeCallbackBridge::OnDone; - -private: - MTRSubscriptionEstablishedHandler mEstablishedHandler; -}; - class MTRHEPAFilterMonitoringClusterChangeIndicationEnumAttributeCallbackBridge : public MTRCallbackBridge { diff --git a/src/darwin/Framework/CHIP/zap-generated/MTRCallbackBridge.mm b/src/darwin/Framework/CHIP/zap-generated/MTRCallbackBridge.mm index 6314800b01a871..2a0dd1d620c47e 100644 --- a/src/darwin/Framework/CHIP/zap-generated/MTRCallbackBridge.mm +++ b/src/darwin/Framework/CHIP/zap-generated/MTRCallbackBridge.mm @@ -9229,333 +9229,6 @@ } } -void MTRRVCOperationalStatePhaseListListAttributeCallbackBridge::OnSuccessFn( - void * context, const chip::app::DataModel::Nullable> & value) -{ - NSArray * _Nullable objCValue; - if (value.IsNull()) { - objCValue = nil; - } else { - { // Scope for our temporary variables - auto * array_1 = [NSMutableArray new]; - auto iter_1 = value.Value().begin(); - while (iter_1.Next()) { - auto & entry_1 = iter_1.GetValue(); - NSString * newElement_1; - newElement_1 = AsString(entry_1); - if (newElement_1 == nil) { - CHIP_ERROR err = CHIP_ERROR_INVALID_ARGUMENT; - OnFailureFn(context, err); - return; - } - [array_1 addObject:newElement_1]; - } - CHIP_ERROR err = iter_1.GetStatus(); - if (err != CHIP_NO_ERROR) { - OnFailureFn(context, err); - return; - } - objCValue = array_1; - } - } - DispatchSuccess(context, objCValue); -}; - -void MTRRVCOperationalStatePhaseListListAttributeCallbackSubscriptionBridge::OnSubscriptionEstablished() -{ - if (!mQueue) { - return; - } - - if (mEstablishedHandler != nil) { - dispatch_async(mQueue, mEstablishedHandler); - // On failure, mEstablishedHandler will be cleaned up by our destructor, - // but we can clean it up earlier on successful subscription - // establishment. - mEstablishedHandler = nil; - } -} - -void MTRRVCOperationalStateOperationalStateListListAttributeCallbackBridge::OnSuccessFn(void * context, - const chip::app::DataModel::DecodableList< - chip::app::Clusters::RvcOperationalState::Structs::OperationalStateStruct::DecodableType> & value) -{ - NSArray * _Nonnull objCValue; - { // Scope for our temporary variables - auto * array_0 = [NSMutableArray new]; - auto iter_0 = value.begin(); - while (iter_0.Next()) { - auto & entry_0 = iter_0.GetValue(); - MTRRVCOperationalStateClusterOperationalStateStruct * newElement_0; - newElement_0 = [MTRRVCOperationalStateClusterOperationalStateStruct new]; - newElement_0.operationalStateID = [NSNumber numberWithUnsignedChar:entry_0.operationalStateID]; - if (entry_0.operationalStateLabel.HasValue()) { - newElement_0.operationalStateLabel = AsString(entry_0.operationalStateLabel.Value()); - if (newElement_0.operationalStateLabel == nil) { - CHIP_ERROR err = CHIP_ERROR_INVALID_ARGUMENT; - OnFailureFn(context, err); - return; - } - } else { - newElement_0.operationalStateLabel = nil; - } - [array_0 addObject:newElement_0]; - } - CHIP_ERROR err = iter_0.GetStatus(); - if (err != CHIP_NO_ERROR) { - OnFailureFn(context, err); - return; - } - objCValue = array_0; - } - DispatchSuccess(context, objCValue); -}; - -void MTRRVCOperationalStateOperationalStateListListAttributeCallbackSubscriptionBridge::OnSubscriptionEstablished() -{ - if (!mQueue) { - return; - } - - if (mEstablishedHandler != nil) { - dispatch_async(mQueue, mEstablishedHandler); - // On failure, mEstablishedHandler will be cleaned up by our destructor, - // but we can clean it up earlier on successful subscription - // establishment. - mEstablishedHandler = nil; - } -} - -void MTRRVCOperationalStateOperationalStateStructAttributeCallbackBridge::OnSuccessFn( - void * context, const chip::app::Clusters::RvcOperationalState::Structs::OperationalStateStruct::DecodableType & value) -{ - MTRRVCOperationalStateClusterOperationalStateStruct * _Nonnull objCValue; - objCValue = [MTRRVCOperationalStateClusterOperationalStateStruct new]; - objCValue.operationalStateID = [NSNumber numberWithUnsignedChar:value.operationalStateID]; - if (value.operationalStateLabel.HasValue()) { - objCValue.operationalStateLabel = AsString(value.operationalStateLabel.Value()); - if (objCValue.operationalStateLabel == nil) { - CHIP_ERROR err = CHIP_ERROR_INVALID_ARGUMENT; - OnFailureFn(context, err); - return; - } - } else { - objCValue.operationalStateLabel = nil; - } - DispatchSuccess(context, objCValue); -}; - -void MTRRVCOperationalStateOperationalStateStructAttributeCallbackSubscriptionBridge::OnSubscriptionEstablished() -{ - if (!mQueue) { - return; - } - - if (mEstablishedHandler != nil) { - dispatch_async(mQueue, mEstablishedHandler); - // On failure, mEstablishedHandler will be cleaned up by our destructor, - // but we can clean it up earlier on successful subscription - // establishment. - mEstablishedHandler = nil; - } -} - -void MTRRVCOperationalStateOperationalErrorStructAttributeCallbackBridge::OnSuccessFn( - void * context, const chip::app::Clusters::RvcOperationalState::Structs::ErrorStateStruct::DecodableType & value) -{ - MTRRVCOperationalStateClusterErrorStateStruct * _Nonnull objCValue; - objCValue = [MTRRVCOperationalStateClusterErrorStateStruct new]; - objCValue.errorStateID = [NSNumber numberWithUnsignedChar:value.errorStateID]; - if (value.errorStateLabel.HasValue()) { - objCValue.errorStateLabel = AsString(value.errorStateLabel.Value()); - if (objCValue.errorStateLabel == nil) { - CHIP_ERROR err = CHIP_ERROR_INVALID_ARGUMENT; - OnFailureFn(context, err); - return; - } - } else { - objCValue.errorStateLabel = nil; - } - if (value.errorStateDetails.HasValue()) { - objCValue.errorStateDetails = AsString(value.errorStateDetails.Value()); - if (objCValue.errorStateDetails == nil) { - CHIP_ERROR err = CHIP_ERROR_INVALID_ARGUMENT; - OnFailureFn(context, err); - return; - } - } else { - objCValue.errorStateDetails = nil; - } - DispatchSuccess(context, objCValue); -}; - -void MTRRVCOperationalStateOperationalErrorStructAttributeCallbackSubscriptionBridge::OnSubscriptionEstablished() -{ - if (!mQueue) { - return; - } - - if (mEstablishedHandler != nil) { - dispatch_async(mQueue, mEstablishedHandler); - // On failure, mEstablishedHandler will be cleaned up by our destructor, - // but we can clean it up earlier on successful subscription - // establishment. - mEstablishedHandler = nil; - } -} - -void MTRRVCOperationalStateGeneratedCommandListListAttributeCallbackBridge::OnSuccessFn( - void * context, const chip::app::DataModel::DecodableList & value) -{ - NSArray * _Nonnull objCValue; - { // Scope for our temporary variables - auto * array_0 = [NSMutableArray new]; - auto iter_0 = value.begin(); - while (iter_0.Next()) { - auto & entry_0 = iter_0.GetValue(); - NSNumber * newElement_0; - newElement_0 = [NSNumber numberWithUnsignedInt:entry_0]; - [array_0 addObject:newElement_0]; - } - CHIP_ERROR err = iter_0.GetStatus(); - if (err != CHIP_NO_ERROR) { - OnFailureFn(context, err); - return; - } - objCValue = array_0; - } - DispatchSuccess(context, objCValue); -}; - -void MTRRVCOperationalStateGeneratedCommandListListAttributeCallbackSubscriptionBridge::OnSubscriptionEstablished() -{ - if (!mQueue) { - return; - } - - if (mEstablishedHandler != nil) { - dispatch_async(mQueue, mEstablishedHandler); - // On failure, mEstablishedHandler will be cleaned up by our destructor, - // but we can clean it up earlier on successful subscription - // establishment. - mEstablishedHandler = nil; - } -} - -void MTRRVCOperationalStateAcceptedCommandListListAttributeCallbackBridge::OnSuccessFn( - void * context, const chip::app::DataModel::DecodableList & value) -{ - NSArray * _Nonnull objCValue; - { // Scope for our temporary variables - auto * array_0 = [NSMutableArray new]; - auto iter_0 = value.begin(); - while (iter_0.Next()) { - auto & entry_0 = iter_0.GetValue(); - NSNumber * newElement_0; - newElement_0 = [NSNumber numberWithUnsignedInt:entry_0]; - [array_0 addObject:newElement_0]; - } - CHIP_ERROR err = iter_0.GetStatus(); - if (err != CHIP_NO_ERROR) { - OnFailureFn(context, err); - return; - } - objCValue = array_0; - } - DispatchSuccess(context, objCValue); -}; - -void MTRRVCOperationalStateAcceptedCommandListListAttributeCallbackSubscriptionBridge::OnSubscriptionEstablished() -{ - if (!mQueue) { - return; - } - - if (mEstablishedHandler != nil) { - dispatch_async(mQueue, mEstablishedHandler); - // On failure, mEstablishedHandler will be cleaned up by our destructor, - // but we can clean it up earlier on successful subscription - // establishment. - mEstablishedHandler = nil; - } -} - -void MTRRVCOperationalStateEventListListAttributeCallbackBridge::OnSuccessFn( - void * context, const chip::app::DataModel::DecodableList & value) -{ - NSArray * _Nonnull objCValue; - { // Scope for our temporary variables - auto * array_0 = [NSMutableArray new]; - auto iter_0 = value.begin(); - while (iter_0.Next()) { - auto & entry_0 = iter_0.GetValue(); - NSNumber * newElement_0; - newElement_0 = [NSNumber numberWithUnsignedInt:entry_0]; - [array_0 addObject:newElement_0]; - } - CHIP_ERROR err = iter_0.GetStatus(); - if (err != CHIP_NO_ERROR) { - OnFailureFn(context, err); - return; - } - objCValue = array_0; - } - DispatchSuccess(context, objCValue); -}; - -void MTRRVCOperationalStateEventListListAttributeCallbackSubscriptionBridge::OnSubscriptionEstablished() -{ - if (!mQueue) { - return; - } - - if (mEstablishedHandler != nil) { - dispatch_async(mQueue, mEstablishedHandler); - // On failure, mEstablishedHandler will be cleaned up by our destructor, - // but we can clean it up earlier on successful subscription - // establishment. - mEstablishedHandler = nil; - } -} - -void MTRRVCOperationalStateAttributeListListAttributeCallbackBridge::OnSuccessFn( - void * context, const chip::app::DataModel::DecodableList & value) -{ - NSArray * _Nonnull objCValue; - { // Scope for our temporary variables - auto * array_0 = [NSMutableArray new]; - auto iter_0 = value.begin(); - while (iter_0.Next()) { - auto & entry_0 = iter_0.GetValue(); - NSNumber * newElement_0; - newElement_0 = [NSNumber numberWithUnsignedInt:entry_0]; - [array_0 addObject:newElement_0]; - } - CHIP_ERROR err = iter_0.GetStatus(); - if (err != CHIP_NO_ERROR) { - OnFailureFn(context, err); - return; - } - objCValue = array_0; - } - DispatchSuccess(context, objCValue); -}; - -void MTRRVCOperationalStateAttributeListListAttributeCallbackSubscriptionBridge::OnSubscriptionEstablished() -{ - if (!mQueue) { - return; - } - - if (mEstablishedHandler != nil) { - dispatch_async(mQueue, mEstablishedHandler); - // On failure, mEstablishedHandler will be cleaned up by our destructor, - // but we can clean it up earlier on successful subscription - // establishment. - mEstablishedHandler = nil; - } -} - void MTRHEPAFilterMonitoringGeneratedCommandListListAttributeCallbackBridge::OnSuccessFn( void * context, const chip::app::DataModel::DecodableList & value) { @@ -17740,18 +17413,6 @@ DispatchSuccess(context, response); }; -void MTRRVCOperationalStateClusterOperationalCommandResponseCallbackBridge::OnSuccessFn( - void * context, const chip::app::Clusters::RvcOperationalState::Commands::OperationalCommandResponse::DecodableType & data) -{ - auto * response = [MTRRVCOperationalStateClusterOperationalCommandResponseParams new]; - CHIP_ERROR err = [response _setFieldsFromDecodableStruct:data]; - if (err != CHIP_NO_ERROR) { - OnFailureFn(context, err); - return; - } - DispatchSuccess(context, response); -}; - void MTRDoorLockClusterGetWeekDayScheduleResponseCallbackBridge::OnSuccessFn( void * context, const chip::app::Clusters::DoorLock::Commands::GetWeekDayScheduleResponse::DecodableType & data) { @@ -21823,106 +21484,6 @@ } } -void MTRRVCOperationalStateClusterErrorStateEnumAttributeCallbackBridge::OnSuccessFn( - void * context, chip::app::Clusters::RvcOperationalState::ErrorStateEnum value) -{ - NSNumber * _Nonnull objCValue; - objCValue = [NSNumber numberWithUnsignedChar:chip::to_underlying(value)]; - DispatchSuccess(context, objCValue); -}; - -void MTRRVCOperationalStateClusterErrorStateEnumAttributeCallbackSubscriptionBridge::OnSubscriptionEstablished() -{ - if (!mQueue) { - return; - } - - if (mEstablishedHandler != nil) { - dispatch_async(mQueue, mEstablishedHandler); - // On failure, mEstablishedHandler will be cleaned up by our destructor, - // but we can clean it up earlier on successful subscription - // establishment. - mEstablishedHandler = nil; - } -} - -void MTRNullableRVCOperationalStateClusterErrorStateEnumAttributeCallbackBridge::OnSuccessFn( - void * context, const chip::app::DataModel::Nullable & value) -{ - NSNumber * _Nullable objCValue; - if (value.IsNull()) { - objCValue = nil; - } else { - objCValue = [NSNumber numberWithUnsignedChar:chip::to_underlying(value.Value())]; - } - DispatchSuccess(context, objCValue); -}; - -void MTRNullableRVCOperationalStateClusterErrorStateEnumAttributeCallbackSubscriptionBridge::OnSubscriptionEstablished() -{ - if (!mQueue) { - return; - } - - if (mEstablishedHandler != nil) { - dispatch_async(mQueue, mEstablishedHandler); - // On failure, mEstablishedHandler will be cleaned up by our destructor, - // but we can clean it up earlier on successful subscription - // establishment. - mEstablishedHandler = nil; - } -} - -void MTRRVCOperationalStateClusterOperationalStateEnumAttributeCallbackBridge::OnSuccessFn( - void * context, chip::app::Clusters::RvcOperationalState::OperationalStateEnum value) -{ - NSNumber * _Nonnull objCValue; - objCValue = [NSNumber numberWithUnsignedChar:chip::to_underlying(value)]; - DispatchSuccess(context, objCValue); -}; - -void MTRRVCOperationalStateClusterOperationalStateEnumAttributeCallbackSubscriptionBridge::OnSubscriptionEstablished() -{ - if (!mQueue) { - return; - } - - if (mEstablishedHandler != nil) { - dispatch_async(mQueue, mEstablishedHandler); - // On failure, mEstablishedHandler will be cleaned up by our destructor, - // but we can clean it up earlier on successful subscription - // establishment. - mEstablishedHandler = nil; - } -} - -void MTRNullableRVCOperationalStateClusterOperationalStateEnumAttributeCallbackBridge::OnSuccessFn( - void * context, const chip::app::DataModel::Nullable & value) -{ - NSNumber * _Nullable objCValue; - if (value.IsNull()) { - objCValue = nil; - } else { - objCValue = [NSNumber numberWithUnsignedChar:chip::to_underlying(value.Value())]; - } - DispatchSuccess(context, objCValue); -}; - -void MTRNullableRVCOperationalStateClusterOperationalStateEnumAttributeCallbackSubscriptionBridge::OnSubscriptionEstablished() -{ - if (!mQueue) { - return; - } - - if (mEstablishedHandler != nil) { - dispatch_async(mQueue, mEstablishedHandler); - // On failure, mEstablishedHandler will be cleaned up by our destructor, - // but we can clean it up earlier on successful subscription - // establishment. - mEstablishedHandler = nil; - } -} - void MTRHEPAFilterMonitoringClusterChangeIndicationEnumAttributeCallbackBridge::OnSuccessFn( void * context, chip::app::Clusters::HepaFilterMonitoring::ChangeIndicationEnum value) { diff --git a/src/darwin/Framework/CHIP/zap-generated/MTRClusterConstants.h b/src/darwin/Framework/CHIP/zap-generated/MTRClusterConstants.h index 92f35f673db378..0e06ba47e07b3f 100644 --- a/src/darwin/Framework/CHIP/zap-generated/MTRClusterConstants.h +++ b/src/darwin/Framework/CHIP/zap-generated/MTRClusterConstants.h @@ -281,7 +281,6 @@ typedef NS_ENUM(uint32_t, MTRClusterIDType) { MTRClusterIDTypeAirQualityID MTR_NEWLY_AVAILABLE = 0x0000005B, MTRClusterIDTypeSmokeCOAlarmID MTR_NEWLY_AVAILABLE = 0x0000005C, MTRClusterIDTypeOperationalStateID MTR_NEWLY_AVAILABLE = 0x00000060, - MTRClusterIDTypeRVCOperationalStateID MTR_NEWLY_AVAILABLE = 0x00000061, MTRClusterIDTypeHEPAFilterMonitoringID MTR_NEWLY_AVAILABLE = 0x00000071, MTRClusterIDTypeActivatedCarbonFilterMonitoringID MTR_NEWLY_AVAILABLE = 0x00000072, MTRClusterIDTypeDoorLockID API_AVAILABLE(ios(16.4), macos(13.3), watchos(9.4), tvos(16.4)) = 0x00000101, @@ -3826,26 +3825,6 @@ typedef NS_ENUM(uint32_t, MTRAttributeIDType) { MTRAttributeIDTypeClusterOperationalStateAttributeClusterRevisionID MTR_NEWLY_AVAILABLE = MTRAttributeIDTypeGlobalAttributeClusterRevisionID, - // Cluster RVCOperationalState attributes - MTRAttributeIDTypeClusterRVCOperationalStateAttributePhaseListID MTR_NEWLY_AVAILABLE = 0x00000000, - MTRAttributeIDTypeClusterRVCOperationalStateAttributeCurrentPhaseID MTR_NEWLY_AVAILABLE = 0x00000001, - MTRAttributeIDTypeClusterRVCOperationalStateAttributeCountdownTimeID MTR_NEWLY_AVAILABLE = 0x00000002, - MTRAttributeIDTypeClusterRVCOperationalStateAttributeOperationalStateListID MTR_NEWLY_AVAILABLE = 0x00000003, - MTRAttributeIDTypeClusterRVCOperationalStateAttributeOperationalStateID MTR_NEWLY_AVAILABLE = 0x00000004, - MTRAttributeIDTypeClusterRVCOperationalStateAttributeOperationalErrorID MTR_NEWLY_AVAILABLE = 0x00000005, - MTRAttributeIDTypeClusterRVCOperationalStateAttributeGeneratedCommandListID MTR_NEWLY_AVAILABLE - = MTRAttributeIDTypeGlobalAttributeGeneratedCommandListID, - MTRAttributeIDTypeClusterRVCOperationalStateAttributeAcceptedCommandListID MTR_NEWLY_AVAILABLE - = MTRAttributeIDTypeGlobalAttributeAcceptedCommandListID, - MTRAttributeIDTypeClusterRVCOperationalStateAttributeEventListID MTR_NEWLY_AVAILABLE - = MTRAttributeIDTypeGlobalAttributeEventListID, - MTRAttributeIDTypeClusterRVCOperationalStateAttributeAttributeListID MTR_NEWLY_AVAILABLE - = MTRAttributeIDTypeGlobalAttributeAttributeListID, - MTRAttributeIDTypeClusterRVCOperationalStateAttributeFeatureMapID MTR_NEWLY_AVAILABLE - = MTRAttributeIDTypeGlobalAttributeFeatureMapID, - MTRAttributeIDTypeClusterRVCOperationalStateAttributeClusterRevisionID MTR_NEWLY_AVAILABLE - = MTRAttributeIDTypeGlobalAttributeClusterRevisionID, - // Cluster HEPAFilterMonitoring attributes MTRAttributeIDTypeClusterHEPAFilterMonitoringAttributeConditionID MTR_NEWLY_AVAILABLE = 0x00000000, MTRAttributeIDTypeClusterHEPAFilterMonitoringAttributeDegradationDirectionID MTR_NEWLY_AVAILABLE = 0x00000001, @@ -9297,13 +9276,6 @@ typedef NS_ENUM(uint32_t, MTRCommandIDType) { MTRCommandIDTypeClusterOperationalStateCommandResumeID MTR_NEWLY_AVAILABLE = 0x00000003, MTRCommandIDTypeClusterOperationalStateCommandOperationalCommandResponseID MTR_NEWLY_AVAILABLE = 0x00000004, - // Cluster RVCOperationalState commands - MTRCommandIDTypeClusterRVCOperationalStateCommandPauseID MTR_NEWLY_AVAILABLE = 0x00000000, - MTRCommandIDTypeClusterRVCOperationalStateCommandStopID MTR_NEWLY_AVAILABLE = 0x00000001, - MTRCommandIDTypeClusterRVCOperationalStateCommandStartID MTR_NEWLY_AVAILABLE = 0x00000002, - MTRCommandIDTypeClusterRVCOperationalStateCommandResumeID MTR_NEWLY_AVAILABLE = 0x00000003, - MTRCommandIDTypeClusterRVCOperationalStateCommandOperationalCommandResponseID MTR_NEWLY_AVAILABLE = 0x00000004, - // Cluster HEPAFilterMonitoring commands MTRCommandIDTypeClusterHEPAFilterMonitoringCommandResetConditionID MTR_NEWLY_AVAILABLE = 0x00000000, @@ -10453,10 +10425,6 @@ typedef NS_ENUM(uint32_t, MTREventIDType) { MTREventIDTypeClusterOperationalStateEventOperationalErrorID MTR_NEWLY_AVAILABLE = 0x00000000, MTREventIDTypeClusterOperationalStateEventOperationCompletionID MTR_NEWLY_AVAILABLE = 0x00000001, - // Cluster RVCOperationalState events - MTREventIDTypeClusterRVCOperationalStateEventOperationalErrorID MTR_NEWLY_AVAILABLE = 0x00000000, - MTREventIDTypeClusterRVCOperationalStateEventOperationCompletionID MTR_NEWLY_AVAILABLE = 0x00000001, - // Cluster DoorLock deprecated event names MTRClusterDoorLockEventDoorLockAlarmID MTR_DEPRECATED("Please use MTREventIDTypeClusterDoorLockEventDoorLockAlarmID", ios(16.1, 16.4), macos(13.0, 13.3), watchos(9.1, 9.4), tvos(16.1, 16.4)) diff --git a/src/darwin/Framework/CHIP/zap-generated/MTRClusters.h b/src/darwin/Framework/CHIP/zap-generated/MTRClusters.h index 7f62aa4280d55d..dcc4a1916f0fe1 100644 --- a/src/darwin/Framework/CHIP/zap-generated/MTRClusters.h +++ b/src/darwin/Framework/CHIP/zap-generated/MTRClusters.h @@ -3056,83 +3056,6 @@ MTR_NEWLY_AVAILABLE @end -/** - * Cluster RVC Operational State - * This cluster supports remotely monitoring and, where supported, changing the operational state of a Robotic Vacuum. - */ -MTR_NEWLY_AVAILABLE -@interface MTRClusterRVCOperationalState : MTRCluster - -- (instancetype _Nullable)initWithDevice:(MTRDevice *)device - endpointID:(NSNumber *)endpointID - queue:(dispatch_queue_t)queue NS_DESIGNATED_INITIALIZER MTR_NEWLY_AVAILABLE; - -- (void)pauseWithParams:(MTRRVCOperationalStateClusterPauseParams * _Nullable)params - expectedValues:(NSArray *> * _Nullable)expectedDataValueDictionaries - expectedValueInterval:(NSNumber * _Nullable)expectedValueIntervalMs - completion:(void (^)(MTRRVCOperationalStateClusterOperationalCommandResponseParams * _Nullable data, - NSError * _Nullable error))completion MTR_NEWLY_AVAILABLE; -- (void)pauseWithExpectedValues:(NSArray *> *)expectedValues - expectedValueInterval:(NSNumber *)expectedValueIntervalMs - completion:(void (^)(MTRRVCOperationalStateClusterOperationalCommandResponseParams * _Nullable data, - NSError * _Nullable error))completion MTR_NEWLY_AVAILABLE; -- (void)stopWithParams:(MTRRVCOperationalStateClusterStopParams * _Nullable)params - expectedValues:(NSArray *> * _Nullable)expectedDataValueDictionaries - expectedValueInterval:(NSNumber * _Nullable)expectedValueIntervalMs - completion:(void (^)(MTRRVCOperationalStateClusterOperationalCommandResponseParams * _Nullable data, - NSError * _Nullable error))completion MTR_NEWLY_AVAILABLE; -- (void)stopWithExpectedValues:(NSArray *> *)expectedValues - expectedValueInterval:(NSNumber *)expectedValueIntervalMs - completion:(void (^)(MTRRVCOperationalStateClusterOperationalCommandResponseParams * _Nullable data, - NSError * _Nullable error))completion MTR_NEWLY_AVAILABLE; -- (void)startWithParams:(MTRRVCOperationalStateClusterStartParams * _Nullable)params - expectedValues:(NSArray *> * _Nullable)expectedDataValueDictionaries - expectedValueInterval:(NSNumber * _Nullable)expectedValueIntervalMs - completion:(void (^)(MTRRVCOperationalStateClusterOperationalCommandResponseParams * _Nullable data, - NSError * _Nullable error))completion MTR_NEWLY_AVAILABLE; -- (void)startWithExpectedValues:(NSArray *> *)expectedValues - expectedValueInterval:(NSNumber *)expectedValueIntervalMs - completion:(void (^)(MTRRVCOperationalStateClusterOperationalCommandResponseParams * _Nullable data, - NSError * _Nullable error))completion MTR_NEWLY_AVAILABLE; -- (void)resumeWithParams:(MTRRVCOperationalStateClusterResumeParams * _Nullable)params - expectedValues:(NSArray *> * _Nullable)expectedDataValueDictionaries - expectedValueInterval:(NSNumber * _Nullable)expectedValueIntervalMs - completion:(void (^)(MTRRVCOperationalStateClusterOperationalCommandResponseParams * _Nullable data, - NSError * _Nullable error))completion MTR_NEWLY_AVAILABLE; -- (void)resumeWithExpectedValues:(NSArray *> *)expectedValues - expectedValueInterval:(NSNumber *)expectedValueIntervalMs - completion:(void (^)(MTRRVCOperationalStateClusterOperationalCommandResponseParams * _Nullable data, - NSError * _Nullable error))completion MTR_NEWLY_AVAILABLE; - -- (NSDictionary *)readAttributePhaseListWithParams:(MTRReadParams * _Nullable)params MTR_NEWLY_AVAILABLE; - -- (NSDictionary *)readAttributeCurrentPhaseWithParams:(MTRReadParams * _Nullable)params MTR_NEWLY_AVAILABLE; - -- (NSDictionary *)readAttributeCountdownTimeWithParams:(MTRReadParams * _Nullable)params MTR_NEWLY_AVAILABLE; - -- (NSDictionary *)readAttributeOperationalStateListWithParams:(MTRReadParams * _Nullable)params MTR_NEWLY_AVAILABLE; - -- (NSDictionary *)readAttributeOperationalStateWithParams:(MTRReadParams * _Nullable)params MTR_NEWLY_AVAILABLE; - -- (NSDictionary *)readAttributeOperationalErrorWithParams:(MTRReadParams * _Nullable)params MTR_NEWLY_AVAILABLE; - -- (NSDictionary *)readAttributeGeneratedCommandListWithParams:(MTRReadParams * _Nullable)params MTR_NEWLY_AVAILABLE; - -- (NSDictionary *)readAttributeAcceptedCommandListWithParams:(MTRReadParams * _Nullable)params MTR_NEWLY_AVAILABLE; - -- (NSDictionary *)readAttributeEventListWithParams:(MTRReadParams * _Nullable)params MTR_NEWLY_AVAILABLE; - -- (NSDictionary *)readAttributeAttributeListWithParams:(MTRReadParams * _Nullable)params MTR_NEWLY_AVAILABLE; - -- (NSDictionary *)readAttributeFeatureMapWithParams:(MTRReadParams * _Nullable)params MTR_NEWLY_AVAILABLE; - -- (NSDictionary *)readAttributeClusterRevisionWithParams:(MTRReadParams * _Nullable)params MTR_NEWLY_AVAILABLE; - -- (instancetype)init NS_UNAVAILABLE; -+ (instancetype)new NS_UNAVAILABLE; - -@end - /** * Cluster HEPA Filter Monitoring * Attributes and commands for monitoring HEPA filters in a device diff --git a/src/darwin/Framework/CHIP/zap-generated/MTRClusters.mm b/src/darwin/Framework/CHIP/zap-generated/MTRClusters.mm index 99f1566cb1bc91..2f1684e89b3480 100644 --- a/src/darwin/Framework/CHIP/zap-generated/MTRClusters.mm +++ b/src/darwin/Framework/CHIP/zap-generated/MTRClusters.mm @@ -13913,423 +13913,6 @@ - (void)resumeWithParams:(MTROperationalStateClusterResumeParams * _Nullable)par @end -@implementation MTRClusterRVCOperationalState - -- (instancetype)initWithDevice:(MTRDevice *)device endpointID:(NSNumber *)endpointID queue:(dispatch_queue_t)queue -{ - if (self = [super initWithQueue:queue]) { - if (device == nil) { - return nil; - } - - _endpoint = [endpointID unsignedShortValue]; - _device = device; - } - return self; -} - -- (void)pauseWithExpectedValues:(NSArray *> *)expectedValues - expectedValueInterval:(NSNumber *)expectedValueIntervalMs - completion:(void (^)(MTRRVCOperationalStateClusterOperationalCommandResponseParams * _Nullable data, - NSError * _Nullable error))completion -{ - [self pauseWithParams:nil expectedValues:expectedValues expectedValueInterval:expectedValueIntervalMs completion:completion]; -} -- (void)pauseWithParams:(MTRRVCOperationalStateClusterPauseParams * _Nullable)params - expectedValues:(NSArray *> *)expectedValues - expectedValueInterval:(NSNumber *)expectedValueIntervalMs - completion:(void (^)(MTRRVCOperationalStateClusterOperationalCommandResponseParams * _Nullable data, - NSError * _Nullable error))completion -{ - NSString * logPrefix = [NSString stringWithFormat:@"MTRDevice command %u %u %u %u", self.device.deviceController.fabricIndex, - _endpoint, (unsigned int) MTRClusterIDTypeRVCOperationalStateID, - (unsigned int) MTRCommandIDTypeClusterRVCOperationalStateCommandPauseID]; - // Make a copy of params before we go async. - params = [params copy]; - NSNumber * timedInvokeTimeoutMsParam = params.timedInvokeTimeoutMs; - if (timedInvokeTimeoutMsParam) { - timedInvokeTimeoutMsParam = MTRClampedNumber(timedInvokeTimeoutMsParam, @(1), @(UINT16_MAX)); - } - MTRAsyncCallbackQueueWorkItem * workItem = [[MTRAsyncCallbackQueueWorkItem alloc] initWithQueue:self.device.queue]; - MTRAsyncCallbackReadyHandler readyHandler = ^(MTRDevice * device, NSUInteger retryCount) { - MTRClustersLogDequeue(logPrefix, self.device.asyncCallbackWorkQueue); - MTRBaseDevice * baseDevice = [[MTRBaseDevice alloc] initWithNodeID:self.device.nodeID - controller:self.device.deviceController]; - auto * bridge = new MTRRVCOperationalStateClusterOperationalCommandResponseCallbackBridge( - self.device.queue, - ^(id _Nullable value, NSError * _Nullable error) { - MTRClustersLogCompletion(logPrefix, value, error); - dispatch_async(self.callbackQueue, ^{ - completion(value, error); - }); - [workItem endWork]; - }, - ^(ExchangeManager & exchangeManager, const SessionHandle & session, - RVCOperationalStateClusterOperationalCommandResponseCallbackType successCb, MTRErrorCallback failureCb, - MTRCallbackBridgeBase * bridge) { - auto * typedBridge = static_cast(bridge); - Optional timedInvokeTimeoutMs; - Optional invokeTimeout; - ListFreer listFreer; - RvcOperationalState::Commands::Pause::Type request; - if (timedInvokeTimeoutMsParam != nil) { - timedInvokeTimeoutMs.SetValue(timedInvokeTimeoutMsParam.unsignedShortValue); - } - if (params != nil) { - if (params.serverSideProcessingTimeout != nil) { - // Clamp to a number of seconds that will not overflow 32-bit - // int when converted to ms. - auto * serverSideProcessingTimeout - = MTRClampedNumber(params.serverSideProcessingTimeout, @(0), @(UINT16_MAX)); - invokeTimeout.SetValue(Seconds16(serverSideProcessingTimeout.unsignedShortValue)); - } - } - - return MTRStartInvokeInteraction(typedBridge, request, exchangeManager, session, successCb, failureCb, - self->_endpoint, timedInvokeTimeoutMs, invokeTimeout); - }); - std::move(*bridge).DispatchAction(baseDevice); - }; - workItem.readyHandler = readyHandler; - MTRClustersLogEnqueue(logPrefix, self.device.asyncCallbackWorkQueue); - [self.device.asyncCallbackWorkQueue enqueueWorkItem:workItem]; - - if (!expectedValueIntervalMs || ([expectedValueIntervalMs compare:@(0)] == NSOrderedAscending)) { - expectedValues = nil; - } else { - expectedValueIntervalMs = MTRClampedNumber(expectedValueIntervalMs, @(1), @(UINT32_MAX)); - } - if (expectedValues) { - [self.device setExpectedValues:expectedValues expectedValueInterval:expectedValueIntervalMs]; - } -} - -- (void)stopWithExpectedValues:(NSArray *> *)expectedValues - expectedValueInterval:(NSNumber *)expectedValueIntervalMs - completion:(void (^)(MTRRVCOperationalStateClusterOperationalCommandResponseParams * _Nullable data, - NSError * _Nullable error))completion -{ - [self stopWithParams:nil expectedValues:expectedValues expectedValueInterval:expectedValueIntervalMs completion:completion]; -} -- (void)stopWithParams:(MTRRVCOperationalStateClusterStopParams * _Nullable)params - expectedValues:(NSArray *> *)expectedValues - expectedValueInterval:(NSNumber *)expectedValueIntervalMs - completion:(void (^)(MTRRVCOperationalStateClusterOperationalCommandResponseParams * _Nullable data, - NSError * _Nullable error))completion -{ - NSString * logPrefix = [NSString stringWithFormat:@"MTRDevice command %u %u %u %u", self.device.deviceController.fabricIndex, - _endpoint, (unsigned int) MTRClusterIDTypeRVCOperationalStateID, - (unsigned int) MTRCommandIDTypeClusterRVCOperationalStateCommandStopID]; - // Make a copy of params before we go async. - params = [params copy]; - NSNumber * timedInvokeTimeoutMsParam = params.timedInvokeTimeoutMs; - if (timedInvokeTimeoutMsParam) { - timedInvokeTimeoutMsParam = MTRClampedNumber(timedInvokeTimeoutMsParam, @(1), @(UINT16_MAX)); - } - MTRAsyncCallbackQueueWorkItem * workItem = [[MTRAsyncCallbackQueueWorkItem alloc] initWithQueue:self.device.queue]; - MTRAsyncCallbackReadyHandler readyHandler = ^(MTRDevice * device, NSUInteger retryCount) { - MTRClustersLogDequeue(logPrefix, self.device.asyncCallbackWorkQueue); - MTRBaseDevice * baseDevice = [[MTRBaseDevice alloc] initWithNodeID:self.device.nodeID - controller:self.device.deviceController]; - auto * bridge = new MTRRVCOperationalStateClusterOperationalCommandResponseCallbackBridge( - self.device.queue, - ^(id _Nullable value, NSError * _Nullable error) { - MTRClustersLogCompletion(logPrefix, value, error); - dispatch_async(self.callbackQueue, ^{ - completion(value, error); - }); - [workItem endWork]; - }, - ^(ExchangeManager & exchangeManager, const SessionHandle & session, - RVCOperationalStateClusterOperationalCommandResponseCallbackType successCb, MTRErrorCallback failureCb, - MTRCallbackBridgeBase * bridge) { - auto * typedBridge = static_cast(bridge); - Optional timedInvokeTimeoutMs; - Optional invokeTimeout; - ListFreer listFreer; - RvcOperationalState::Commands::Stop::Type request; - if (timedInvokeTimeoutMsParam != nil) { - timedInvokeTimeoutMs.SetValue(timedInvokeTimeoutMsParam.unsignedShortValue); - } - if (params != nil) { - if (params.serverSideProcessingTimeout != nil) { - // Clamp to a number of seconds that will not overflow 32-bit - // int when converted to ms. - auto * serverSideProcessingTimeout - = MTRClampedNumber(params.serverSideProcessingTimeout, @(0), @(UINT16_MAX)); - invokeTimeout.SetValue(Seconds16(serverSideProcessingTimeout.unsignedShortValue)); - } - } - - return MTRStartInvokeInteraction(typedBridge, request, exchangeManager, session, successCb, failureCb, - self->_endpoint, timedInvokeTimeoutMs, invokeTimeout); - }); - std::move(*bridge).DispatchAction(baseDevice); - }; - workItem.readyHandler = readyHandler; - MTRClustersLogEnqueue(logPrefix, self.device.asyncCallbackWorkQueue); - [self.device.asyncCallbackWorkQueue enqueueWorkItem:workItem]; - - if (!expectedValueIntervalMs || ([expectedValueIntervalMs compare:@(0)] == NSOrderedAscending)) { - expectedValues = nil; - } else { - expectedValueIntervalMs = MTRClampedNumber(expectedValueIntervalMs, @(1), @(UINT32_MAX)); - } - if (expectedValues) { - [self.device setExpectedValues:expectedValues expectedValueInterval:expectedValueIntervalMs]; - } -} - -- (void)startWithExpectedValues:(NSArray *> *)expectedValues - expectedValueInterval:(NSNumber *)expectedValueIntervalMs - completion:(void (^)(MTRRVCOperationalStateClusterOperationalCommandResponseParams * _Nullable data, - NSError * _Nullable error))completion -{ - [self startWithParams:nil expectedValues:expectedValues expectedValueInterval:expectedValueIntervalMs completion:completion]; -} -- (void)startWithParams:(MTRRVCOperationalStateClusterStartParams * _Nullable)params - expectedValues:(NSArray *> *)expectedValues - expectedValueInterval:(NSNumber *)expectedValueIntervalMs - completion:(void (^)(MTRRVCOperationalStateClusterOperationalCommandResponseParams * _Nullable data, - NSError * _Nullable error))completion -{ - NSString * logPrefix = [NSString stringWithFormat:@"MTRDevice command %u %u %u %u", self.device.deviceController.fabricIndex, - _endpoint, (unsigned int) MTRClusterIDTypeRVCOperationalStateID, - (unsigned int) MTRCommandIDTypeClusterRVCOperationalStateCommandStartID]; - // Make a copy of params before we go async. - params = [params copy]; - NSNumber * timedInvokeTimeoutMsParam = params.timedInvokeTimeoutMs; - if (timedInvokeTimeoutMsParam) { - timedInvokeTimeoutMsParam = MTRClampedNumber(timedInvokeTimeoutMsParam, @(1), @(UINT16_MAX)); - } - MTRAsyncCallbackQueueWorkItem * workItem = [[MTRAsyncCallbackQueueWorkItem alloc] initWithQueue:self.device.queue]; - MTRAsyncCallbackReadyHandler readyHandler = ^(MTRDevice * device, NSUInteger retryCount) { - MTRClustersLogDequeue(logPrefix, self.device.asyncCallbackWorkQueue); - MTRBaseDevice * baseDevice = [[MTRBaseDevice alloc] initWithNodeID:self.device.nodeID - controller:self.device.deviceController]; - auto * bridge = new MTRRVCOperationalStateClusterOperationalCommandResponseCallbackBridge( - self.device.queue, - ^(id _Nullable value, NSError * _Nullable error) { - MTRClustersLogCompletion(logPrefix, value, error); - dispatch_async(self.callbackQueue, ^{ - completion(value, error); - }); - [workItem endWork]; - }, - ^(ExchangeManager & exchangeManager, const SessionHandle & session, - RVCOperationalStateClusterOperationalCommandResponseCallbackType successCb, MTRErrorCallback failureCb, - MTRCallbackBridgeBase * bridge) { - auto * typedBridge = static_cast(bridge); - Optional timedInvokeTimeoutMs; - Optional invokeTimeout; - ListFreer listFreer; - RvcOperationalState::Commands::Start::Type request; - if (timedInvokeTimeoutMsParam != nil) { - timedInvokeTimeoutMs.SetValue(timedInvokeTimeoutMsParam.unsignedShortValue); - } - if (params != nil) { - if (params.serverSideProcessingTimeout != nil) { - // Clamp to a number of seconds that will not overflow 32-bit - // int when converted to ms. - auto * serverSideProcessingTimeout - = MTRClampedNumber(params.serverSideProcessingTimeout, @(0), @(UINT16_MAX)); - invokeTimeout.SetValue(Seconds16(serverSideProcessingTimeout.unsignedShortValue)); - } - } - - return MTRStartInvokeInteraction(typedBridge, request, exchangeManager, session, successCb, failureCb, - self->_endpoint, timedInvokeTimeoutMs, invokeTimeout); - }); - std::move(*bridge).DispatchAction(baseDevice); - }; - workItem.readyHandler = readyHandler; - MTRClustersLogEnqueue(logPrefix, self.device.asyncCallbackWorkQueue); - [self.device.asyncCallbackWorkQueue enqueueWorkItem:workItem]; - - if (!expectedValueIntervalMs || ([expectedValueIntervalMs compare:@(0)] == NSOrderedAscending)) { - expectedValues = nil; - } else { - expectedValueIntervalMs = MTRClampedNumber(expectedValueIntervalMs, @(1), @(UINT32_MAX)); - } - if (expectedValues) { - [self.device setExpectedValues:expectedValues expectedValueInterval:expectedValueIntervalMs]; - } -} - -- (void)resumeWithExpectedValues:(NSArray *> *)expectedValues - expectedValueInterval:(NSNumber *)expectedValueIntervalMs - completion:(void (^)(MTRRVCOperationalStateClusterOperationalCommandResponseParams * _Nullable data, - NSError * _Nullable error))completion -{ - [self resumeWithParams:nil expectedValues:expectedValues expectedValueInterval:expectedValueIntervalMs completion:completion]; -} -- (void)resumeWithParams:(MTRRVCOperationalStateClusterResumeParams * _Nullable)params - expectedValues:(NSArray *> *)expectedValues - expectedValueInterval:(NSNumber *)expectedValueIntervalMs - completion:(void (^)(MTRRVCOperationalStateClusterOperationalCommandResponseParams * _Nullable data, - NSError * _Nullable error))completion -{ - NSString * logPrefix = [NSString stringWithFormat:@"MTRDevice command %u %u %u %u", self.device.deviceController.fabricIndex, - _endpoint, (unsigned int) MTRClusterIDTypeRVCOperationalStateID, - (unsigned int) MTRCommandIDTypeClusterRVCOperationalStateCommandResumeID]; - // Make a copy of params before we go async. - params = [params copy]; - NSNumber * timedInvokeTimeoutMsParam = params.timedInvokeTimeoutMs; - if (timedInvokeTimeoutMsParam) { - timedInvokeTimeoutMsParam = MTRClampedNumber(timedInvokeTimeoutMsParam, @(1), @(UINT16_MAX)); - } - MTRAsyncCallbackQueueWorkItem * workItem = [[MTRAsyncCallbackQueueWorkItem alloc] initWithQueue:self.device.queue]; - MTRAsyncCallbackReadyHandler readyHandler = ^(MTRDevice * device, NSUInteger retryCount) { - MTRClustersLogDequeue(logPrefix, self.device.asyncCallbackWorkQueue); - MTRBaseDevice * baseDevice = [[MTRBaseDevice alloc] initWithNodeID:self.device.nodeID - controller:self.device.deviceController]; - auto * bridge = new MTRRVCOperationalStateClusterOperationalCommandResponseCallbackBridge( - self.device.queue, - ^(id _Nullable value, NSError * _Nullable error) { - MTRClustersLogCompletion(logPrefix, value, error); - dispatch_async(self.callbackQueue, ^{ - completion(value, error); - }); - [workItem endWork]; - }, - ^(ExchangeManager & exchangeManager, const SessionHandle & session, - RVCOperationalStateClusterOperationalCommandResponseCallbackType successCb, MTRErrorCallback failureCb, - MTRCallbackBridgeBase * bridge) { - auto * typedBridge = static_cast(bridge); - Optional timedInvokeTimeoutMs; - Optional invokeTimeout; - ListFreer listFreer; - RvcOperationalState::Commands::Resume::Type request; - if (timedInvokeTimeoutMsParam != nil) { - timedInvokeTimeoutMs.SetValue(timedInvokeTimeoutMsParam.unsignedShortValue); - } - if (params != nil) { - if (params.serverSideProcessingTimeout != nil) { - // Clamp to a number of seconds that will not overflow 32-bit - // int when converted to ms. - auto * serverSideProcessingTimeout - = MTRClampedNumber(params.serverSideProcessingTimeout, @(0), @(UINT16_MAX)); - invokeTimeout.SetValue(Seconds16(serverSideProcessingTimeout.unsignedShortValue)); - } - } - - return MTRStartInvokeInteraction(typedBridge, request, exchangeManager, session, successCb, failureCb, - self->_endpoint, timedInvokeTimeoutMs, invokeTimeout); - }); - std::move(*bridge).DispatchAction(baseDevice); - }; - workItem.readyHandler = readyHandler; - MTRClustersLogEnqueue(logPrefix, self.device.asyncCallbackWorkQueue); - [self.device.asyncCallbackWorkQueue enqueueWorkItem:workItem]; - - if (!expectedValueIntervalMs || ([expectedValueIntervalMs compare:@(0)] == NSOrderedAscending)) { - expectedValues = nil; - } else { - expectedValueIntervalMs = MTRClampedNumber(expectedValueIntervalMs, @(1), @(UINT32_MAX)); - } - if (expectedValues) { - [self.device setExpectedValues:expectedValues expectedValueInterval:expectedValueIntervalMs]; - } -} - -- (NSDictionary *)readAttributePhaseListWithParams:(MTRReadParams * _Nullable)params -{ - return [self.device readAttributeWithEndpointID:@(_endpoint) - clusterID:@(MTRClusterIDTypeRVCOperationalStateID) - attributeID:@(MTRAttributeIDTypeClusterRVCOperationalStateAttributePhaseListID) - params:params]; -} - -- (NSDictionary *)readAttributeCurrentPhaseWithParams:(MTRReadParams * _Nullable)params -{ - return [self.device readAttributeWithEndpointID:@(_endpoint) - clusterID:@(MTRClusterIDTypeRVCOperationalStateID) - attributeID:@(MTRAttributeIDTypeClusterRVCOperationalStateAttributeCurrentPhaseID) - params:params]; -} - -- (NSDictionary *)readAttributeCountdownTimeWithParams:(MTRReadParams * _Nullable)params -{ - return [self.device readAttributeWithEndpointID:@(_endpoint) - clusterID:@(MTRClusterIDTypeRVCOperationalStateID) - attributeID:@(MTRAttributeIDTypeClusterRVCOperationalStateAttributeCountdownTimeID) - params:params]; -} - -- (NSDictionary *)readAttributeOperationalStateListWithParams:(MTRReadParams * _Nullable)params -{ - return [self.device readAttributeWithEndpointID:@(_endpoint) - clusterID:@(MTRClusterIDTypeRVCOperationalStateID) - attributeID:@(MTRAttributeIDTypeClusterRVCOperationalStateAttributeOperationalStateListID) - params:params]; -} - -- (NSDictionary *)readAttributeOperationalStateWithParams:(MTRReadParams * _Nullable)params -{ - return [self.device readAttributeWithEndpointID:@(_endpoint) - clusterID:@(MTRClusterIDTypeRVCOperationalStateID) - attributeID:@(MTRAttributeIDTypeClusterRVCOperationalStateAttributeOperationalStateID) - params:params]; -} - -- (NSDictionary *)readAttributeOperationalErrorWithParams:(MTRReadParams * _Nullable)params -{ - return [self.device readAttributeWithEndpointID:@(_endpoint) - clusterID:@(MTRClusterIDTypeRVCOperationalStateID) - attributeID:@(MTRAttributeIDTypeClusterRVCOperationalStateAttributeOperationalErrorID) - params:params]; -} - -- (NSDictionary *)readAttributeGeneratedCommandListWithParams:(MTRReadParams * _Nullable)params -{ - return [self.device readAttributeWithEndpointID:@(_endpoint) - clusterID:@(MTRClusterIDTypeRVCOperationalStateID) - attributeID:@(MTRAttributeIDTypeClusterRVCOperationalStateAttributeGeneratedCommandListID) - params:params]; -} - -- (NSDictionary *)readAttributeAcceptedCommandListWithParams:(MTRReadParams * _Nullable)params -{ - return [self.device readAttributeWithEndpointID:@(_endpoint) - clusterID:@(MTRClusterIDTypeRVCOperationalStateID) - attributeID:@(MTRAttributeIDTypeClusterRVCOperationalStateAttributeAcceptedCommandListID) - params:params]; -} - -- (NSDictionary *)readAttributeEventListWithParams:(MTRReadParams * _Nullable)params -{ - return [self.device readAttributeWithEndpointID:@(_endpoint) - clusterID:@(MTRClusterIDTypeRVCOperationalStateID) - attributeID:@(MTRAttributeIDTypeClusterRVCOperationalStateAttributeEventListID) - params:params]; -} - -- (NSDictionary *)readAttributeAttributeListWithParams:(MTRReadParams * _Nullable)params -{ - return [self.device readAttributeWithEndpointID:@(_endpoint) - clusterID:@(MTRClusterIDTypeRVCOperationalStateID) - attributeID:@(MTRAttributeIDTypeClusterRVCOperationalStateAttributeAttributeListID) - params:params]; -} - -- (NSDictionary *)readAttributeFeatureMapWithParams:(MTRReadParams * _Nullable)params -{ - return [self.device readAttributeWithEndpointID:@(_endpoint) - clusterID:@(MTRClusterIDTypeRVCOperationalStateID) - attributeID:@(MTRAttributeIDTypeClusterRVCOperationalStateAttributeFeatureMapID) - params:params]; -} - -- (NSDictionary *)readAttributeClusterRevisionWithParams:(MTRReadParams * _Nullable)params -{ - return [self.device readAttributeWithEndpointID:@(_endpoint) - clusterID:@(MTRClusterIDTypeRVCOperationalStateID) - attributeID:@(MTRAttributeIDTypeClusterRVCOperationalStateAttributeClusterRevisionID) - params:params]; -} - -@end - @implementation MTRClusterHEPAFilterMonitoring - (instancetype)initWithDevice:(MTRDevice *)device endpointID:(NSNumber *)endpointID queue:(dispatch_queue_t)queue diff --git a/src/darwin/Framework/CHIP/zap-generated/MTRClusters_Internal.h b/src/darwin/Framework/CHIP/zap-generated/MTRClusters_Internal.h index 849782b23cad83..8c738156db2ce6 100644 --- a/src/darwin/Framework/CHIP/zap-generated/MTRClusters_Internal.h +++ b/src/darwin/Framework/CHIP/zap-generated/MTRClusters_Internal.h @@ -226,11 +226,6 @@ @property (nonatomic, readonly) MTRDevice * device; @end -@interface MTRClusterRVCOperationalState () -@property (nonatomic, readonly) uint16_t endpoint; -@property (nonatomic, readonly) MTRDevice * device; -@end - @interface MTRClusterHEPAFilterMonitoring () @property (nonatomic, readonly) uint16_t endpoint; @property (nonatomic, readonly) MTRDevice * device; diff --git a/src/darwin/Framework/CHIP/zap-generated/MTRCommandPayloadsObjc.h b/src/darwin/Framework/CHIP/zap-generated/MTRCommandPayloadsObjc.h index 8838c0c06e0703..c8e9c13f87d418 100644 --- a/src/darwin/Framework/CHIP/zap-generated/MTRCommandPayloadsObjc.h +++ b/src/darwin/Framework/CHIP/zap-generated/MTRCommandPayloadsObjc.h @@ -4266,137 +4266,6 @@ MTR_NEWLY_AVAILABLE error:(NSError * __autoreleasing *)error MTR_NEWLY_AVAILABLE; @end -MTR_NEWLY_AVAILABLE -@interface MTRRVCOperationalStateClusterPauseParams : NSObject -/** - * Controls whether the command is a timed command (using Timed Invoke). - * - * If nil (the default value), a regular invoke is done for commands that do - * not require a timed invoke and a timed invoke with some default timed request - * timeout is done for commands that require a timed invoke. - * - * If not nil, a timed invoke is done, with the provided value used as the timed - * request timeout. The value should be chosen small enough to provide the - * desired security properties but large enough that it will allow a round-trip - * from the sever to the client (for the status response and actual invoke - * request) within the timeout window. - * - */ -@property (nonatomic, copy, nullable) NSNumber * timedInvokeTimeoutMs; - -/** - * Controls how much time, in seconds, we will allow for the server to process the command. - * - * The command will then time out if that much time, plus an allowance for retransmits due to network failures, passes. - * - * If nil, the framework will try to select an appropriate timeout value itself. - */ -@property (nonatomic, copy, nullable) NSNumber * serverSideProcessingTimeout; -@end - -MTR_NEWLY_AVAILABLE -@interface MTRRVCOperationalStateClusterStopParams : NSObject -/** - * Controls whether the command is a timed command (using Timed Invoke). - * - * If nil (the default value), a regular invoke is done for commands that do - * not require a timed invoke and a timed invoke with some default timed request - * timeout is done for commands that require a timed invoke. - * - * If not nil, a timed invoke is done, with the provided value used as the timed - * request timeout. The value should be chosen small enough to provide the - * desired security properties but large enough that it will allow a round-trip - * from the sever to the client (for the status response and actual invoke - * request) within the timeout window. - * - */ -@property (nonatomic, copy, nullable) NSNumber * timedInvokeTimeoutMs; - -/** - * Controls how much time, in seconds, we will allow for the server to process the command. - * - * The command will then time out if that much time, plus an allowance for retransmits due to network failures, passes. - * - * If nil, the framework will try to select an appropriate timeout value itself. - */ -@property (nonatomic, copy, nullable) NSNumber * serverSideProcessingTimeout; -@end - -MTR_NEWLY_AVAILABLE -@interface MTRRVCOperationalStateClusterStartParams : NSObject -/** - * Controls whether the command is a timed command (using Timed Invoke). - * - * If nil (the default value), a regular invoke is done for commands that do - * not require a timed invoke and a timed invoke with some default timed request - * timeout is done for commands that require a timed invoke. - * - * If not nil, a timed invoke is done, with the provided value used as the timed - * request timeout. The value should be chosen small enough to provide the - * desired security properties but large enough that it will allow a round-trip - * from the sever to the client (for the status response and actual invoke - * request) within the timeout window. - * - */ -@property (nonatomic, copy, nullable) NSNumber * timedInvokeTimeoutMs; - -/** - * Controls how much time, in seconds, we will allow for the server to process the command. - * - * The command will then time out if that much time, plus an allowance for retransmits due to network failures, passes. - * - * If nil, the framework will try to select an appropriate timeout value itself. - */ -@property (nonatomic, copy, nullable) NSNumber * serverSideProcessingTimeout; -@end - -MTR_NEWLY_AVAILABLE -@interface MTRRVCOperationalStateClusterResumeParams : NSObject -/** - * Controls whether the command is a timed command (using Timed Invoke). - * - * If nil (the default value), a regular invoke is done for commands that do - * not require a timed invoke and a timed invoke with some default timed request - * timeout is done for commands that require a timed invoke. - * - * If not nil, a timed invoke is done, with the provided value used as the timed - * request timeout. The value should be chosen small enough to provide the - * desired security properties but large enough that it will allow a round-trip - * from the sever to the client (for the status response and actual invoke - * request) within the timeout window. - * - */ -@property (nonatomic, copy, nullable) NSNumber * timedInvokeTimeoutMs; - -/** - * Controls how much time, in seconds, we will allow for the server to process the command. - * - * The command will then time out if that much time, plus an allowance for retransmits due to network failures, passes. - * - * If nil, the framework will try to select an appropriate timeout value itself. - */ -@property (nonatomic, copy, nullable) NSNumber * serverSideProcessingTimeout; -@end - -MTR_NEWLY_AVAILABLE -@interface MTRRVCOperationalStateClusterOperationalCommandResponseParams : NSObject - -@property (nonatomic, copy) MTRRVCOperationalStateClusterErrorStateStruct * _Nonnull commandResponseState MTR_NEWLY_AVAILABLE; - -/** - * Initialize an MTRRVCOperationalStateClusterOperationalCommandResponseParams with a response-value dictionary - * of the sort that MTRDeviceResponseHandler would receive. - * - * Will return nil and hand out an error if the response-value dictionary is not - * a command data response or is not the right command response. - * - * Will return nil and hand out an error if the data response does not match the known - * schema for this command. - */ -- (nullable instancetype)initWithResponseValue:(NSDictionary *)responseValue - error:(NSError * __autoreleasing *)error MTR_NEWLY_AVAILABLE; -@end - MTR_NEWLY_AVAILABLE @interface MTRHEPAFilterMonitoringClusterResetConditionParams : NSObject /** diff --git a/src/darwin/Framework/CHIP/zap-generated/MTRCommandPayloadsObjc.mm b/src/darwin/Framework/CHIP/zap-generated/MTRCommandPayloadsObjc.mm index 7e03309d57cca3..a99ccebd27db17 100644 --- a/src/darwin/Framework/CHIP/zap-generated/MTRCommandPayloadsObjc.mm +++ b/src/darwin/Framework/CHIP/zap-generated/MTRCommandPayloadsObjc.mm @@ -6714,213 +6714,6 @@ - (CHIP_ERROR)_setFieldsFromDecodableStruct: return CHIP_NO_ERROR; } @end -@implementation MTRRVCOperationalStateClusterPauseParams -- (instancetype)init -{ - if (self = [super init]) { - _timedInvokeTimeoutMs = nil; - _serverSideProcessingTimeout = nil; - } - return self; -} - -- (id)copyWithZone:(NSZone * _Nullable)zone; -{ - auto other = [[MTRRVCOperationalStateClusterPauseParams alloc] init]; - - other.timedInvokeTimeoutMs = self.timedInvokeTimeoutMs; - other.serverSideProcessingTimeout = self.serverSideProcessingTimeout; - - return other; -} - -- (NSString *)description -{ - NSString * descriptionString = [NSString stringWithFormat:@"<%@: >", NSStringFromClass([self class])]; - return descriptionString; -} - -@end -@implementation MTRRVCOperationalStateClusterStopParams -- (instancetype)init -{ - if (self = [super init]) { - _timedInvokeTimeoutMs = nil; - _serverSideProcessingTimeout = nil; - } - return self; -} - -- (id)copyWithZone:(NSZone * _Nullable)zone; -{ - auto other = [[MTRRVCOperationalStateClusterStopParams alloc] init]; - - other.timedInvokeTimeoutMs = self.timedInvokeTimeoutMs; - other.serverSideProcessingTimeout = self.serverSideProcessingTimeout; - - return other; -} - -- (NSString *)description -{ - NSString * descriptionString = [NSString stringWithFormat:@"<%@: >", NSStringFromClass([self class])]; - return descriptionString; -} - -@end -@implementation MTRRVCOperationalStateClusterStartParams -- (instancetype)init -{ - if (self = [super init]) { - _timedInvokeTimeoutMs = nil; - _serverSideProcessingTimeout = nil; - } - return self; -} - -- (id)copyWithZone:(NSZone * _Nullable)zone; -{ - auto other = [[MTRRVCOperationalStateClusterStartParams alloc] init]; - - other.timedInvokeTimeoutMs = self.timedInvokeTimeoutMs; - other.serverSideProcessingTimeout = self.serverSideProcessingTimeout; - - return other; -} - -- (NSString *)description -{ - NSString * descriptionString = [NSString stringWithFormat:@"<%@: >", NSStringFromClass([self class])]; - return descriptionString; -} - -@end -@implementation MTRRVCOperationalStateClusterResumeParams -- (instancetype)init -{ - if (self = [super init]) { - _timedInvokeTimeoutMs = nil; - _serverSideProcessingTimeout = nil; - } - return self; -} - -- (id)copyWithZone:(NSZone * _Nullable)zone; -{ - auto other = [[MTRRVCOperationalStateClusterResumeParams alloc] init]; - - other.timedInvokeTimeoutMs = self.timedInvokeTimeoutMs; - other.serverSideProcessingTimeout = self.serverSideProcessingTimeout; - - return other; -} - -- (NSString *)description -{ - NSString * descriptionString = [NSString stringWithFormat:@"<%@: >", NSStringFromClass([self class])]; - return descriptionString; -} - -@end -@implementation MTRRVCOperationalStateClusterOperationalCommandResponseParams -- (instancetype)init -{ - if (self = [super init]) { - - _commandResponseState = [MTRRVCOperationalStateClusterErrorStateStruct new]; - } - return self; -} - -- (id)copyWithZone:(NSZone * _Nullable)zone; -{ - auto other = [[MTRRVCOperationalStateClusterOperationalCommandResponseParams alloc] init]; - - other.commandResponseState = self.commandResponseState; - - return other; -} - -- (NSString *)description -{ - NSString * descriptionString = - [NSString stringWithFormat:@"<%@: commandResponseState:%@; >", NSStringFromClass([self class]), _commandResponseState]; - return descriptionString; -} - -- (nullable instancetype)initWithResponseValue:(NSDictionary *)responseValue - error:(NSError * __autoreleasing *)error -{ - if (!(self = [super init])) { - return nil; - } - - using DecodableType = chip::app::Clusters::RvcOperationalState::Commands::OperationalCommandResponse::DecodableType; - chip::System::PacketBufferHandle buffer = [MTRBaseDevice _responseDataForCommand:responseValue - clusterID:DecodableType::GetClusterId() - commandID:DecodableType::GetCommandId() - error:error]; - if (buffer.IsNull()) { - return nil; - } - - chip::TLV::TLVReader reader; - reader.Init(buffer->Start(), buffer->DataLength()); - - CHIP_ERROR err = reader.Next(chip::TLV::AnonymousTag()); - if (err == CHIP_NO_ERROR) { - DecodableType decodedStruct; - err = chip::app::DataModel::Decode(reader, decodedStruct); - if (err == CHIP_NO_ERROR) { - err = [self _setFieldsFromDecodableStruct:decodedStruct]; - if (err == CHIP_NO_ERROR) { - return self; - } - } - } - - NSString * errorStr = [NSString stringWithFormat:@"Command payload decoding failed: %s", err.AsString()]; - MTR_LOG_ERROR("%s", errorStr.UTF8String); - if (error != nil) { - NSDictionary * userInfo = @{ NSLocalizedFailureReasonErrorKey : NSLocalizedString(errorStr, nil) }; - *error = [NSError errorWithDomain:MTRErrorDomain code:MTRErrorCodeSchemaMismatch userInfo:userInfo]; - } - return nil; -} - -@end - -@implementation MTRRVCOperationalStateClusterOperationalCommandResponseParams (InternalMethods) - -- (CHIP_ERROR)_setFieldsFromDecodableStruct: - (const chip::app::Clusters::RvcOperationalState::Commands::OperationalCommandResponse::DecodableType &)decodableStruct -{ - { - self.commandResponseState = [MTRRVCOperationalStateClusterErrorStateStruct new]; - self.commandResponseState.errorStateID = - [NSNumber numberWithUnsignedChar:decodableStruct.commandResponseState.errorStateID]; - if (decodableStruct.commandResponseState.errorStateLabel.HasValue()) { - self.commandResponseState.errorStateLabel = AsString(decodableStruct.commandResponseState.errorStateLabel.Value()); - if (self.commandResponseState.errorStateLabel == nil) { - CHIP_ERROR err = CHIP_ERROR_INVALID_ARGUMENT; - return err; - } - } else { - self.commandResponseState.errorStateLabel = nil; - } - if (decodableStruct.commandResponseState.errorStateDetails.HasValue()) { - self.commandResponseState.errorStateDetails = AsString(decodableStruct.commandResponseState.errorStateDetails.Value()); - if (self.commandResponseState.errorStateDetails == nil) { - CHIP_ERROR err = CHIP_ERROR_INVALID_ARGUMENT; - return err; - } - } else { - self.commandResponseState.errorStateDetails = nil; - } - } - return CHIP_NO_ERROR; -} -@end @implementation MTRHEPAFilterMonitoringClusterResetConditionParams - (instancetype)init { diff --git a/src/darwin/Framework/CHIP/zap-generated/MTRCommandPayloads_Internal.h b/src/darwin/Framework/CHIP/zap-generated/MTRCommandPayloads_Internal.h index 51c8bc30950138..28f95b18ae822e 100644 --- a/src/darwin/Framework/CHIP/zap-generated/MTRCommandPayloads_Internal.h +++ b/src/darwin/Framework/CHIP/zap-generated/MTRCommandPayloads_Internal.h @@ -224,13 +224,6 @@ NS_ASSUME_NONNULL_BEGIN @end -@interface MTRRVCOperationalStateClusterOperationalCommandResponseParams (InternalMethods) - -- (CHIP_ERROR)_setFieldsFromDecodableStruct: - (const chip::app::Clusters::RvcOperationalState::Commands::OperationalCommandResponse::DecodableType &)decodableStruct; - -@end - @interface MTRDoorLockClusterGetWeekDayScheduleResponseParams (InternalMethods) - (CHIP_ERROR)_setFieldsFromDecodableStruct: diff --git a/src/darwin/Framework/CHIP/zap-generated/MTREventTLVValueDecoder.mm b/src/darwin/Framework/CHIP/zap-generated/MTREventTLVValueDecoder.mm index 193a8a34012329..7705e88b2bda4e 100644 --- a/src/darwin/Framework/CHIP/zap-generated/MTREventTLVValueDecoder.mm +++ b/src/darwin/Framework/CHIP/zap-generated/MTREventTLVValueDecoder.mm @@ -1848,99 +1848,6 @@ static id _Nullable DecodeEventPayloadForOperationalStateCluster(EventId aEventI *aError = CHIP_ERROR_IM_MALFORMED_EVENT_PATH_IB; return nil; } -static id _Nullable DecodeEventPayloadForRVCOperationalStateCluster(EventId aEventId, TLV::TLVReader & aReader, CHIP_ERROR * aError) -{ - using namespace Clusters::RvcOperationalState; - switch (aEventId) { - case Events::OperationalError::Id: { - Events::OperationalError::DecodableType cppValue; - *aError = DataModel::Decode(aReader, cppValue); - if (*aError != CHIP_NO_ERROR) { - return nil; - } - - __auto_type * value = [MTRRVCOperationalStateClusterOperationalErrorEvent new]; - - do { - MTRRVCOperationalStateClusterErrorStateStruct * _Nonnull memberValue; - memberValue = [MTRRVCOperationalStateClusterErrorStateStruct new]; - memberValue.errorStateID = [NSNumber numberWithUnsignedChar:cppValue.errorState.errorStateID]; - if (cppValue.errorState.errorStateLabel.HasValue()) { - memberValue.errorStateLabel = AsString(cppValue.errorState.errorStateLabel.Value()); - if (memberValue.errorStateLabel == nil) { - CHIP_ERROR err = CHIP_ERROR_INVALID_ARGUMENT; - *aError = err; - return nil; - } - } else { - memberValue.errorStateLabel = nil; - } - if (cppValue.errorState.errorStateDetails.HasValue()) { - memberValue.errorStateDetails = AsString(cppValue.errorState.errorStateDetails.Value()); - if (memberValue.errorStateDetails == nil) { - CHIP_ERROR err = CHIP_ERROR_INVALID_ARGUMENT; - *aError = err; - return nil; - } - } else { - memberValue.errorStateDetails = nil; - } - value.errorState = memberValue; - } while (0); - - return value; - } - case Events::OperationCompletion::Id: { - Events::OperationCompletion::DecodableType cppValue; - *aError = DataModel::Decode(aReader, cppValue); - if (*aError != CHIP_NO_ERROR) { - return nil; - } - - __auto_type * value = [MTRRVCOperationalStateClusterOperationCompletionEvent new]; - - do { - NSNumber * _Nonnull memberValue; - memberValue = [NSNumber numberWithUnsignedChar:cppValue.completionErrorCode]; - value.completionErrorCode = memberValue; - } while (0); - do { - NSNumber * _Nullable memberValue; - if (cppValue.totalOperationalTime.HasValue()) { - if (cppValue.totalOperationalTime.Value().IsNull()) { - memberValue = nil; - } else { - memberValue = [NSNumber numberWithUnsignedInt:cppValue.totalOperationalTime.Value().Value()]; - } - } else { - memberValue = nil; - } - value.totalOperationalTime = memberValue; - } while (0); - do { - NSNumber * _Nullable memberValue; - if (cppValue.pausedTime.HasValue()) { - if (cppValue.pausedTime.Value().IsNull()) { - memberValue = nil; - } else { - memberValue = [NSNumber numberWithUnsignedInt:cppValue.pausedTime.Value().Value()]; - } - } else { - memberValue = nil; - } - value.pausedTime = memberValue; - } while (0); - - return value; - } - default: { - break; - } - } - - *aError = CHIP_ERROR_IM_MALFORMED_EVENT_PATH_IB; - return nil; -} static id _Nullable DecodeEventPayloadForHEPAFilterMonitoringCluster( EventId aEventId, TLV::TLVReader & aReader, CHIP_ERROR * aError) { @@ -3143,9 +3050,6 @@ id _Nullable MTRDecodeEventPayload(const ConcreteEventPath & aPath, TLV::TLVRead case Clusters::OperationalState::Id: { return DecodeEventPayloadForOperationalStateCluster(aPath.mEventId, aReader, aError); } - case Clusters::RvcOperationalState::Id: { - return DecodeEventPayloadForRVCOperationalStateCluster(aPath.mEventId, aReader, aError); - } case Clusters::HepaFilterMonitoring::Id: { return DecodeEventPayloadForHEPAFilterMonitoringCluster(aPath.mEventId, aReader, aError); } diff --git a/src/darwin/Framework/CHIP/zap-generated/MTRStructsObjc.h b/src/darwin/Framework/CHIP/zap-generated/MTRStructsObjc.h index 63264e74bdead1..076ed268a092cb 100644 --- a/src/darwin/Framework/CHIP/zap-generated/MTRStructsObjc.h +++ b/src/darwin/Framework/CHIP/zap-generated/MTRStructsObjc.h @@ -781,31 +781,6 @@ MTR_NEWLY_AVAILABLE @property (nonatomic, copy) NSNumber * _Nullable pausedTime MTR_NEWLY_AVAILABLE; @end -MTR_NEWLY_AVAILABLE -@interface MTRRVCOperationalStateClusterErrorStateStruct : NSObject -@property (nonatomic, copy) NSNumber * _Nonnull errorStateID MTR_NEWLY_AVAILABLE; -@property (nonatomic, copy) NSString * _Nullable errorStateLabel MTR_NEWLY_AVAILABLE; -@property (nonatomic, copy) NSString * _Nullable errorStateDetails MTR_NEWLY_AVAILABLE; -@end - -MTR_NEWLY_AVAILABLE -@interface MTRRVCOperationalStateClusterOperationalStateStruct : NSObject -@property (nonatomic, copy) NSNumber * _Nonnull operationalStateID MTR_NEWLY_AVAILABLE; -@property (nonatomic, copy) NSString * _Nullable operationalStateLabel MTR_NEWLY_AVAILABLE; -@end - -MTR_NEWLY_AVAILABLE -@interface MTRRVCOperationalStateClusterOperationalErrorEvent : NSObject -@property (nonatomic, copy) MTRRVCOperationalStateClusterErrorStateStruct * _Nonnull errorState MTR_NEWLY_AVAILABLE; -@end - -MTR_NEWLY_AVAILABLE -@interface MTRRVCOperationalStateClusterOperationCompletionEvent : NSObject -@property (nonatomic, copy) NSNumber * _Nonnull completionErrorCode MTR_NEWLY_AVAILABLE; -@property (nonatomic, copy) NSNumber * _Nullable totalOperationalTime MTR_NEWLY_AVAILABLE; -@property (nonatomic, copy) NSNumber * _Nullable pausedTime MTR_NEWLY_AVAILABLE; -@end - API_AVAILABLE(ios(16.4), macos(13.3), watchos(9.4), tvos(16.4)) @interface MTRDoorLockClusterCredentialStruct : NSObject @property (nonatomic, copy) NSNumber * _Nonnull credentialType API_AVAILABLE(ios(16.4), macos(13.3), watchos(9.4), tvos(16.4)); diff --git a/src/darwin/Framework/CHIP/zap-generated/MTRStructsObjc.mm b/src/darwin/Framework/CHIP/zap-generated/MTRStructsObjc.mm index 17046b2bc00ffb..f81221f07a8bed 100644 --- a/src/darwin/Framework/CHIP/zap-generated/MTRStructsObjc.mm +++ b/src/darwin/Framework/CHIP/zap-generated/MTRStructsObjc.mm @@ -3104,134 +3104,6 @@ - (NSString *)description @end -@implementation MTRRVCOperationalStateClusterErrorStateStruct -- (instancetype)init -{ - if (self = [super init]) { - - _errorStateID = @(0); - - _errorStateLabel = nil; - - _errorStateDetails = nil; - } - return self; -} - -- (id)copyWithZone:(NSZone * _Nullable)zone -{ - auto other = [[MTRRVCOperationalStateClusterErrorStateStruct alloc] init]; - - other.errorStateID = self.errorStateID; - other.errorStateLabel = self.errorStateLabel; - other.errorStateDetails = self.errorStateDetails; - - return other; -} - -- (NSString *)description -{ - NSString * descriptionString = [NSString stringWithFormat:@"<%@: errorStateID:%@; errorStateLabel:%@; errorStateDetails:%@; >", - NSStringFromClass([self class]), _errorStateID, _errorStateLabel, _errorStateDetails]; - return descriptionString; -} - -@end - -@implementation MTRRVCOperationalStateClusterOperationalStateStruct -- (instancetype)init -{ - if (self = [super init]) { - - _operationalStateID = @(0); - - _operationalStateLabel = nil; - } - return self; -} - -- (id)copyWithZone:(NSZone * _Nullable)zone -{ - auto other = [[MTRRVCOperationalStateClusterOperationalStateStruct alloc] init]; - - other.operationalStateID = self.operationalStateID; - other.operationalStateLabel = self.operationalStateLabel; - - return other; -} - -- (NSString *)description -{ - NSString * descriptionString = [NSString stringWithFormat:@"<%@: operationalStateID:%@; operationalStateLabel:%@; >", - NSStringFromClass([self class]), _operationalStateID, _operationalStateLabel]; - return descriptionString; -} - -@end - -@implementation MTRRVCOperationalStateClusterOperationalErrorEvent -- (instancetype)init -{ - if (self = [super init]) { - - _errorState = [MTRRVCOperationalStateClusterErrorStateStruct new]; - } - return self; -} - -- (id)copyWithZone:(NSZone * _Nullable)zone -{ - auto other = [[MTRRVCOperationalStateClusterOperationalErrorEvent alloc] init]; - - other.errorState = self.errorState; - - return other; -} - -- (NSString *)description -{ - NSString * descriptionString = - [NSString stringWithFormat:@"<%@: errorState:%@; >", NSStringFromClass([self class]), _errorState]; - return descriptionString; -} - -@end - -@implementation MTRRVCOperationalStateClusterOperationCompletionEvent -- (instancetype)init -{ - if (self = [super init]) { - - _completionErrorCode = @(0); - - _totalOperationalTime = nil; - - _pausedTime = nil; - } - return self; -} - -- (id)copyWithZone:(NSZone * _Nullable)zone -{ - auto other = [[MTRRVCOperationalStateClusterOperationCompletionEvent alloc] init]; - - other.completionErrorCode = self.completionErrorCode; - other.totalOperationalTime = self.totalOperationalTime; - other.pausedTime = self.pausedTime; - - return other; -} - -- (NSString *)description -{ - NSString * descriptionString = - [NSString stringWithFormat:@"<%@: completionErrorCode:%@; totalOperationalTime:%@; pausedTime:%@; >", - NSStringFromClass([self class]), _completionErrorCode, _totalOperationalTime, _pausedTime]; - return descriptionString; -} - -@end - @implementation MTRDoorLockClusterCredentialStruct - (instancetype)init { diff --git a/src/darwin/Framework/Matter.xcodeproj/project.pbxproj b/src/darwin/Framework/Matter.xcodeproj/project.pbxproj index d2d7f3ae8d3cd2..0d07b1e07129a1 100644 --- a/src/darwin/Framework/Matter.xcodeproj/project.pbxproj +++ b/src/darwin/Framework/Matter.xcodeproj/project.pbxproj @@ -79,6 +79,10 @@ 03F430A7299410C000166449 /* ExamplePersistentStorage.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 03F430A6299410C000166449 /* ExamplePersistentStorage.cpp */; }; 03F430A82994112B00166449 /* editline.c in Sources */ = {isa = PBXBuildFile; fileRef = 0395470B2992DB37006D42A8 /* editline.c */; }; 03F430AA2994113500166449 /* sysunix.c in Sources */ = {isa = PBXBuildFile; fileRef = 03F430A92994113500166449 /* sysunix.c */; }; + 1E4D654E29C208DD00BC3478 /* MTRCommissionableBrowserResult.h in Headers */ = {isa = PBXBuildFile; fileRef = 1E4D654B29C208DD00BC3478 /* MTRCommissionableBrowserResult.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 1E4D654F29C208DD00BC3478 /* MTRCommissionableBrowser.h in Headers */ = {isa = PBXBuildFile; fileRef = 1E4D654C29C208DD00BC3478 /* MTRCommissionableBrowser.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 1E4D655029C208DD00BC3478 /* MTRCommissionableBrowserDelegate.h in Headers */ = {isa = PBXBuildFile; fileRef = 1E4D654D29C208DD00BC3478 /* MTRCommissionableBrowserDelegate.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 1E4D655229C30A8700BC3478 /* MTRCommissionableBrowser.mm in Sources */ = {isa = PBXBuildFile; fileRef = 1E4D655129C30A8700BC3478 /* MTRCommissionableBrowser.mm */; }; 1E5801C328941C050033A199 /* MTRTestOTAProvider.m in Sources */ = {isa = PBXBuildFile; fileRef = 1E748B3828941A44008A1BE8 /* MTRTestOTAProvider.m */; }; 1EC3238D271999E2002A8BF0 /* cluster-objects.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 1EC3238C271999E2002A8BF0 /* cluster-objects.cpp */; }; 1EC4CE5D25CC26E900D7304F /* MTRBaseClusters.mm in Sources */ = {isa = PBXBuildFile; fileRef = 1EC4CE5925CC26E900D7304F /* MTRBaseClusters.mm */; }; @@ -347,6 +351,10 @@ 0395470C2992DB37006D42A8 /* complete.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = complete.c; path = repo/src/complete.c; sourceTree = ""; }; 03F430A6299410C000166449 /* ExamplePersistentStorage.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ExamplePersistentStorage.cpp; sourceTree = ""; }; 03F430A92994113500166449 /* sysunix.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = sysunix.c; path = repo/src/sysunix.c; sourceTree = ""; }; + 1E4D654B29C208DD00BC3478 /* MTRCommissionableBrowserResult.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MTRCommissionableBrowserResult.h; sourceTree = ""; }; + 1E4D654C29C208DD00BC3478 /* MTRCommissionableBrowser.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MTRCommissionableBrowser.h; sourceTree = ""; }; + 1E4D654D29C208DD00BC3478 /* MTRCommissionableBrowserDelegate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MTRCommissionableBrowserDelegate.h; sourceTree = ""; }; + 1E4D655129C30A8700BC3478 /* MTRCommissionableBrowser.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = MTRCommissionableBrowser.mm; sourceTree = ""; }; 1E748B3828941A44008A1BE8 /* MTRTestOTAProvider.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MTRTestOTAProvider.m; sourceTree = ""; }; 1E748B3928941A45008A1BE8 /* MTRTestOTAProvider.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MTRTestOTAProvider.h; sourceTree = ""; }; 1EC3238C271999E2002A8BF0 /* cluster-objects.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = "cluster-objects.cpp"; path = "../../../../../zzz_generated/app-common/app-common/zap-generated/cluster-objects.cpp"; sourceTree = ""; }; @@ -944,6 +952,10 @@ B202528F2459E34F00F97062 /* CHIP */ = { isa = PBXGroup; children = ( + 1E4D655129C30A8700BC3478 /* MTRCommissionableBrowser.mm */, + 1E4D654C29C208DD00BC3478 /* MTRCommissionableBrowser.h */, + 1E4D654D29C208DD00BC3478 /* MTRCommissionableBrowserDelegate.h */, + 1E4D654B29C208DD00BC3478 /* MTRCommissionableBrowserResult.h */, 1E857311265519DE0050A4D9 /* app */, 3D843718294984AF0070D20A /* templates */, 1EC4CE5825CC26AB00D7304F /* zap-generated */, @@ -1216,15 +1228,18 @@ 3DECCB742934C21B00585AEC /* MTRDefines.h in Headers */, 2C5EEEF6268A85C400CAE3D3 /* MTRDeviceConnectionBridge.h in Headers */, 2C8C8FC0253E0C2100797F05 /* MTRPersistentStorageDelegateBridge.h in Headers */, + 1E4D654F29C208DD00BC3478 /* MTRCommissionableBrowser.h in Headers */, 51E4D121291D0EB400C8C535 /* MTRBaseClusterUtils.h in Headers */, 51E51FC0282AD37A00FC978D /* MTRDeviceControllerStartupParams_Internal.h in Headers */, 3DECCB702934AECD00585AEC /* MTRLogging.h in Headers */, + 1E4D654E29C208DD00BC3478 /* MTRCommissionableBrowserResult.h in Headers */, 998F286F26D55EC5001846C6 /* MTRP256KeypairBridge.h in Headers */, 2C222ADF255C811800E446B9 /* MTRBaseDevice_Internal.h in Headers */, 511913FC28C100EF009235E9 /* MTRBaseSubscriptionCallback.h in Headers */, 51E0310027EA20D20083DC9C /* MTRControllerAccessControl.h in Headers */, 3D843713294977000070D20A /* NSDataSpanConversion.h in Headers */, 991DC08B247704DC00C13860 /* MTRLogging_Internal.h in Headers */, + 1E4D655029C208DD00BC3478 /* MTRCommissionableBrowserDelegate.h in Headers */, 7596A84828762783004DAE0E /* MTRAsyncCallbackWorkQueue.h in Headers */, 5A7947E527C0129F00434CF2 /* MTRDeviceController+XPC.h in Headers */, B2E0D7B4245B0B5C003C5B48 /* MTRError_Internal.h in Headers */, @@ -1471,6 +1486,7 @@ 88EBF8CF27FABDD500686BC1 /* MTRDeviceAttestationDelegateBridge.mm in Sources */, 5A6FEC9827B5C6AF00F25F42 /* MTRDeviceOverXPC.mm in Sources */, 51431AF927D2973E008A7943 /* MTRIMDispatch.mm in Sources */, + 1E4D655229C30A8700BC3478 /* MTRCommissionableBrowser.mm in Sources */, 51431AFB27D29CA4008A7943 /* ota-provider.cpp in Sources */, 3DECCB722934AFE200585AEC /* MTRLogging.mm in Sources */, 7596A84528762729004DAE0E /* MTRDevice.mm in Sources */, diff --git a/src/lib/core/CHIPConfig.h b/src/lib/core/CHIPConfig.h index 24a88cb64df273..c6c6726ff5fcc8 100644 --- a/src/lib/core/CHIPConfig.h +++ b/src/lib/core/CHIPConfig.h @@ -1387,6 +1387,13 @@ extern const char CHIP_NON_PRODUCTION_MARKER[]; #define CHIP_CONFIG_SCENES_MAX_PER_FABRIC (CHIP_CONFIG_MAX_SCENES_PER_ENDPOINT / 2) #endif +/** + * @brief The maximum number of attribute value pairs in an extension field set. + */ +#ifndef CHIP_CONFIG_SCENES_MAX_AV_PAIRS_EFS +#define CHIP_CONFIG_SCENES_MAX_AV_PAIRS_EFS 15 +#endif + /** * @brief The maximum number of clusters per scene, defaults to 3 for a typical usecase (onOff + level control + color control * cluster). Needs to be changed in case a greater number of clusters is chosen. diff --git a/src/lib/dnssd/Advertiser_ImplMinimalMdns.cpp b/src/lib/dnssd/Advertiser_ImplMinimalMdns.cpp index 33f037587858b5..c3817ce4c3811a 100644 --- a/src/lib/dnssd/Advertiser_ImplMinimalMdns.cpp +++ b/src/lib/dnssd/Advertiser_ImplMinimalMdns.cpp @@ -906,7 +906,7 @@ void AdvertiserMinMdns::AdvertiseRecords(BroadcastAdvertiseType type) // This optimization likely will take more logic and state storage, so // for now it is not done. QueryData queryData(QType::PTR, QClass::IN, false /* unicast */); - queryData.SetIsInternalBroadcast(true); + queryData.SetIsAnnounceBroadcast(true); for (auto & it : mOperationalResponders) { @@ -916,6 +916,7 @@ void AdvertiserMinMdns::AdvertiseRecords(BroadcastAdvertiseType type) mQueryResponderAllocatorCommissioner.GetQueryResponder()->ClearBroadcastThrottle(); CHIP_ERROR err = mResponseSender.Respond(0, queryData, &packetInfo, responseConfiguration); + if (err != CHIP_NO_ERROR) { ChipLogError(Discovery, "Failed to advertise records: %" CHIP_ERROR_FORMAT, err.Format()); diff --git a/src/lib/dnssd/minimal_mdns/Parser.h b/src/lib/dnssd/minimal_mdns/Parser.h index 509633b9e192fa..879c6858a2912f 100644 --- a/src/lib/dnssd/minimal_mdns/Parser.h +++ b/src/lib/dnssd/minimal_mdns/Parser.h @@ -46,8 +46,8 @@ class QueryData /// any broadcast filtering. Intent is for paths such as: /// - boot time advertisement: advertise all services available /// - stop-time advertisement: advertise a TTL of 0 as services are removed - bool IsInternalBroadcast() const { return mIsInternalBroadcast; } - void SetIsInternalBroadcast(bool isInternalBroadcast) { mIsInternalBroadcast = isInternalBroadcast; } + bool IsAnnounceBroadcast() const { return mIsAnnounceBroadcast; } + void SetIsAnnounceBroadcast(bool isAnnounceBroadcast) { mIsAnnounceBroadcast = isAnnounceBroadcast; } SerializedQNameIterator GetName() const { return mNameIterator; } @@ -69,7 +69,7 @@ class QueryData /// Flag as an internal broadcast, controls reply construction (e.g. no /// filtering applied) - bool mIsInternalBroadcast = false; + bool mIsAnnounceBroadcast = false; }; class ResourceData diff --git a/src/lib/dnssd/minimal_mdns/QueryReplyFilter.h b/src/lib/dnssd/minimal_mdns/QueryReplyFilter.h index c7eb0a98af0151..a9cf13842d3527 100644 --- a/src/lib/dnssd/minimal_mdns/QueryReplyFilter.h +++ b/src/lib/dnssd/minimal_mdns/QueryReplyFilter.h @@ -81,7 +81,7 @@ class QueryReplyFilter : public ReplyFilter bool AcceptablePath(FullQName qname) { - if (mIgnoreNameMatch || mQueryData.IsInternalBroadcast()) + if (mIgnoreNameMatch || mQueryData.IsAnnounceBroadcast()) { return true; } diff --git a/src/lib/dnssd/minimal_mdns/ResponseSender.cpp b/src/lib/dnssd/minimal_mdns/ResponseSender.cpp index 722ca973902fb3..7aec6142f0b555 100644 --- a/src/lib/dnssd/minimal_mdns/ResponseSender.cpp +++ b/src/lib/dnssd/minimal_mdns/ResponseSender.cpp @@ -26,6 +26,8 @@ namespace Minimal { namespace { +using namespace mdns::Minimal::Internal; + constexpr uint16_t kMdnsStandardPort = 5353; // Restriction for UDP packets: https://tools.ietf.org/html/rfc1035#section-4.2.1 @@ -105,6 +107,12 @@ CHIP_ERROR ResponseSender::Respond(uint16_t messageId, const QueryData & query, { mSendState.Reset(messageId, query, querySource); + if (query.IsAnnounceBroadcast()) + { + // Deny listing large amount of data + mSendState.MarkWasSent(ResponseItemsSent::kServiceListingData); + } + // Responder has a stateful 'additional replies required' that is used within the response // loop. 'no additionals required' is set at the start and additionals are marked as the query // reply is built. @@ -158,7 +166,12 @@ CHIP_ERROR ResponseSender::Respond(uint16_t messageId, const QueryData & query, // send all 'Additional' replies { - mSendState.SetResourceType(ResourceType::kAdditional); + if (!query.IsAnnounceBroadcast()) + { + // Initial service broadcast should keep adding data as 'Answers' rather + // than addtional data (https://datatracker.ietf.org/doc/html/rfc6762#section-8.3) + mSendState.SetResourceType(ResourceType::kAdditional); + } QueryReplyFilter queryReplyFilter(query); @@ -232,6 +245,45 @@ CHIP_ERROR ResponseSender::PrepareNewReplyPacket() return CHIP_NO_ERROR; } +bool ResponseSender::ShouldSend(const Responder & responder) const +{ + switch (responder.GetQType()) + { + case QType::A: + return !mSendState.GetWasSent(ResponseItemsSent::kIPv4Addresses); + case QType::AAAA: + return !mSendState.GetWasSent(ResponseItemsSent::kIPv6Addresses); + case QType::PTR: { + static const QNamePart kDnsSdQueryPath[] = { "_services", "_dns-sd", "_udp", "local" }; + + if (responder.GetQName() == FullQName(kDnsSdQueryPath)) + { + return !mSendState.GetWasSent(ResponseItemsSent::kServiceListingData); + } + break; + } + default: + break; + } + + return true; +} + +void ResponseSender::ResponsesAdded(const Responder & responder) +{ + switch (responder.GetQType()) + { + case QType::A: + mSendState.MarkWasSent(ResponseItemsSent::kIPv4Addresses); + break; + case QType::AAAA: + mSendState.MarkWasSent(ResponseItemsSent::kIPv6Addresses); + break; + default: + break; + } +} + void ResponseSender::AddResponse(const ResourceRecord & record) { ReturnOnFailure(mSendState.GetError()); diff --git a/src/lib/dnssd/minimal_mdns/ResponseSender.h b/src/lib/dnssd/minimal_mdns/ResponseSender.h index 636acaaf7acf14..487b3b5b104f81 100644 --- a/src/lib/dnssd/minimal_mdns/ResponseSender.h +++ b/src/lib/dnssd/minimal_mdns/ResponseSender.h @@ -47,6 +47,24 @@ namespace Minimal { namespace Internal { +// Flags for keeping track of items having been sent as DNSSD responses +// +// We rely on knowing Matter DNSSD only sends the same set of data +// for some instances like A/AAAA always being the same. +// +enum class ResponseItemsSent : uint8_t +{ + // DNSSD may have different servers referenced by IP addresses, + // however we know the matter dnssd server name is fixed and + // the same even across SRV records. + kIPv4Addresses = 0x01, + kIPv6Addresses = 0x02, + + // Boot time advertisement filters. We allow multiple of these + // however we also allow filtering them out at response start + kServiceListingData = 0x04, +}; + /// Represents the internal state for sending a currently active request class ResponseSendingState { @@ -60,6 +78,7 @@ class ResponseSendingState mSource = packet; mSendError = CHIP_NO_ERROR; mResourceType = ResourceType::kAnswer; + mSentItems.ClearAll(); } void SetResourceType(ResourceType resourceType) { mResourceType = resourceType; } @@ -88,12 +107,16 @@ class ResponseSendingState const chip::Inet::IPAddress & GetSourceAddress() const { return mSource->SrcAddress; } chip::Inet::InterfaceId GetSourceInterfaceId() const { return mSource->Interface; } + bool GetWasSent(ResponseItemsSent item) const { return mSentItems.Has(item); } + void MarkWasSent(ResponseItemsSent item) { mSentItems.Set(item); } + private: const QueryData * mQuery = nullptr; // query being replied to const chip::Inet::IPPacketInfo * mSource = nullptr; // Where to send the reply (if unicast) uint16_t mMessageId = 0; // message id for the reply ResourceType mResourceType = ResourceType::kAnswer; // what is being sent right now CHIP_ERROR mSendError = CHIP_NO_ERROR; + chip::BitFlags mSentItems; }; } // namespace Internal @@ -117,6 +140,8 @@ class ResponseSender : public ResponderDelegate // Implementation of ResponderDelegate void AddResponse(const ResourceRecord & record) override; + bool ShouldSend(const Responder &) const override; + void ResponsesAdded(const Responder &) override; void SetServer(ServerBase * server) { mServer = server; } diff --git a/src/lib/dnssd/minimal_mdns/responders/IP.cpp b/src/lib/dnssd/minimal_mdns/responders/IP.cpp index 8290db94e0aa40..80e57e15223737 100644 --- a/src/lib/dnssd/minimal_mdns/responders/IP.cpp +++ b/src/lib/dnssd/minimal_mdns/responders/IP.cpp @@ -30,6 +30,11 @@ void IPv4Responder::AddAllResponses(const chip::Inet::IPPacketInfo * source, Res const ResponseConfiguration & configuration) { #if INET_CONFIG_ENABLE_IPV4 + if (!delegate->ShouldSend(*this)) + { + return; + } + chip::Inet::IPAddress addr; UniquePtr ips = GetAddressPolicy()->GetIpAddressesForEndpoint(source->Interface, chip::Inet::IPAddressType::kIPv4); @@ -46,12 +51,18 @@ void IPv4Responder::AddAllResponses(const chip::Inet::IPPacketInfo * source, Res configuration.Adjust(record); delegate->AddResponse(record); } + delegate->ResponsesAdded(*this); #endif } void IPv6Responder::AddAllResponses(const chip::Inet::IPPacketInfo * source, ResponderDelegate * delegate, const ResponseConfiguration & configuration) { + if (!delegate->ShouldSend(*this)) + { + return; + } + chip::Inet::IPAddress addr; UniquePtr ips = GetAddressPolicy()->GetIpAddressesForEndpoint(source->Interface, chip::Inet::IPAddressType::kIPv6); @@ -68,6 +79,7 @@ void IPv6Responder::AddAllResponses(const chip::Inet::IPPacketInfo * source, Res configuration.Adjust(record); delegate->AddResponse(record); } + delegate->ResponsesAdded(*this); } } // namespace Minimal diff --git a/src/lib/dnssd/minimal_mdns/responders/Ptr.h b/src/lib/dnssd/minimal_mdns/responders/Ptr.h index 1fd50a0b5e142c..80e91e2349b16e 100644 --- a/src/lib/dnssd/minimal_mdns/responders/Ptr.h +++ b/src/lib/dnssd/minimal_mdns/responders/Ptr.h @@ -31,9 +31,15 @@ class PtrResponder : public RecordResponder void AddAllResponses(const chip::Inet::IPPacketInfo * source, ResponderDelegate * delegate, const ResponseConfiguration & configuration) override { + if (!delegate->ShouldSend(*this)) + { + return; + } + PtrResourceRecord record(GetQName(), mTarget); configuration.Adjust(record); delegate->AddResponse(record); + delegate->ResponsesAdded(*this); } private: diff --git a/src/lib/dnssd/minimal_mdns/responders/QueryResponder.cpp b/src/lib/dnssd/minimal_mdns/responders/QueryResponder.cpp index 47731c7a42ddfd..eb0ed5ac065118 100644 --- a/src/lib/dnssd/minimal_mdns/responders/QueryResponder.cpp +++ b/src/lib/dnssd/minimal_mdns/responders/QueryResponder.cpp @@ -142,6 +142,11 @@ void QueryResponderBase::MarkAdditionalRepliesFor(QueryResponderIterator it) void QueryResponderBase::AddAllResponses(const chip::Inet::IPPacketInfo * source, ResponderDelegate * delegate, const ResponseConfiguration & configuration) { + if (!delegate->ShouldSend(*this)) + { + return; + } + // reply to dns-sd service list request for (size_t i = 0; i < mResponderInfoSize; i++) { @@ -159,6 +164,8 @@ void QueryResponderBase::AddAllResponses(const chip::Inet::IPPacketInfo * source configuration.Adjust(record); delegate->AddResponse(record); } + + delegate->ResponsesAdded(*this); } void QueryResponderBase::ClearBroadcastThrottle() diff --git a/src/lib/dnssd/minimal_mdns/responders/Responder.h b/src/lib/dnssd/minimal_mdns/responders/Responder.h index 4a1b4e015dbe59..534b661df64535 100644 --- a/src/lib/dnssd/minimal_mdns/responders/Responder.h +++ b/src/lib/dnssd/minimal_mdns/responders/Responder.h @@ -26,15 +26,6 @@ namespace mdns { namespace Minimal { -class ResponderDelegate -{ -public: - virtual ~ResponderDelegate() {} - - /// Add the specified resource record to the response - virtual void AddResponse(const ResourceRecord & record) = 0; -}; - /// Controls specific options for responding to mDNS queries /// class ResponseConfiguration @@ -67,6 +58,9 @@ class ResponseConfiguration chip::Optional mTtlSecondsOverride; }; +// Delegates that responders can write themselves to +class ResponderDelegate; + /// Adds ability to respond with specific types of data class Responder { @@ -81,7 +75,7 @@ class Responder /// Domain name is generally just 'local' FullQName GetQName() const { return mQName; } - /// Report all reponses maintained by this responder + /// Report all responses maintained by this responder /// /// Responses are associated with the objects type/class/qname. virtual void AddAllResponses(const chip::Inet::IPPacketInfo * source, ResponderDelegate * delegate, @@ -92,5 +86,24 @@ class Responder const FullQName mQName; }; +class ResponderDelegate +{ +public: + virtual ~ResponderDelegate() {} + + /// Add the specified resource record to the response + virtual void AddResponse(const ResourceRecord & record) = 0; + + /// Accept to add responses for the particular responder. + /// + /// This will be called before responders serialize their records. + virtual bool ShouldSend(const Responder &) const { return true; } + + /// Called when all responses were added for a particular responder + /// + /// Only called if a previous accept returned true. + virtual void ResponsesAdded(const Responder &) {} +}; + } // namespace Minimal } // namespace mdns diff --git a/src/lib/dnssd/minimal_mdns/responders/Srv.h b/src/lib/dnssd/minimal_mdns/responders/Srv.h index d23226092b3e09..868bf878302aaf 100644 --- a/src/lib/dnssd/minimal_mdns/responders/Srv.h +++ b/src/lib/dnssd/minimal_mdns/responders/Srv.h @@ -31,9 +31,15 @@ class SrvResponder : public RecordResponder void AddAllResponses(const chip::Inet::IPPacketInfo * source, ResponderDelegate * delegate, const ResponseConfiguration & configuration) override { + if (!delegate->ShouldSend(*this)) + { + return; + } + SrvResourceRecord record = mRecord; configuration.Adjust(record); delegate->AddResponse(record); + delegate->ResponsesAdded(*this); } private: diff --git a/src/lib/dnssd/minimal_mdns/responders/Txt.h b/src/lib/dnssd/minimal_mdns/responders/Txt.h index 5b607265b8c55c..b2a920ab96c0fd 100644 --- a/src/lib/dnssd/minimal_mdns/responders/Txt.h +++ b/src/lib/dnssd/minimal_mdns/responders/Txt.h @@ -31,9 +31,15 @@ class TxtResponder : public RecordResponder void AddAllResponses(const chip::Inet::IPPacketInfo * source, ResponderDelegate * delegate, const ResponseConfiguration & configuration) override { + if (!delegate->ShouldSend(*this)) + { + return; + } + TxtResourceRecord record = mRecord; configuration.Adjust(record); delegate->AddResponse(record); + delegate->ResponsesAdded(*this); } private: diff --git a/src/lib/dnssd/platform/Dnssd.h b/src/lib/dnssd/platform/Dnssd.h index d2d834d00f7034..778e9bc05f1d9c 100644 --- a/src/lib/dnssd/platform/Dnssd.h +++ b/src/lib/dnssd/platform/Dnssd.h @@ -304,7 +304,7 @@ void ChipDnssdResolveNoLongerNeeded(const char * instanceName); * * @param[in] hostname The hostname the address belongs to. * @param[in] address The address to reconfirm. - * @param[in] interfaceId The interfaceId of the address. + * @param[in] interface The interfaceId of the address. * */ CHIP_ERROR ChipDnssdReconfirmRecord(const char * hostname, chip::Inet::IPAddress address, chip::Inet::InterfaceId interface); diff --git a/src/platform/ESP32/CHIPDevicePlatformConfig.h b/src/platform/ESP32/CHIPDevicePlatformConfig.h index 5bee6b221919c2..96b910785cf620 100644 --- a/src/platform/ESP32/CHIPDevicePlatformConfig.h +++ b/src/platform/ESP32/CHIPDevicePlatformConfig.h @@ -72,6 +72,8 @@ #define CHIP_DEVICE_CONFIG_ENABLE_WIFI CHIP_DEVICE_CONFIG_ENABLE_WIFI_AP | CHIP_DEVICE_CONFIG_ENABLE_WIFI_STATION #endif // CONFIG_IDF_TARGET_ESP32H2 +#define CHIP_DEVICE_CONFIG_ENABLE_SED CONFIG_WIFI_POWER_SAVE_MIN || CONFIG_WIFI_POWER_SAVE_MAX + #define CHIP_DEVICE_CONFIG_ENABLE_CHIPOBLE CONFIG_ENABLE_CHIPOBLE #define CHIP_DEVICE_CONFIG_ENABLE_EXTENDED_DISCOVERY CONFIG_ENABLE_EXTENDED_DISCOVERY #define CHIP_DEVICE_CONFIG_ENABLE_COMMISSIONABLE_DEVICE_TYPE CONFIG_ENABLE_COMMISSIONABLE_DEVICE_TYPE diff --git a/src/platform/ESP32/ConnectivityManagerImpl.h b/src/platform/ESP32/ConnectivityManagerImpl.h index 35658206b76c02..bc12092c506391 100644 --- a/src/platform/ESP32/ConnectivityManagerImpl.h +++ b/src/platform/ESP32/ConnectivityManagerImpl.h @@ -119,6 +119,11 @@ class ConnectivityManagerImpl final : public ConnectivityManager, void _OnWiFiScanDone(); void _OnWiFiStationProvisionChange(); +#if CHIP_DEVICE_CONFIG_ENABLE_SED + CHIP_ERROR _GetSEDIntervalsConfig(ConnectivityManager::SEDIntervalsConfig & intervalsConfig); + CHIP_ERROR _SetSEDIntervalsConfig(const ConnectivityManager::SEDIntervalsConfig & intervalsConfig); + CHIP_ERROR _RequestSEDActiveMode(bool onOff, bool delayIdle = false); +#endif // ===== Private members reserved for use by this class only. System::Clock::Timestamp mLastStationConnectFailTime; diff --git a/src/platform/ESP32/ConnectivityManagerImpl_WiFi.cpp b/src/platform/ESP32/ConnectivityManagerImpl_WiFi.cpp index 98d87bff717be8..e79ba6e5830aaf 100644 --- a/src/platform/ESP32/ConnectivityManagerImpl_WiFi.cpp +++ b/src/platform/ESP32/ConnectivityManagerImpl_WiFi.cpp @@ -423,7 +423,10 @@ CHIP_ERROR ConnectivityManagerImpl::InitWiFi() std::min(sizeof(wifiConfig.sta.password), strlen(CONFIG_DEFAULT_WIFI_PASSWORD))); wifiConfig.sta.scan_method = WIFI_ALL_CHANNEL_SCAN; wifiConfig.sta.sort_method = WIFI_CONNECT_AP_BY_SIGNAL; - esp_err_t err = esp_wifi_set_config(WIFI_IF_STA, &wifiConfig); +#if CONFIG_WIFI_POWER_SAVE_MAX + wifiConfig.sta.listen_interval = CONFIG_WIFI_PS_LISTEN_INTERVAL; +#endif + esp_err_t err = esp_wifi_set_config(WIFI_IF_STA, &wifiConfig); if (err != ESP_OK) { ChipLogError(DeviceLayer, "esp_wifi_set_config() failed: %s", esp_err_to_name(err)); @@ -1109,6 +1112,33 @@ void ConnectivityManagerImpl::OnStationIPv6AddressAvailable(const ip_event_got_i #endif } +#if CHIP_DEVICE_CONFIG_ENABLE_SED +static constexpr uint32_t kBeaconIntervalMs = 100; +static constexpr uint32_t kDefaultDTIMInterval = 3; // this is determined by the AP, use a constant value for it. + +CHIP_ERROR ConnectivityManagerImpl::_GetSEDIntervalsConfig(ConnectivityManager::SEDIntervalsConfig & sedIntervalsConfig) +{ + sedIntervalsConfig.ActiveIntervalMS = chip::System::Clock::Milliseconds32(kBeaconIntervalMs); +#if CONFIG_WIFI_POWER_SAVE_MIN + sedIntervalsConfig.IdleIntervalMS = chip::System::Clock::Milliseconds32(kDefaultDTIMInterval * kBeaconIntervalMs); +#elif CONFIG_WIFI_POWER_SAVE_MAX + sedIntervalsConfig.IdleIntervalMS = chip::System::Clock::Milliseconds32(CONFIG_WIFI_PS_LISTEN_INTERVAL * kBeaconIntervalMs); +#endif + return CHIP_NO_ERROR; +} + +CHIP_ERROR ConnectivityManagerImpl::_SetSEDIntervalsConfig(const ConnectivityManager::SEDIntervalsConfig & intervalsConfig) +{ + return CHIP_ERROR_UNSUPPORTED_CHIP_FEATURE; +} + +CHIP_ERROR ConnectivityManagerImpl::_RequestSEDActiveMode(bool onOff, bool delayIdle) +{ + return CHIP_ERROR_UNSUPPORTED_CHIP_FEATURE; +} + +#endif // CHIP_DEVICE_CONFIG_ENABLE_SED + } // namespace DeviceLayer } // namespace chip diff --git a/src/platform/ESP32/ESP32Utils.cpp b/src/platform/ESP32/ESP32Utils.cpp index 4a03d08282dcda..c5000929ab08dd 100644 --- a/src/platform/ESP32/ESP32Utils.cpp +++ b/src/platform/ESP32/ESP32Utils.cpp @@ -117,6 +117,13 @@ CHIP_ERROR ESP32Utils::StartWiFiLayer(void) ChipLogError(DeviceLayer, "esp_wifi_start() failed: %s", esp_err_to_name(err)); return ESP32Utils::MapError(err); } +#if CONFIC_WIFI_POWER_SAVE_MIN + esp_wifi_set_ps(WIFI_PS_MIN_MODEM); +#elif CONFIC_WIFI_POWER_SAVE_MAX + esp_wifi_set_ps(WIFI_PS_MAX_MODEM); +#elif CONFIG_WIFI_POWER_SAVE_NONE + esp_wifi_set_ps(WIFI_PS_NONE); +#endif } return CHIP_NO_ERROR; diff --git a/src/platform/ESP32/NetworkCommissioningDriver.cpp b/src/platform/ESP32/NetworkCommissioningDriver.cpp index 7e080f5246256e..a99f20a57a0885 100644 --- a/src/platform/ESP32/NetworkCommissioningDriver.cpp +++ b/src/platform/ESP32/NetworkCommissioningDriver.cpp @@ -189,6 +189,9 @@ CHIP_ERROR ESPWiFiDriver::ConnectWiFiNetwork(const char * ssid, uint8_t ssidLen, memset(&wifiConfig, 0, sizeof(wifiConfig)); memcpy(wifiConfig.sta.ssid, ssid, std::min(ssidLen, static_cast(sizeof(wifiConfig.sta.ssid)))); memcpy(wifiConfig.sta.password, key, std::min(keyLen, static_cast(sizeof(wifiConfig.sta.password)))); +#if CONFIG_WIFI_POWER_SAVE_MAX + wifiConfig.sta..listen_interval = CONFIG_WIFI_PS_LISTEN_INTERVAL; +#endif // Configure the ESP WiFi interface. esp_err_t err = esp_wifi_set_config(WIFI_IF_STA, &wifiConfig); diff --git a/src/platform/OpenThread/GenericNetworkCommissioningThreadDriver.h b/src/platform/OpenThread/GenericNetworkCommissioningThreadDriver.h index 8a445e8d6c08e8..4a87d07e2fb084 100644 --- a/src/platform/OpenThread/GenericNetworkCommissioningThreadDriver.h +++ b/src/platform/OpenThread/GenericNetworkCommissioningThreadDriver.h @@ -81,6 +81,12 @@ class GenericThreadDriver final : public ThreadDriver bool exhausted = false; }; + GenericThreadDriver(uint8_t scanTimeoutSec = 10, uint8_t connectTimeoutSec = 20) + { + scanNetworkTimeoutSeconds = scanTimeoutSec; + connectNetworkTimeout = connectTimeoutSec; + } + // BaseDriver NetworkIterator * GetNetworks() override { return new ThreadNetworkIterator(this); } CHIP_ERROR Init(Internal::BaseDriver::NetworkStatusChangeCallback * statusChangeCallback) override; @@ -88,8 +94,11 @@ class GenericThreadDriver final : public ThreadDriver // WirelessDriver uint8_t GetMaxNetworks() override { return 1; } - uint8_t GetScanNetworkTimeoutSeconds() override { return 10; } - uint8_t GetConnectNetworkTimeoutSeconds() override { return 20; } + uint8_t GetScanNetworkTimeoutSeconds() override { return scanNetworkTimeoutSeconds; } + uint8_t GetConnectNetworkTimeoutSeconds() override { return connectNetworkTimeout; } + + void SetScanNetworkTimeoutSeconds(uint8_t scanTimeoutSec) { scanNetworkTimeoutSeconds = scanTimeoutSec; } + void SetConnectNetworkTimeoutSeconds(uint8_t connectTimeoutSec) { connectNetworkTimeout = connectTimeoutSec; } CHIP_ERROR CommitConfiguration() override; CHIP_ERROR RevertConfiguration() override; @@ -103,6 +112,8 @@ class GenericThreadDriver final : public ThreadDriver void ScanNetworks(ThreadDriver::ScanCallback * callback) override; private: + uint8_t scanNetworkTimeoutSeconds; + uint8_t connectNetworkTimeout; Status MatchesNetworkId(const Thread::OperationalDataset & dataset, const ByteSpan & networkId) const; CHIP_ERROR BackupConfiguration(); diff --git a/src/platform/nxp/crypto/nxp_crypto.gni b/src/platform/nxp/crypto/nxp_crypto.gni new file mode 100644 index 00000000000000..dcc4dcae7c8f8f --- /dev/null +++ b/src/platform/nxp/crypto/nxp_crypto.gni @@ -0,0 +1,21 @@ +# Copyright (c) 2022 Project CHIP Authors +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +declare_args() { + nxp_crypto_impl = "" + nxp_crypto_mw_root = "" +} + +assert(nxp_crypto_impl != "", "nxp_crypto_impl should be defined") +assert(nxp_crypto_mw_root != "", "nxp_crypto_mw_root should be defined") diff --git a/src/platform/nxp/crypto/se05x/BUILD.gn b/src/platform/nxp/crypto/se05x/BUILD.gn new file mode 100644 index 00000000000000..dc41efa0977635 --- /dev/null +++ b/src/platform/nxp/crypto/se05x/BUILD.gn @@ -0,0 +1,65 @@ +# Copyright (c) 2020 Project CHIP Authors +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +import("//build_overrides/chip.gni") +import("//build_overrides/nlassert.gni") +import("${chip_root}/build/chip/buildconfig_header.gni") +import("${chip_root}/src/crypto/crypto.gni") +import("${chip_root}/src/platform/nxp/crypto/se05x/args.gni") + +if (chip_crypto == "platform") { + import("//build_overrides/mbedtls.gni") +} + +source_set("public_headers") { + sources = [ + "CHIPCryptoPAL.h", + "OperationalKeystore.h", + ] + + public_deps = [ + "${chip_root}/src/lib/asn1", + "${chip_root}/src/lib/core", + "${chip_root}/src/lib/support", + "${nlassert_root}:nlassert", + ] +} + +static_library("nxp_crypto_lib") { + sources = [ + "${chip_root}/src/platform/nxp/crypto/se05x/CHIPCryptoPALHost.cpp", + "${chip_root}/src/platform/nxp/crypto/se05x/CHIPCryptoPALHsm_se05x_hkdf.cpp", + "${chip_root}/src/platform/nxp/crypto/se05x/CHIPCryptoPALHsm_se05x_hmac.cpp", + "${chip_root}/src/platform/nxp/crypto/se05x/CHIPCryptoPALHsm_se05x_p256.cpp", + "${chip_root}/src/platform/nxp/crypto/se05x/CHIPCryptoPALHsm_se05x_pbkdf.cpp", + "${chip_root}/src/platform/nxp/crypto/se05x/CHIPCryptoPALHsm_se05x_rng.cpp", + "${chip_root}/src/platform/nxp/crypto/se05x/CHIPCryptoPALHsm_se05x_utils.cpp", + "${chip_root}/src/platform/nxp/crypto/se05x/CHIPCryptoPAL_HostFallBack.cpp", + ] + + public_deps = [ ":public_headers" ] + deps = [ "${chip_root}/${nxp_crypto_mw_root}:se05x" ] + + external_mbedtls = current_os == "zephyr" + + if (!external_mbedtls) { + public_deps += [ "${mbedtls_root}:mbedtls" ] + } + + include_dirs = [ + ".", + "${chip_root}/src/crypto", + "${chip_root}/src/platform/nxp/crypto/se05x", + ] +} diff --git a/src/platform/nxp/crypto/se05x/CHIPCryptoPALHost.cpp b/src/platform/nxp/crypto/se05x/CHIPCryptoPALHost.cpp new file mode 100644 index 00000000000000..525d3e32ba654f --- /dev/null +++ b/src/platform/nxp/crypto/se05x/CHIPCryptoPALHost.cpp @@ -0,0 +1,1351 @@ +/* + * + * Copyright (c) 2020-2022 Project CHIP Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/** + * @file + * mbedTLS based implementation of CHIP crypto primitives + */ + +#include "CHIPCryptoPAL.h" + +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#if defined(MBEDTLS_X509_CRT_PARSE_C) +#include +#endif // defined(MBEDTLS_X509_CRT_PARSE_C) +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +namespace chip { +namespace Crypto { + +#define MAX_ERROR_STR_LEN 128 +#define NUM_BYTES_IN_SHA256_HASH 32 + +// In mbedTLS 3.0.0 direct access to structure fields was replaced with using MBEDTLS_PRIVATE macro. +#if (MBEDTLS_VERSION_NUMBER >= 0x03000000) +#define CHIP_CRYPTO_PAL_PRIVATE(x) MBEDTLS_PRIVATE(x) +#else +#define CHIP_CRYPTO_PAL_PRIVATE(x) x +#endif + +#if (MBEDTLS_VERSION_NUMBER >= 0x03000000 && MBEDTLS_VERSION_NUMBER < 0x03010000) +#define CHIP_CRYPTO_PAL_PRIVATE_X509(x) MBEDTLS_PRIVATE(x) +#else +#define CHIP_CRYPTO_PAL_PRIVATE_X509(x) x +#endif + +typedef struct +{ + bool mInitialized; + bool mDRBGSeeded; + mbedtls_ctr_drbg_context mDRBGCtxt; + mbedtls_entropy_context mEntropy; +} EntropyContext; + +static EntropyContext gsEntropyContext; + +static void _log_mbedTLS_error(int error_code) +{ + if (error_code != 0) + { +#if defined(MBEDTLS_ERROR_C) + char error_str[MAX_ERROR_STR_LEN]; + mbedtls_strerror(error_code, error_str, sizeof(error_str)); + ChipLogError(Crypto, "mbedTLS error: %s", error_str); +#else + // Error codes defined in 16-bit negative hex numbers. Ease lookup by printing likewise + ChipLogError(Crypto, "mbedTLS error: -0x%04X", -static_cast(error_code)); +#endif + } +} + +static bool _isValidTagLength(size_t tag_length) +{ + if (tag_length == 8 || tag_length == 12 || tag_length == 16) + { + return true; + } + return false; +} + +CHIP_ERROR AES_CCM_encrypt(const uint8_t * plaintext, size_t plaintext_length, const uint8_t * aad, size_t aad_length, + const Aes128KeyHandle & key, const uint8_t * nonce, size_t nonce_length, uint8_t * ciphertext, + uint8_t * tag, size_t tag_length) +{ + CHIP_ERROR error = CHIP_NO_ERROR; + int result = 1; + + mbedtls_ccm_context context; + mbedtls_ccm_init(&context); + + VerifyOrExit(plaintext != nullptr || plaintext_length == 0, error = CHIP_ERROR_INVALID_ARGUMENT); + VerifyOrExit(ciphertext != nullptr || plaintext_length == 0, error = CHIP_ERROR_INVALID_ARGUMENT); + VerifyOrExit(nonce != nullptr, error = CHIP_ERROR_INVALID_ARGUMENT); + VerifyOrExit(nonce_length > 0, error = CHIP_ERROR_INVALID_ARGUMENT); + VerifyOrExit(tag != nullptr, error = CHIP_ERROR_INVALID_ARGUMENT); + VerifyOrExit(_isValidTagLength(tag_length), error = CHIP_ERROR_INVALID_ARGUMENT); + if (aad_length > 0) + { + VerifyOrExit(aad != nullptr, error = CHIP_ERROR_INVALID_ARGUMENT); + } + + // Size of key is expressed in bits, hence the multiplication by 8. + result = mbedtls_ccm_setkey(&context, MBEDTLS_CIPHER_ID_AES, key.As(), sizeof(Aes128KeyByteArray) * 8); + VerifyOrExit(result == 0, error = CHIP_ERROR_INTERNAL); + + // Encrypt + result = mbedtls_ccm_encrypt_and_tag(&context, plaintext_length, Uint8::to_const_uchar(nonce), nonce_length, + Uint8::to_const_uchar(aad), aad_length, Uint8::to_const_uchar(plaintext), + Uint8::to_uchar(ciphertext), Uint8::to_uchar(tag), tag_length); + _log_mbedTLS_error(result); + VerifyOrExit(result == 0, error = CHIP_ERROR_INTERNAL); + +exit: + mbedtls_ccm_free(&context); + return error; +} + +CHIP_ERROR AES_CCM_decrypt(const uint8_t * ciphertext, size_t ciphertext_len, const uint8_t * aad, size_t aad_len, + const uint8_t * tag, size_t tag_length, const Aes128KeyHandle & key, const uint8_t * nonce, + size_t nonce_length, uint8_t * plaintext) +{ + CHIP_ERROR error = CHIP_NO_ERROR; + int result = 1; + + mbedtls_ccm_context context; + mbedtls_ccm_init(&context); + + VerifyOrExit(plaintext != nullptr || ciphertext_len == 0, error = CHIP_ERROR_INVALID_ARGUMENT); + VerifyOrExit(ciphertext != nullptr || ciphertext_len == 0, error = CHIP_ERROR_INVALID_ARGUMENT); + VerifyOrExit(tag != nullptr, error = CHIP_ERROR_INVALID_ARGUMENT); + VerifyOrExit(_isValidTagLength(tag_length), error = CHIP_ERROR_INVALID_ARGUMENT); + VerifyOrExit(nonce != nullptr, error = CHIP_ERROR_INVALID_ARGUMENT); + VerifyOrExit(nonce_length > 0, error = CHIP_ERROR_INVALID_ARGUMENT); + if (aad_len > 0) + { + VerifyOrExit(aad != nullptr, error = CHIP_ERROR_INVALID_ARGUMENT); + } + + // Size of key is expressed in bits, hence the multiplication by 8. + result = mbedtls_ccm_setkey(&context, MBEDTLS_CIPHER_ID_AES, key.As(), sizeof(Aes128KeyByteArray) * 8); + VerifyOrExit(result == 0, error = CHIP_ERROR_INTERNAL); + + // Decrypt + result = mbedtls_ccm_auth_decrypt(&context, ciphertext_len, Uint8::to_const_uchar(nonce), nonce_length, + Uint8::to_const_uchar(aad), aad_len, Uint8::to_const_uchar(ciphertext), + Uint8::to_uchar(plaintext), Uint8::to_const_uchar(tag), tag_length); + _log_mbedTLS_error(result); + VerifyOrExit(result == 0, error = CHIP_ERROR_INTERNAL); + +exit: + mbedtls_ccm_free(&context); + return error; +} + +CHIP_ERROR Hash_SHA256(const uint8_t * data, const size_t data_length, uint8_t * out_buffer) +{ + // zero data length hash is supported. + VerifyOrReturnError(data != nullptr, CHIP_ERROR_INVALID_ARGUMENT); + VerifyOrReturnError(out_buffer != nullptr, CHIP_ERROR_INVALID_ARGUMENT); + +#if (MBEDTLS_VERSION_NUMBER >= 0x03000000) + const int result = mbedtls_sha256(Uint8::to_const_uchar(data), data_length, Uint8::to_uchar(out_buffer), 0); +#else + const int result = mbedtls_sha256_ret(Uint8::to_const_uchar(data), data_length, Uint8::to_uchar(out_buffer), 0); +#endif + + VerifyOrReturnError(result == 0, CHIP_ERROR_INTERNAL); + + return CHIP_NO_ERROR; +} + +CHIP_ERROR Hash_SHA1(const uint8_t * data, const size_t data_length, uint8_t * out_buffer) +{ + // zero data length hash is supported. + VerifyOrReturnError(out_buffer != nullptr, CHIP_ERROR_INVALID_ARGUMENT); + +#if (MBEDTLS_VERSION_NUMBER >= 0x03000000) + const int result = mbedtls_sha1(Uint8::to_const_uchar(data), data_length, Uint8::to_uchar(out_buffer)); +#else + const int result = mbedtls_sha1_ret(Uint8::to_const_uchar(data), data_length, Uint8::to_uchar(out_buffer)); +#endif + + VerifyOrReturnError(result == 0, CHIP_ERROR_INTERNAL); + + return CHIP_NO_ERROR; +} + +static_assert(kMAX_Hash_SHA256_Context_Size >= sizeof(mbedtls_sha256_context), + "kMAX_Hash_SHA256_Context_Size is too small for the size of underlying mbedtls_sha256_context"); + +static inline mbedtls_sha256_context * to_inner_hash_sha256_context(HashSHA256OpaqueContext * context) +{ + return SafePointerCast(context); +} + +Hash_SHA256_stream::Hash_SHA256_stream(void) +{ + mbedtls_sha256_context * context = to_inner_hash_sha256_context(&mContext); + mbedtls_sha256_init(context); +} + +Hash_SHA256_stream::~Hash_SHA256_stream(void) +{ + mbedtls_sha256_context * context = to_inner_hash_sha256_context(&mContext); + mbedtls_sha256_free(context); + Clear(); +} + +CHIP_ERROR Hash_SHA256_stream::Begin(void) +{ + mbedtls_sha256_context * const context = to_inner_hash_sha256_context(&mContext); + +#if (MBEDTLS_VERSION_NUMBER >= 0x03000000) + const int result = mbedtls_sha256_starts(context, 0); +#else + const int result = mbedtls_sha256_starts_ret(context, 0); +#endif + + VerifyOrReturnError(result == 0, CHIP_ERROR_INTERNAL); + + return CHIP_NO_ERROR; +} + +CHIP_ERROR Hash_SHA256_stream::AddData(const ByteSpan data) +{ + mbedtls_sha256_context * const context = to_inner_hash_sha256_context(&mContext); + +#if (MBEDTLS_VERSION_NUMBER >= 0x03000000) + const int result = mbedtls_sha256_update(context, Uint8::to_const_uchar(data.data()), data.size()); +#else + const int result = mbedtls_sha256_update_ret(context, Uint8::to_const_uchar(data.data()), data.size()); +#endif + + VerifyOrReturnError(result == 0, CHIP_ERROR_INTERNAL); + + return CHIP_NO_ERROR; +} + +CHIP_ERROR Hash_SHA256_stream::GetDigest(MutableByteSpan & out_buffer) +{ + mbedtls_sha256_context * context = to_inner_hash_sha256_context(&mContext); + + // Back-up context as we are about to finalize the hash to extract digest. + mbedtls_sha256_context previous_ctx; + mbedtls_sha256_init(&previous_ctx); + mbedtls_sha256_clone(&previous_ctx, context); + + // Pad + compute digest, then finalize context. It is restored next line to continue. + CHIP_ERROR result = Finish(out_buffer); + + // Restore context prior to finalization. + mbedtls_sha256_clone(context, &previous_ctx); + mbedtls_sha256_free(&previous_ctx); + + return result; +} + +CHIP_ERROR Hash_SHA256_stream::Finish(MutableByteSpan & out_buffer) +{ + VerifyOrReturnError(out_buffer.size() >= kSHA256_Hash_Length, CHIP_ERROR_BUFFER_TOO_SMALL); + mbedtls_sha256_context * const context = to_inner_hash_sha256_context(&mContext); + +#if (MBEDTLS_VERSION_NUMBER >= 0x03000000) + const int result = mbedtls_sha256_finish(context, Uint8::to_uchar(out_buffer.data())); +#else + const int result = mbedtls_sha256_finish_ret(context, Uint8::to_uchar(out_buffer.data())); +#endif + + VerifyOrReturnError(result == 0, CHIP_ERROR_INTERNAL); + out_buffer = out_buffer.SubSpan(0, kSHA256_Hash_Length); + + return CHIP_NO_ERROR; +} + +void Hash_SHA256_stream::Clear(void) +{ + mbedtls_platform_zeroize(this, sizeof(*this)); +} + +static EntropyContext * get_entropy_context() +{ + if (!gsEntropyContext.mInitialized) + { + mbedtls_entropy_init(&gsEntropyContext.mEntropy); + mbedtls_ctr_drbg_init(&gsEntropyContext.mDRBGCtxt); + + gsEntropyContext.mInitialized = true; + } + + return &gsEntropyContext; +} + +CHIP_ERROR add_entropy_source(entropy_source fn_source, void * p_source, size_t threshold) +{ + VerifyOrReturnError(fn_source != nullptr, CHIP_ERROR_INVALID_ARGUMENT); + + EntropyContext * const entropy_ctxt = get_entropy_context(); + VerifyOrReturnError(entropy_ctxt != nullptr, CHIP_ERROR_INTERNAL); + + const int result = + mbedtls_entropy_add_source(&entropy_ctxt->mEntropy, fn_source, p_source, threshold, MBEDTLS_ENTROPY_SOURCE_STRONG); + VerifyOrReturnError(result == 0, CHIP_ERROR_INTERNAL); + return CHIP_NO_ERROR; +} + +static int CryptoRNG(void * ctxt, uint8_t * out_buffer, size_t out_length) +{ + return (chip::Crypto::DRBG_get_bytes(out_buffer, out_length) == CHIP_NO_ERROR) ? 0 : 1; +} + +mbedtls_ecp_group_id MapECPGroupId(SupportedECPKeyTypes keyType) +{ + switch (keyType) + { + case SupportedECPKeyTypes::ECP256R1: + return MBEDTLS_ECP_DP_SECP256R1; + default: + return MBEDTLS_ECP_DP_NONE; + } +} + +static inline mbedtls_ecp_keypair * to_keypair(P256KeypairContext * context) +{ + return SafePointerCast(context); +} + +static inline const mbedtls_ecp_keypair * to_const_keypair(const P256KeypairContext * context) +{ + return SafePointerCast(context); +} + +// THE BELOW IS FROM `third_party/openthread/repo/third_party/mbedtls/repo/library/constant_time.c` since +// mbedtls_ct_memcmp is not available on Linux somehow :( +int mbedtls_ct_memcmp_copy(const void * a, const void * b, size_t n) +{ + size_t i; + volatile const unsigned char * A = (volatile const unsigned char *) a; + volatile const unsigned char * B = (volatile const unsigned char *) b; + volatile unsigned char diff = 0; + + for (i = 0; i < n; i++) + { + /* Read volatile data in order before computing diff. + * This avoids IAR compiler warning: + * 'the order of volatile accesses is undefined ..' */ + unsigned char x = A[i], y = B[i]; + diff |= x ^ y; + } + + return ((int) diff); +} + +bool IsBufferContentEqualConstantTime(const void * a, const void * b, size_t n) +{ + return mbedtls_ct_memcmp_copy(a, b, n) == 0; +} + +void P256Keypair::Clear() +{ + if (mInitialized) + { + mbedtls_ecp_keypair * keypair = to_keypair(&mKeypair); + mbedtls_ecp_keypair_free(keypair); + mInitialized = false; + } +} + +CHIP_ERROR VerifyCertificateSigningRequest(const uint8_t * csr_buf, size_t csr_length, P256PublicKey & pubkey) +{ +#if defined(MBEDTLS_X509_CSR_PARSE_C) + ReturnErrorOnFailure(VerifyCertificateSigningRequestFormat(csr_buf, csr_length)); + + // TODO: For some embedded targets, mbedTLS library doesn't have mbedtls_x509_csr_parse_der, and mbedtls_x509_csr_parse_free. + // Taking a step back, embedded targets likely will not process CSR requests. Adding this action item to reevaluate + // this if there's a need for this processing for embedded targets. + CHIP_ERROR error = CHIP_NO_ERROR; + size_t pubkey_size = 0; + + mbedtls_ecp_keypair * keypair = nullptr; + + P256ECDSASignature signature; + MutableByteSpan out_raw_sig_span(signature.Bytes(), signature.Capacity()); + + mbedtls_x509_csr csr; + mbedtls_x509_csr_init(&csr); + + int result = mbedtls_x509_csr_parse_der(&csr, csr_buf, csr_length); + VerifyOrExit(result == 0, error = CHIP_ERROR_INTERNAL); + + // Verify the signature algorithm and public key type + VerifyOrExit(csr.CHIP_CRYPTO_PAL_PRIVATE(sig_md) == MBEDTLS_MD_SHA256, error = CHIP_ERROR_UNSUPPORTED_SIGNATURE_TYPE); + VerifyOrExit(csr.CHIP_CRYPTO_PAL_PRIVATE(sig_pk) == MBEDTLS_PK_ECDSA, error = CHIP_ERROR_WRONG_KEY_TYPE); + + keypair = mbedtls_pk_ec(csr.CHIP_CRYPTO_PAL_PRIVATE_X509(pk)); + + // Copy the public key from the CSR + result = mbedtls_ecp_point_write_binary(&keypair->CHIP_CRYPTO_PAL_PRIVATE(grp), &keypair->CHIP_CRYPTO_PAL_PRIVATE(Q), + MBEDTLS_ECP_PF_UNCOMPRESSED, &pubkey_size, Uint8::to_uchar(pubkey), pubkey.Length()); + + VerifyOrExit(result == 0, error = CHIP_ERROR_INTERNAL); + VerifyOrExit(pubkey_size == pubkey.Length(), error = CHIP_ERROR_INTERNAL); + + // Convert DER signature to raw signature + error = EcdsaAsn1SignatureToRaw(kP256_FE_Length, + ByteSpan{ csr.CHIP_CRYPTO_PAL_PRIVATE(sig).CHIP_CRYPTO_PAL_PRIVATE_X509(p), + csr.CHIP_CRYPTO_PAL_PRIVATE(sig).CHIP_CRYPTO_PAL_PRIVATE_X509(len) }, + out_raw_sig_span); + + VerifyOrExit(error == CHIP_NO_ERROR, error = CHIP_ERROR_INVALID_ARGUMENT); + VerifyOrExit(out_raw_sig_span.size() == (kP256_FE_Length * 2), error = CHIP_ERROR_INTERNAL); + signature.SetLength(out_raw_sig_span.size()); + + // Verify the signature using the public key + error = pubkey.ECDSA_validate_msg_signature(csr.CHIP_CRYPTO_PAL_PRIVATE_X509(cri).CHIP_CRYPTO_PAL_PRIVATE_X509(p), + csr.CHIP_CRYPTO_PAL_PRIVATE_X509(cri).CHIP_CRYPTO_PAL_PRIVATE_X509(len), signature); + + SuccessOrExit(error); + +exit: + mbedtls_x509_csr_free(&csr); + _log_mbedTLS_error(result); + return error; +#else + ChipLogError(Crypto, "MBEDTLS_X509_CSR_PARSE_C is not enabled. CSR cannot be parsed"); + return CHIP_ERROR_UNSUPPORTED_CHIP_FEATURE; +#endif +} + +typedef struct Spake2p_Context +{ + mbedtls_ecp_group curve; + mbedtls_ecp_point M; + mbedtls_ecp_point N; + mbedtls_ecp_point X; + mbedtls_ecp_point Y; + mbedtls_ecp_point L; + mbedtls_ecp_point Z; + mbedtls_ecp_point V; + + mbedtls_mpi w0; + mbedtls_mpi w1; + mbedtls_mpi xy; + mbedtls_mpi tempbn; +} Spake2p_Context; + +static inline Spake2p_Context * to_inner_spake2p_context(Spake2pOpaqueContext * context) +{ + return SafePointerCast(context); +} + +CHIP_ERROR Spake2p_P256_SHA256_HKDF_HMAC::InitInternal(void) +{ + CHIP_ERROR error = CHIP_NO_ERROR; + int result = 0; + + Spake2p_Context * context = to_inner_spake2p_context(&mSpake2pContext); + + memset(context, 0, sizeof(Spake2p_Context)); + + mbedtls_ecp_group_init(&context->curve); + result = mbedtls_ecp_group_load(&context->curve, MBEDTLS_ECP_DP_SECP256R1); + VerifyOrExit(result == 0, error = CHIP_ERROR_INTERNAL); + + VerifyOrExit(mbedtls_md_info_from_type(MBEDTLS_MD_SHA256) != nullptr, error = CHIP_ERROR_INTERNAL); + + mbedtls_ecp_point_init(&context->M); + mbedtls_ecp_point_init(&context->N); + mbedtls_ecp_point_init(&context->X); + mbedtls_ecp_point_init(&context->Y); + mbedtls_ecp_point_init(&context->L); + mbedtls_ecp_point_init(&context->V); + mbedtls_ecp_point_init(&context->Z); + M = &context->M; + N = &context->N; + X = &context->X; + Y = &context->Y; + L = &context->L; + V = &context->V; + Z = &context->Z; + + mbedtls_mpi_init(&context->w0); + mbedtls_mpi_init(&context->w1); + mbedtls_mpi_init(&context->xy); + mbedtls_mpi_init(&context->tempbn); + w0 = &context->w0; + w1 = &context->w1; + xy = &context->xy; + tempbn = &context->tempbn; + + G = &context->curve.G; + order = &context->curve.N; + + return error; + +exit: + _log_mbedTLS_error(result); + Clear(); + return error; +} + +void Spake2p_P256_SHA256_HKDF_HMAC::Clear() +{ + VerifyOrReturn(state != CHIP_SPAKE2P_STATE::PREINIT); + + Spake2p_Context * context = to_inner_spake2p_context(&mSpake2pContext); + mbedtls_ecp_point_free(&context->M); + mbedtls_ecp_point_free(&context->N); + mbedtls_ecp_point_free(&context->X); + mbedtls_ecp_point_free(&context->Y); + mbedtls_ecp_point_free(&context->L); + mbedtls_ecp_point_free(&context->Z); + mbedtls_ecp_point_free(&context->V); + + mbedtls_mpi_free(&context->w0); + mbedtls_mpi_free(&context->w1); + mbedtls_mpi_free(&context->xy); + mbedtls_mpi_free(&context->tempbn); + + mbedtls_ecp_group_free(&context->curve); + state = CHIP_SPAKE2P_STATE::PREINIT; +} + +CHIP_ERROR Spake2p_P256_SHA256_HKDF_HMAC::Mac(const uint8_t * key, size_t key_len, const uint8_t * in, size_t in_len, + MutableByteSpan & out_span) +{ + HMAC_sha hmac; + VerifyOrReturnError(out_span.size() >= kSHA256_Hash_Length, CHIP_ERROR_BUFFER_TOO_SMALL); + ReturnErrorOnFailure(hmac.HMAC_SHA256(key, key_len, in, in_len, out_span.data(), kSHA256_Hash_Length)); + out_span = out_span.SubSpan(0, kSHA256_Hash_Length); + return CHIP_NO_ERROR; +} + +CHIP_ERROR Spake2p_P256_SHA256_HKDF_HMAC::MacVerify(const uint8_t * key, size_t key_len, const uint8_t * mac, size_t mac_len, + const uint8_t * in, size_t in_len) +{ + CHIP_ERROR error = CHIP_NO_ERROR; + int result = 0; + + uint8_t computed_mac[kSHA256_Hash_Length]; + MutableByteSpan computed_mac_span{ computed_mac }; + VerifyOrExit(mac_len == kSHA256_Hash_Length, error = CHIP_ERROR_INVALID_ARGUMENT); + + SuccessOrExit(error = Mac(key, key_len, in, in_len, computed_mac_span)); + VerifyOrExit(computed_mac_span.size() == mac_len, error = CHIP_ERROR_INTERNAL); + + VerifyOrExit(IsBufferContentEqualConstantTime(mac, computed_mac, kSHA256_Hash_Length), error = CHIP_ERROR_INTERNAL); + +exit: + _log_mbedTLS_error(result); + return error; +} + +CHIP_ERROR Spake2p_P256_SHA256_HKDF_HMAC::FELoad(const uint8_t * in, size_t in_len, void * fe) +{ + CHIP_ERROR error = CHIP_NO_ERROR; + int result = 0; + + result = mbedtls_mpi_read_binary((mbedtls_mpi *) fe, Uint8::to_const_uchar(in), in_len); + VerifyOrExit(result == 0, error = CHIP_ERROR_INTERNAL); + + result = mbedtls_mpi_mod_mpi((mbedtls_mpi *) fe, (mbedtls_mpi *) fe, (const mbedtls_mpi *) order); + VerifyOrExit(result == 0, error = CHIP_ERROR_INTERNAL); + +exit: + _log_mbedTLS_error(result); + return error; +} + +CHIP_ERROR Spake2p_P256_SHA256_HKDF_HMAC::FEWrite(const void * fe, uint8_t * out, size_t out_len) +{ + if (mbedtls_mpi_write_binary((const mbedtls_mpi *) fe, Uint8::to_uchar(out), out_len) != 0) + { + return CHIP_ERROR_INTERNAL; + } + return CHIP_NO_ERROR; +} + +CHIP_ERROR Spake2p_P256_SHA256_HKDF_HMAC::FEGenerate(void * fe) +{ + CHIP_ERROR error = CHIP_NO_ERROR; + int result = 0; + + Spake2p_Context * context = to_inner_spake2p_context(&mSpake2pContext); + + result = mbedtls_ecp_gen_privkey(&context->curve, (mbedtls_mpi *) fe, CryptoRNG, nullptr); + VerifyOrExit(result == 0, error = CHIP_ERROR_INTERNAL); + +exit: + _log_mbedTLS_error(result); + return error; +} + +CHIP_ERROR Spake2p_P256_SHA256_HKDF_HMAC::FEMul(void * fer, const void * fe1, const void * fe2) +{ + CHIP_ERROR error = CHIP_NO_ERROR; + int result = 0; + + result = mbedtls_mpi_mul_mpi((mbedtls_mpi *) fer, (const mbedtls_mpi *) fe1, (const mbedtls_mpi *) fe2); + VerifyOrExit(result == 0, error = CHIP_ERROR_INTERNAL); + + result = mbedtls_mpi_mod_mpi((mbedtls_mpi *) fer, (mbedtls_mpi *) fer, (const mbedtls_mpi *) order); + VerifyOrExit(result == 0, error = CHIP_ERROR_INTERNAL); + +exit: + _log_mbedTLS_error(result); + return error; +} + +CHIP_ERROR Spake2p_P256_SHA256_HKDF_HMAC::PointLoad(const uint8_t * in, size_t in_len, void * R) +{ + Spake2p_Context * context = to_inner_spake2p_context(&mSpake2pContext); + + if (mbedtls_ecp_point_read_binary(&context->curve, (mbedtls_ecp_point *) R, Uint8::to_const_uchar(in), in_len) != 0) + { + return CHIP_ERROR_INTERNAL; + } + + return CHIP_NO_ERROR; +} + +CHIP_ERROR Spake2p_P256_SHA256_HKDF_HMAC::PointWrite(const void * R, uint8_t * out, size_t out_len) +{ + memset(out, 0, out_len); + + size_t mbedtls_out_len = out_len; + + Spake2p_Context * context = to_inner_spake2p_context(&mSpake2pContext); + + if (mbedtls_ecp_point_write_binary(&context->curve, (const mbedtls_ecp_point *) R, MBEDTLS_ECP_PF_UNCOMPRESSED, + &mbedtls_out_len, Uint8::to_uchar(out), out_len) != 0) + { + return CHIP_ERROR_INTERNAL; + } + + return CHIP_NO_ERROR; +} + +CHIP_ERROR Spake2p_P256_SHA256_HKDF_HMAC::PointMul(void * R, const void * P1, const void * fe1) +{ + Spake2p_Context * context = to_inner_spake2p_context(&mSpake2pContext); + + if (mbedtls_ecp_mul(&context->curve, (mbedtls_ecp_point *) R, (const mbedtls_mpi *) fe1, (const mbedtls_ecp_point *) P1, + CryptoRNG, nullptr) != 0) + { + return CHIP_ERROR_INTERNAL; + } + + return CHIP_NO_ERROR; +} + +CHIP_ERROR Spake2p_P256_SHA256_HKDF_HMAC::PointAddMul(void * R, const void * P1, const void * fe1, const void * P2, + const void * fe2) +{ + Spake2p_Context * context = to_inner_spake2p_context(&mSpake2pContext); + + if (mbedtls_ecp_muladd(&context->curve, (mbedtls_ecp_point *) R, (const mbedtls_mpi *) fe1, (const mbedtls_ecp_point *) P1, + (const mbedtls_mpi *) fe2, (const mbedtls_ecp_point *) P2) != 0) + { + return CHIP_ERROR_INTERNAL; + } + + return CHIP_NO_ERROR; +} + +CHIP_ERROR Spake2p_P256_SHA256_HKDF_HMAC::PointInvert(void * R) +{ + mbedtls_ecp_point * Rp = (mbedtls_ecp_point *) R; + Spake2p_Context * context = to_inner_spake2p_context(&mSpake2pContext); + + if (mbedtls_mpi_sub_mpi(&Rp->CHIP_CRYPTO_PAL_PRIVATE(Y), &context->curve.P, &Rp->CHIP_CRYPTO_PAL_PRIVATE(Y)) != 0) + { + return CHIP_ERROR_INTERNAL; + } + + return CHIP_NO_ERROR; +} + +CHIP_ERROR Spake2p_P256_SHA256_HKDF_HMAC::PointCofactorMul(void * R) +{ + return CHIP_NO_ERROR; +} + +CHIP_ERROR Spake2p_P256_SHA256_HKDF_HMAC::ComputeL(uint8_t * Lout, size_t * L_len, const uint8_t * w1in, size_t w1in_len) +{ + CHIP_ERROR error = CHIP_NO_ERROR; + int result = 0; + + mbedtls_ecp_group curve; + mbedtls_mpi w1_bn; + mbedtls_ecp_point Ltemp; + + mbedtls_ecp_group_init(&curve); + mbedtls_mpi_init(&w1_bn); + mbedtls_ecp_point_init(&Ltemp); + + result = mbedtls_ecp_group_load(&curve, MBEDTLS_ECP_DP_SECP256R1); + VerifyOrExit(result == 0, error = CHIP_ERROR_INTERNAL); + + result = mbedtls_mpi_read_binary(&w1_bn, Uint8::to_const_uchar(w1in), w1in_len); + VerifyOrExit(result == 0, error = CHIP_ERROR_INTERNAL); + + result = mbedtls_mpi_mod_mpi(&w1_bn, &w1_bn, &curve.N); + VerifyOrExit(result == 0, error = CHIP_ERROR_INTERNAL); + + result = mbedtls_ecp_mul(&curve, &Ltemp, &w1_bn, &curve.G, CryptoRNG, nullptr); + VerifyOrExit(result == 0, error = CHIP_ERROR_INTERNAL); + + memset(Lout, 0, *L_len); + + result = mbedtls_ecp_point_write_binary(&curve, &Ltemp, MBEDTLS_ECP_PF_UNCOMPRESSED, L_len, Uint8::to_uchar(Lout), *L_len); + VerifyOrExit(result == 0, error = CHIP_ERROR_INTERNAL); + +exit: + _log_mbedTLS_error(result); + mbedtls_ecp_point_free(&Ltemp); + mbedtls_mpi_free(&w1_bn); + mbedtls_ecp_group_free(&curve); + + return error; +} + +CHIP_ERROR Spake2p_P256_SHA256_HKDF_HMAC::PointIsValid(void * R) +{ + Spake2p_Context * context = to_inner_spake2p_context(&mSpake2pContext); + + if (mbedtls_ecp_check_pubkey(&context->curve, (mbedtls_ecp_point *) R) != 0) + { + return CHIP_ERROR_INTERNAL; + } + + return CHIP_NO_ERROR; +} + +namespace { + +#if defined(MBEDTLS_X509_CRT_PARSE_C) +bool IsTimeGreaterThanEqual(const mbedtls_x509_time * const timeA, const mbedtls_x509_time * const timeB) +{ + + // checks if two values are different and if yes, then returns first > second. +#define RETURN_STRICTLY_GREATER_IF_DIFFERENT(component) \ + { \ + auto valueA = timeA->CHIP_CRYPTO_PAL_PRIVATE_X509(component); \ + auto valueB = timeB->CHIP_CRYPTO_PAL_PRIVATE_X509(component); \ + \ + if (valueA != valueB) \ + { \ + return valueA > valueB; \ + } \ + } + + RETURN_STRICTLY_GREATER_IF_DIFFERENT(year); + RETURN_STRICTLY_GREATER_IF_DIFFERENT(mon); + RETURN_STRICTLY_GREATER_IF_DIFFERENT(day); + RETURN_STRICTLY_GREATER_IF_DIFFERENT(hour); + RETURN_STRICTLY_GREATER_IF_DIFFERENT(min); + RETURN_STRICTLY_GREATER_IF_DIFFERENT(sec); + + // all above are equal + return true; +} + +CHIP_ERROR IsCertificateValidAtIssuance(const mbedtls_x509_crt * candidateCertificate, const mbedtls_x509_crt * issuerCertificate) +{ + mbedtls_x509_time candidateNotBeforeTime = candidateCertificate->CHIP_CRYPTO_PAL_PRIVATE_X509(valid_from); + mbedtls_x509_time issuerNotBeforeTime = issuerCertificate->CHIP_CRYPTO_PAL_PRIVATE_X509(valid_from); + mbedtls_x509_time issuerNotAfterTime = issuerCertificate->CHIP_CRYPTO_PAL_PRIVATE_X509(valid_to); + + // check if candidateCertificate is issued at or after issuerCertificate's notBefore timestamp + VerifyOrReturnError(IsTimeGreaterThanEqual(&candidateNotBeforeTime, &issuerNotBeforeTime), CHIP_ERROR_CERT_EXPIRED); + + // check if candidateCertificate is issued at or before issuerCertificate's notAfter timestamp + VerifyOrReturnError(IsTimeGreaterThanEqual(&issuerNotAfterTime, &candidateNotBeforeTime), CHIP_ERROR_CERT_EXPIRED); + + return CHIP_NO_ERROR; +} + +int CallbackForCustomValidityCheck(void * data, mbedtls_x509_crt * crt, int depth, uint32_t * flags) +{ + mbedtls_x509_crt * leafCert = reinterpret_cast(data); + mbedtls_x509_crt * issuerCert = crt; + + // Ignore any time validy error performed by the standard mbedTLS code. + *flags &= ~(static_cast(MBEDTLS_X509_BADCERT_EXPIRED | MBEDTLS_X509_BADCERT_FUTURE)); + + // Verify that the leaf certificate has a notBefore time valid within the validity period of the issuerCertificate. + // Note that this callback is invoked for each certificate in the chain. + if (IsCertificateValidAtIssuance(leafCert, issuerCert) != CHIP_NO_ERROR) + { + return MBEDTLS_ERR_X509_INVALID_DATE; + } + + return 0; +} + +constexpr uint8_t sOID_AttributeType_CommonName[] = { 0x55, 0x04, 0x03 }; +constexpr uint8_t sOID_AttributeType_MatterVendorId[] = { 0x2B, 0x06, 0x01, 0x04, 0x01, 0x82, 0xA2, 0x7C, 0x02, 0x01 }; +constexpr uint8_t sOID_AttributeType_MatterProductId[] = { 0x2B, 0x06, 0x01, 0x04, 0x01, 0x82, 0xA2, 0x7C, 0x02, 0x02 }; +constexpr uint8_t sOID_SigAlgo_ECDSAWithSHA256[] = { 0x2A, 0x86, 0x48, 0xCE, 0x3D, 0x04, 0x03, 0x02 }; +constexpr uint8_t sOID_Extension_BasicConstraints[] = { 0x55, 0x1D, 0x13 }; +constexpr uint8_t sOID_Extension_KeyUsage[] = { 0x55, 0x1D, 0x0F }; +constexpr uint8_t sOID_Extension_SubjectKeyIdentifier[] = { 0x55, 0x1D, 0x0E }; +constexpr uint8_t sOID_Extension_AuthorityKeyIdentifier[] = { 0x55, 0x1D, 0x23 }; + +/** + * Compares an mbedtls_asn1_buf structure (oidBuf) to a reference OID represented as uint8_t array (oid). + */ +#define OID_CMP(oid, oidBuf) \ + ((MBEDTLS_ASN1_OID == (oidBuf).CHIP_CRYPTO_PAL_PRIVATE_X509(tag)) && \ + (sizeof(oid) == (oidBuf).CHIP_CRYPTO_PAL_PRIVATE_X509(len)) && \ + (memcmp((oid), (oidBuf).CHIP_CRYPTO_PAL_PRIVATE_X509(p), (oidBuf).CHIP_CRYPTO_PAL_PRIVATE_X509(len)) == 0)) + +#endif // defined(MBEDTLS_X509_CRT_PARSE_C) + +} // anonymous namespace + +CHIP_ERROR VerifyAttestationCertificateFormat(const ByteSpan & cert, AttestationCertType certType) +{ +#if defined(MBEDTLS_X509_CRT_PARSE_C) + CHIP_ERROR error = CHIP_NO_ERROR; + int result = 0; + mbedtls_x509_crt mbed_cert; + unsigned char * p = nullptr; + const unsigned char * end = nullptr; + size_t len = 0; + bool extBasicPresent = false; + bool extKeyUsagePresent = false; + + VerifyOrReturnError(!cert.empty(), CHIP_ERROR_INVALID_ARGUMENT); + + mbedtls_x509_crt_init(&mbed_cert); + + result = mbedtls_x509_crt_parse(&mbed_cert, Uint8::to_const_uchar(cert.data()), cert.size()); + VerifyOrExit(result == 0, error = CHIP_ERROR_INTERNAL); + + // "version" value is 1 higher than the actual encoded value. + VerifyOrExit(mbed_cert.CHIP_CRYPTO_PAL_PRIVATE_X509(version) - 1 == 2, error = CHIP_ERROR_INTERNAL); + + // Verify signature algorithms is ECDSA with SHA256. + VerifyOrExit(OID_CMP(sOID_SigAlgo_ECDSAWithSHA256, mbed_cert.CHIP_CRYPTO_PAL_PRIVATE_X509(sig_oid)), + error = CHIP_ERROR_INTERNAL); + + // Verify public key presence and format. + { + Crypto::P256PublicKey pubkey; + SuccessOrExit(error = ExtractPubkeyFromX509Cert(cert, pubkey)); + } + + p = mbed_cert.CHIP_CRYPTO_PAL_PRIVATE_X509(v3_ext).CHIP_CRYPTO_PAL_PRIVATE_X509(p); + end = p + mbed_cert.CHIP_CRYPTO_PAL_PRIVATE_X509(v3_ext).CHIP_CRYPTO_PAL_PRIVATE_X509(len); + result = mbedtls_asn1_get_tag(&p, end, &len, MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE); + VerifyOrExit(result == 0, error = CHIP_ERROR_INTERNAL); + + while (p < end) + { + mbedtls_x509_buf extOID = { 0, 0, nullptr }; + int extCritical = 0; + + result = mbedtls_asn1_get_tag(&p, end, &len, MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE); + VerifyOrExit(result == 0, error = CHIP_ERROR_INTERNAL); + + /* Get extension ID */ + result = mbedtls_asn1_get_tag(&p, end, &len, MBEDTLS_ASN1_OID); + VerifyOrExit(result == 0, error = CHIP_ERROR_INTERNAL); + + extOID.CHIP_CRYPTO_PAL_PRIVATE_X509(tag) = MBEDTLS_ASN1_OID; + extOID.CHIP_CRYPTO_PAL_PRIVATE_X509(len) = len; + extOID.CHIP_CRYPTO_PAL_PRIVATE_X509(p) = p; + p += len; + + /* Get optional critical */ + result = mbedtls_asn1_get_bool(&p, end, &extCritical); + VerifyOrExit(result == 0 || result == MBEDTLS_ERR_ASN1_UNEXPECTED_TAG, error = CHIP_ERROR_INTERNAL); + + /* Data should be octet string type */ + result = mbedtls_asn1_get_tag(&p, end, &len, MBEDTLS_ASN1_OCTET_STRING); + VerifyOrExit(result == 0, error = CHIP_ERROR_INTERNAL); + + if (OID_CMP(sOID_Extension_BasicConstraints, extOID)) + { + int isCA = 0; + int pathLen = -1; + unsigned char * seqStart = p; + + VerifyOrExit(extCritical, error = CHIP_ERROR_INTERNAL); + extBasicPresent = true; + + result = mbedtls_asn1_get_tag(&p, end, &len, MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE); + VerifyOrExit(result == 0, error = CHIP_ERROR_INTERNAL); + if (len > 0) + { + result = mbedtls_asn1_get_bool(&p, end, &isCA); + VerifyOrExit(result == 0 || result == MBEDTLS_ERR_ASN1_UNEXPECTED_TAG, error = CHIP_ERROR_INTERNAL); + + if (p != seqStart + len) + { + result = mbedtls_asn1_get_int(&p, end, &pathLen); + VerifyOrExit(result == 0, error = CHIP_ERROR_INTERNAL); + } + } + + if (certType == AttestationCertType::kDAC) + { + VerifyOrExit(!isCA && pathLen == -1, error = CHIP_ERROR_INTERNAL); + } + else if (certType == AttestationCertType::kPAI) + { + VerifyOrExit(isCA && pathLen == 0, error = CHIP_ERROR_INTERNAL); + } + else + { + VerifyOrExit(isCA && (pathLen == -1 || pathLen == 0 || pathLen == 1), error = CHIP_ERROR_INTERNAL); + } + } + else if (OID_CMP(sOID_Extension_KeyUsage, extOID)) + { + mbedtls_x509_bitstring bs = { 0, 0, nullptr }; + unsigned int keyUsage = 0; + + VerifyOrExit(extCritical, error = CHIP_ERROR_INTERNAL); + extKeyUsagePresent = true; + + result = mbedtls_asn1_get_bitstring(&p, p + len, &bs); + VerifyOrExit(result == 0, error = CHIP_ERROR_INTERNAL); + + for (size_t i = 0; i < bs.CHIP_CRYPTO_PAL_PRIVATE_X509(len) && i < sizeof(unsigned int); i++) + { + keyUsage |= static_cast(bs.CHIP_CRYPTO_PAL_PRIVATE_X509(p)[i]) << (8 * i); + } + + if (certType == AttestationCertType::kDAC) + { + // SHALL only have the digitalSignature bit set. + VerifyOrExit(keyUsage == MBEDTLS_X509_KU_DIGITAL_SIGNATURE, error = CHIP_ERROR_INTERNAL); + } + else + { + bool keyCertSignFlag = keyUsage & MBEDTLS_X509_KU_KEY_CERT_SIGN; + bool crlSignFlag = keyUsage & MBEDTLS_X509_KU_CRL_SIGN; + bool otherFlags = + keyUsage & ~(MBEDTLS_X509_KU_CRL_SIGN | MBEDTLS_X509_KU_KEY_CERT_SIGN | MBEDTLS_X509_KU_DIGITAL_SIGNATURE); + VerifyOrExit(keyCertSignFlag && crlSignFlag && !otherFlags, error = CHIP_ERROR_INTERNAL); + } + } + else + { + p += len; + } + } + + // Verify basic and key usage extensions are present. + VerifyOrExit(extBasicPresent && extKeyUsagePresent, error = CHIP_ERROR_INTERNAL); + + // Verify that SKID and AKID extensions are present. + { + uint8_t kidBuf[kSubjectKeyIdentifierLength]; + MutableByteSpan kid(kidBuf); + SuccessOrExit(error = ExtractSKIDFromX509Cert(cert, kid)); + if (certType == AttestationCertType::kDAC || certType == AttestationCertType::kPAI) + { + // Mandatory extension for DAC and PAI certs. + SuccessOrExit(error = ExtractAKIDFromX509Cert(cert, kid)); + } + } + +exit: + _log_mbedTLS_error(result); + mbedtls_x509_crt_free(&mbed_cert); + +#else + (void) cert; + (void) certType; + CHIP_ERROR error = CHIP_ERROR_NOT_IMPLEMENTED; +#endif // defined(MBEDTLS_X509_CRT_PARSE_C) + + return error; +} + +CHIP_ERROR ValidateCertificateChain(const uint8_t * rootCertificate, size_t rootCertificateLen, const uint8_t * caCertificate, + size_t caCertificateLen, const uint8_t * leafCertificate, size_t leafCertificateLen, + CertificateChainValidationResult & result) +{ +#if defined(MBEDTLS_X509_CRT_PARSE_C) + CHIP_ERROR error = CHIP_NO_ERROR; + mbedtls_x509_crt certChain; + mbedtls_x509_crt rootCert; + int mbedResult; + uint32_t flags = 0; + + result = CertificateChainValidationResult::kInternalFrameworkError; + + VerifyOrReturnError(rootCertificate != nullptr && rootCertificateLen != 0, + (result = CertificateChainValidationResult::kRootArgumentInvalid, CHIP_ERROR_INVALID_ARGUMENT)); + VerifyOrReturnError(leafCertificate != nullptr && leafCertificateLen != 0, + (result = CertificateChainValidationResult::kLeafArgumentInvalid, CHIP_ERROR_INVALID_ARGUMENT)); + + mbedtls_x509_crt_init(&certChain); + mbedtls_x509_crt_init(&rootCert); + + /* Start of chain */ + mbedResult = mbedtls_x509_crt_parse(&certChain, Uint8::to_const_uchar(leafCertificate), leafCertificateLen); + VerifyOrExit(mbedResult == 0, (result = CertificateChainValidationResult::kLeafFormatInvalid, error = CHIP_ERROR_INTERNAL)); + + /* Add the intermediate to the chain, if present */ + if (caCertificate != nullptr && caCertificateLen > 0) + { + mbedResult = mbedtls_x509_crt_parse(&certChain, Uint8::to_const_uchar(caCertificate), caCertificateLen); + VerifyOrExit(mbedResult == 0, (result = CertificateChainValidationResult::kICAFormatInvalid, error = CHIP_ERROR_INTERNAL)); + } + + /* Parse the root cert */ + mbedResult = mbedtls_x509_crt_parse(&rootCert, Uint8::to_const_uchar(rootCertificate), rootCertificateLen); + VerifyOrExit(mbedResult == 0, (result = CertificateChainValidationResult::kRootFormatInvalid, error = CHIP_ERROR_INTERNAL)); + + /* Verify the chain against the root */ + mbedResult = + mbedtls_x509_crt_verify(&certChain, &rootCert, nullptr, nullptr, &flags, CallbackForCustomValidityCheck, &certChain); + + switch (mbedResult) + { + case 0: + VerifyOrExit(flags == 0, (result = CertificateChainValidationResult::kInternalFrameworkError, error = CHIP_ERROR_INTERNAL)); + result = CertificateChainValidationResult::kSuccess; + break; + case MBEDTLS_ERR_X509_INVALID_DATE: + case MBEDTLS_ERR_X509_CERT_VERIFY_FAILED: + result = CertificateChainValidationResult::kChainInvalid; + error = CHIP_ERROR_CERT_NOT_TRUSTED; + break; + default: + result = CertificateChainValidationResult::kInternalFrameworkError; + error = CHIP_ERROR_INTERNAL; + break; + } + +exit: + _log_mbedTLS_error(mbedResult); + mbedtls_x509_crt_free(&certChain); + mbedtls_x509_crt_free(&rootCert); + +#else + (void) rootCertificate; + (void) rootCertificateLen; + (void) caCertificate; + (void) caCertificateLen; + (void) leafCertificate; + (void) leafCertificateLen; + (void) result; + CHIP_ERROR error = CHIP_ERROR_NOT_IMPLEMENTED; +#endif // defined(MBEDTLS_X509_CRT_PARSE_C) + + return error; +} + +CHIP_ERROR IsCertificateValidAtIssuance(const ByteSpan & candidateCertificate, const ByteSpan & issuerCertificate) +{ +#if defined(MBEDTLS_X509_CRT_PARSE_C) + CHIP_ERROR error = CHIP_NO_ERROR; + mbedtls_x509_crt mbedCandidateCertificate; + mbedtls_x509_crt mbedIssuerCertificate; + int result; + + VerifyOrReturnError(!candidateCertificate.empty() && !issuerCertificate.empty(), CHIP_ERROR_INVALID_ARGUMENT); + + mbedtls_x509_crt_init(&mbedCandidateCertificate); + mbedtls_x509_crt_init(&mbedIssuerCertificate); + + result = mbedtls_x509_crt_parse(&mbedCandidateCertificate, Uint8::to_const_uchar(candidateCertificate.data()), + candidateCertificate.size()); + VerifyOrExit(result == 0, error = CHIP_ERROR_INTERNAL); + + result = + mbedtls_x509_crt_parse(&mbedIssuerCertificate, Uint8::to_const_uchar(issuerCertificate.data()), issuerCertificate.size()); + VerifyOrExit(result == 0, error = CHIP_ERROR_INTERNAL); + + // Verify that the candidateCertificate has a notBefore time valid within the validity period of the issuerCertificate. + SuccessOrExit(error = IsCertificateValidAtIssuance(&mbedCandidateCertificate, &mbedIssuerCertificate)); + +exit: + _log_mbedTLS_error(result); + mbedtls_x509_crt_free(&mbedCandidateCertificate); + mbedtls_x509_crt_free(&mbedIssuerCertificate); + +#else + (void) candidateCertificate; + (void) issuerCertificate; + CHIP_ERROR error = CHIP_ERROR_NOT_IMPLEMENTED; +#endif // defined(MBEDTLS_X509_CRT_PARSE_C) + + return error; +} + +CHIP_ERROR IsCertificateValidAtCurrentTime(const ByteSpan & certificate) +{ +#if defined(MBEDTLS_X509_CRT_PARSE_C) + CHIP_ERROR error = CHIP_NO_ERROR; + mbedtls_x509_crt mbedCertificate; + int result; + + VerifyOrReturnError(!certificate.empty(), CHIP_ERROR_INVALID_ARGUMENT); + + mbedtls_x509_crt_init(&mbedCertificate); + + result = mbedtls_x509_crt_parse(&mbedCertificate, Uint8::to_const_uchar(certificate.data()), certificate.size()); + VerifyOrExit(result == 0, error = CHIP_ERROR_INTERNAL); + + // check if certificate's notBefore timestamp is earlier than or equal to current time. + result = mbedtls_x509_time_is_past(&mbedCertificate.CHIP_CRYPTO_PAL_PRIVATE_X509(valid_from)); + VerifyOrExit(result == 1, error = CHIP_ERROR_CERT_EXPIRED); + + // check if certificate's notAfter timestamp is later than current time. + result = mbedtls_x509_time_is_future(&mbedCertificate.CHIP_CRYPTO_PAL_PRIVATE_X509(valid_to)); + VerifyOrExit(result == 1, error = CHIP_ERROR_CERT_EXPIRED); + +exit: + _log_mbedTLS_error(result); + mbedtls_x509_crt_free(&mbedCertificate); + +#else + (void) certificate; + CHIP_ERROR error = CHIP_ERROR_NOT_IMPLEMENTED; +#endif // defined(MBEDTLS_X509_CRT_PARSE_C) + + return error; +} + +CHIP_ERROR ExtractPubkeyFromX509Cert(const ByteSpan & certificate, Crypto::P256PublicKey & pubkey) +{ +#if defined(MBEDTLS_X509_CRT_PARSE_C) + CHIP_ERROR error = CHIP_NO_ERROR; + mbedtls_x509_crt mbed_cert; + mbedtls_ecp_keypair * keypair = nullptr; + size_t pubkey_size = 0; + + mbedtls_x509_crt_init(&mbed_cert); + + int result = mbedtls_x509_crt_parse(&mbed_cert, Uint8::to_const_uchar(certificate.data()), certificate.size()); + VerifyOrExit(result == 0, error = CHIP_ERROR_INTERNAL); + + VerifyOrExit(mbedtls_pk_get_type(&(mbed_cert.CHIP_CRYPTO_PAL_PRIVATE_X509(pk))) == MBEDTLS_PK_ECKEY, + error = CHIP_ERROR_INVALID_ARGUMENT); + + keypair = mbedtls_pk_ec(mbed_cert.CHIP_CRYPTO_PAL_PRIVATE_X509(pk)); + VerifyOrExit(keypair->CHIP_CRYPTO_PAL_PRIVATE(grp).id == MapECPGroupId(pubkey.Type()), error = CHIP_ERROR_INVALID_ARGUMENT); + // Copy the public key from the cert in raw point format + result = + mbedtls_ecp_point_write_binary(&keypair->CHIP_CRYPTO_PAL_PRIVATE(grp), &keypair->CHIP_CRYPTO_PAL_PRIVATE(Q), + MBEDTLS_ECP_PF_UNCOMPRESSED, &pubkey_size, Uint8::to_uchar(pubkey.Bytes()), pubkey.Length()); + + VerifyOrExit(result == 0, error = CHIP_ERROR_INTERNAL); + VerifyOrExit(pubkey_size == pubkey.Length(), error = CHIP_ERROR_INTERNAL); + +exit: + _log_mbedTLS_error(result); + mbedtls_x509_crt_free(&mbed_cert); + +#else + (void) certificate; + (void) pubkey; + CHIP_ERROR error = CHIP_ERROR_NOT_IMPLEMENTED; +#endif // defined(MBEDTLS_X509_CRT_PARSE_C) + + return error; +} + +namespace { + +CHIP_ERROR ExtractKIDFromX509Cert(bool extractSKID, const ByteSpan & certificate, MutableByteSpan & kid) +{ +#if defined(MBEDTLS_X509_CRT_PARSE_C) + CHIP_ERROR error = CHIP_ERROR_NOT_FOUND; + mbedtls_x509_crt mbed_cert; + unsigned char * p = nullptr; + const unsigned char * end = nullptr; + size_t len = 0; + + mbedtls_x509_crt_init(&mbed_cert); + + int result = mbedtls_x509_crt_parse(&mbed_cert, Uint8::to_const_uchar(certificate.data()), certificate.size()); + VerifyOrExit(result == 0, error = CHIP_ERROR_INTERNAL); + + // TODO: The mbedTLS team is working on supporting SKID and AKID extensions processing. + // Once it is supported, this code should be updated. + + p = mbed_cert.CHIP_CRYPTO_PAL_PRIVATE_X509(v3_ext).CHIP_CRYPTO_PAL_PRIVATE_X509(p); + end = mbed_cert.CHIP_CRYPTO_PAL_PRIVATE_X509(v3_ext).CHIP_CRYPTO_PAL_PRIVATE_X509(p) + + mbed_cert.CHIP_CRYPTO_PAL_PRIVATE_X509(v3_ext).CHIP_CRYPTO_PAL_PRIVATE_X509(len); + result = mbedtls_asn1_get_tag(&p, end, &len, MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE); + VerifyOrExit(result == 0, error = CHIP_ERROR_WRONG_CERT_TYPE); + + while (p < end) + { + result = mbedtls_asn1_get_tag(&p, end, &len, MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE); + VerifyOrExit(result == 0, error = CHIP_ERROR_WRONG_CERT_TYPE); + result = mbedtls_asn1_get_tag(&p, end, &len, MBEDTLS_ASN1_OID); + VerifyOrExit(result == 0, error = CHIP_ERROR_WRONG_CERT_TYPE); + + mbedtls_x509_buf extOID = { MBEDTLS_ASN1_OID, len, p }; + bool extractCurrentExtSKID = extractSKID && OID_CMP(sOID_Extension_SubjectKeyIdentifier, extOID); + bool extractCurrentExtAKID = !extractSKID && OID_CMP(sOID_Extension_AuthorityKeyIdentifier, extOID); + p += len; + + int is_critical = 0; + result = mbedtls_asn1_get_bool(&p, end, &is_critical); + VerifyOrExit(result == 0 || result == MBEDTLS_ERR_ASN1_UNEXPECTED_TAG, error = CHIP_ERROR_WRONG_CERT_TYPE); + + result = mbedtls_asn1_get_tag(&p, end, &len, MBEDTLS_ASN1_OCTET_STRING); + VerifyOrExit(result == 0, error = CHIP_ERROR_WRONG_CERT_TYPE); + + if (extractCurrentExtSKID || extractCurrentExtAKID) + { + if (extractCurrentExtSKID) + { + result = mbedtls_asn1_get_tag(&p, end, &len, MBEDTLS_ASN1_OCTET_STRING); + VerifyOrExit(result == 0, error = CHIP_ERROR_WRONG_CERT_TYPE); + } + else + { + result = mbedtls_asn1_get_tag(&p, end, &len, MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE); + VerifyOrExit(result == 0, error = CHIP_ERROR_WRONG_CERT_TYPE); + result = mbedtls_asn1_get_tag(&p, end, &len, MBEDTLS_ASN1_CONTEXT_SPECIFIC); + VerifyOrExit(result == 0, error = CHIP_ERROR_WRONG_CERT_TYPE); + // Other optional fields, authorityCertIssuer and authorityCertSerialNumber, + // will be skipped if present. + } + VerifyOrExit(len == kSubjectKeyIdentifierLength, error = CHIP_ERROR_WRONG_CERT_TYPE); + VerifyOrExit(len <= kid.size(), error = CHIP_ERROR_BUFFER_TOO_SMALL); + memcpy(kid.data(), p, len); + if (kid.size() > len) + { + kid.reduce_size(len); + } + ExitNow(error = CHIP_NO_ERROR); + break; + } + p += len; + } + +exit: + _log_mbedTLS_error(result); + mbedtls_x509_crt_free(&mbed_cert); + +#else + (void) certificate; + (void) kid; + CHIP_ERROR error = CHIP_ERROR_NOT_IMPLEMENTED; +#endif // defined(MBEDTLS_X509_CRT_PARSE_C) + + return error; +} + +} // namespace + +CHIP_ERROR ExtractSKIDFromX509Cert(const ByteSpan & certificate, MutableByteSpan & skid) +{ + return ExtractKIDFromX509Cert(true, certificate, skid); +} + +CHIP_ERROR ExtractAKIDFromX509Cert(const ByteSpan & certificate, MutableByteSpan & akid) +{ + return ExtractKIDFromX509Cert(false, certificate, akid); +} + +CHIP_ERROR ExtractVIDPIDFromX509Cert(const ByteSpan & certificate, AttestationCertVidPid & vidpid) +{ +#if defined(MBEDTLS_X509_CRT_PARSE_C) + CHIP_ERROR error = CHIP_NO_ERROR; + mbedtls_x509_crt mbed_cert; + mbedtls_asn1_named_data * dnIterator = nullptr; + AttestationCertVidPid vidpidFromCN; + + mbedtls_x509_crt_init(&mbed_cert); + + int result = mbedtls_x509_crt_parse(&mbed_cert, Uint8::to_const_uchar(certificate.data()), certificate.size()); + VerifyOrExit(result == 0, error = CHIP_ERROR_INTERNAL); + + for (dnIterator = &mbed_cert.CHIP_CRYPTO_PAL_PRIVATE_X509(subject); dnIterator != nullptr; + dnIterator = dnIterator->CHIP_CRYPTO_PAL_PRIVATE_X509(next)) + { + DNAttrType attrType = DNAttrType::kUnspecified; + if (OID_CMP(sOID_AttributeType_CommonName, dnIterator->CHIP_CRYPTO_PAL_PRIVATE_X509(oid))) + { + attrType = DNAttrType::kCommonName; + } + else if (OID_CMP(sOID_AttributeType_MatterVendorId, dnIterator->CHIP_CRYPTO_PAL_PRIVATE_X509(oid))) + { + attrType = DNAttrType::kMatterVID; + } + else if (OID_CMP(sOID_AttributeType_MatterProductId, dnIterator->CHIP_CRYPTO_PAL_PRIVATE_X509(oid))) + { + attrType = DNAttrType::kMatterPID; + } + + size_t val_len = dnIterator->CHIP_CRYPTO_PAL_PRIVATE_X509(val).CHIP_CRYPTO_PAL_PRIVATE_X509(len); + uint8_t * val_p = dnIterator->CHIP_CRYPTO_PAL_PRIVATE_X509(val).CHIP_CRYPTO_PAL_PRIVATE_X509(p); + error = ExtractVIDPIDFromAttributeString(attrType, ByteSpan(val_p, val_len), vidpid, vidpidFromCN); + SuccessOrExit(error); + } + + // If Matter Attributes were not found use values extracted from the CN Attribute, + // which might be uninitialized as well. + if (!vidpid.Initialized()) + { + vidpid = vidpidFromCN; + } + +exit: + _log_mbedTLS_error(result); + mbedtls_x509_crt_free(&mbed_cert); + +#else + (void) certificate; + (void) vidpid; + CHIP_ERROR error = CHIP_ERROR_NOT_IMPLEMENTED; +#endif // defined(MBEDTLS_X509_CRT_PARSE_C) + + return error; +} + +} // namespace Crypto +} // namespace chip diff --git a/src/platform/nxp/crypto/se05x/CHIPCryptoPALHsm_se05x_config.h b/src/platform/nxp/crypto/se05x/CHIPCryptoPALHsm_se05x_config.h new file mode 100644 index 00000000000000..61db3cc26216dd --- /dev/null +++ b/src/platform/nxp/crypto/se05x/CHIPCryptoPALHsm_se05x_config.h @@ -0,0 +1,73 @@ +/* + * + * Copyright (c) 2020 Project CHIP Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/** + * @file + * Header that exposes the options to enable SE05x for required crypto operations. + */ + +#pragma once + +/* + * Enable se05x for SPAKE VERIFIER + */ +#define ENABLE_SE05X_SPAKE_VERIFIER 0 + +/* + * Enable se05x for SPAKE PROVER + */ +#define ENABLE_SE05X_SPAKE_PROVER 0 + +/* + * Enable se05x for random number generation + */ +#define ENABLE_SE05X_RND_GEN 1 + +/* + * Enable se05x for Generate EC Key + */ +#define ENABLE_SE05X_GENERATE_EC_KEY 1 + +/* + * Enable ECDSA Verify using se05x + */ +#define ENABLE_SE05X_ECDSA_VERIFY 1 + +/* + * Enable Key Import for se05x + */ +#define ENABLE_SE05X_KEY_IMPORT 0 + +/* + * Enable se05x for PBKDF SHA256 + */ +#define ENABLE_SE05X_PBKDF2_SHA256 0 + +/* + * Enable se05x for HKDF SHA256 + */ +#define ENABLE_SE05X_HKDF_SHA256 1 + +/* + * Enable se05x for HMAC SHA256 + */ +#define ENABLE_SE05X_HMAC_SHA256 1 + +/* + * Enable se05x for DA + */ +#define ENABLE_SE05X_DEVICE_ATTESTATION 0 diff --git a/src/crypto/hsm/nxp/CHIPCryptoPALHsm_SE05X_HKDF.cpp b/src/platform/nxp/crypto/se05x/CHIPCryptoPALHsm_se05x_hkdf.cpp similarity index 67% rename from src/crypto/hsm/nxp/CHIPCryptoPALHsm_SE05X_HKDF.cpp rename to src/platform/nxp/crypto/se05x/CHIPCryptoPALHsm_se05x_hkdf.cpp index 604ccac84f4e5a..4a3c06d4828272 100644 --- a/src/crypto/hsm/nxp/CHIPCryptoPALHsm_SE05X_HKDF.cpp +++ b/src/platform/nxp/crypto/se05x/CHIPCryptoPALHsm_se05x_hkdf.cpp @@ -22,31 +22,33 @@ * chip crypto apis use either HSM or rollback to software implementation. */ -#include "CHIPCryptoPALHsm_SE05X_utils.h" +#include "CHIPCryptoPALHsm_se05x_utils.h" #include -#if ENABLE_HSM_HKDF_SHA256 - namespace chip { namespace Crypto { -HKDF_shaHSM::HKDF_shaHSM() -{ - keyid = kKeyId_hkdf_sha256_hmac_keyid; -} -HKDF_shaHSM::~HKDF_shaHSM() {} +extern CHIP_ERROR HKDF_SHA256_H(const uint8_t * secret, const size_t secret_length, const uint8_t * salt, const size_t salt_length, + const uint8_t * info, const size_t info_length, uint8_t * out_buffer, size_t out_length); -CHIP_ERROR HKDF_shaHSM::HKDF_SHA256(const uint8_t * secret, const size_t secret_length, const uint8_t * salt, - const size_t salt_length, const uint8_t * info, const size_t info_length, uint8_t * out_buffer, - size_t out_length) +CHIP_ERROR HKDF_sha::HKDF_SHA256(const uint8_t * secret, const size_t secret_length, const uint8_t * salt, const size_t salt_length, + const uint8_t * info, const size_t info_length, uint8_t * out_buffer, size_t out_length) { - CHIP_ERROR error = CHIP_ERROR_INTERNAL; +#if !ENABLE_SE05X_HKDF_SHA256 + return HKDF_SHA256_H(secret, secret_length, salt, salt_length, info, info_length, out_buffer, out_length); +#else + CHIP_ERROR error = CHIP_ERROR_INTERNAL; + uint32_t keyid = kKeyId_hkdf_sha256_hmac_keyid; + sss_object_t keyObject = { 0 }; + if (salt_length > 64 || info_length > 80 || secret_length > 256 || out_length > 768) { /* Length not supported by se05x. Rollback to SW */ - return HKDF_sha::HKDF_SHA256(secret, secret_length, salt, salt_length, info, info_length, out_buffer, out_length); + return HKDF_SHA256_H(secret, secret_length, salt, salt_length, info, info_length, out_buffer, out_length); } + ChipLogDetail(Crypto, "HKDF_SHA256 : Using se05x for HKDF"); + // Salt is optional if (salt_length > 0) { @@ -58,13 +60,10 @@ CHIP_ERROR HKDF_shaHSM::HKDF_SHA256(const uint8_t * secret, const size_t secret_ VerifyOrReturnError(out_buffer != nullptr, CHIP_ERROR_INVALID_ARGUMENT); VerifyOrReturnError(secret != nullptr, CHIP_ERROR_INVALID_ARGUMENT); - VerifyOrReturnError(keyid != kKeyId_NotInitialized, CHIP_ERROR_HSM); - - se05x_sessionOpen(); + VerifyOrReturnError(se05x_sessionOpen() == CHIP_NO_ERROR, CHIP_ERROR_INTERNAL); VerifyOrReturnError(gex_sss_chip_ctx.ks.session != NULL, CHIP_ERROR_INTERNAL); - sss_object_t keyObject = { 0 }; - sss_status_t status = sss_key_object_init(&keyObject, &gex_sss_chip_ctx.ks); + sss_status_t status = sss_key_object_init(&keyObject, &gex_sss_chip_ctx.ks); VerifyOrReturnError(status == kStatus_SSS_Success, CHIP_ERROR_INTERNAL); status = sss_key_object_allocate_handle(&keyObject, keyid, kSSS_KeyPart_Default, kSSS_CipherType_HMAC, secret_length, @@ -81,12 +80,15 @@ CHIP_ERROR HKDF_shaHSM::HKDF_SHA256(const uint8_t * secret, const size_t secret_ error = CHIP_NO_ERROR; exit: - sss_key_store_erase_key(&gex_sss_chip_ctx.ks, &keyObject); + if (keyObject.keyStore->session != NULL) + { + sss_key_store_erase_key(&gex_sss_chip_ctx.ks, &keyObject); + } return error; + +#endif // ENABLE_SE05X_HKDF_SHA256 } } // namespace Crypto } // namespace chip - -#endif //#if ENABLE_HSM_HKDF_SHA256 diff --git a/src/crypto/hsm/nxp/CHIPCryptoPALHsm_SE05X_HMAC.cpp b/src/platform/nxp/crypto/se05x/CHIPCryptoPALHsm_se05x_hmac.cpp similarity index 80% rename from src/crypto/hsm/nxp/CHIPCryptoPALHsm_SE05X_HMAC.cpp rename to src/platform/nxp/crypto/se05x/CHIPCryptoPALHsm_se05x_hmac.cpp index b9d68424d59ca2..ca1fb0111e4a9a 100644 --- a/src/crypto/hsm/nxp/CHIPCryptoPALHsm_SE05X_HMAC.cpp +++ b/src/platform/nxp/crypto/se05x/CHIPCryptoPALHsm_se05x_hmac.cpp @@ -22,30 +22,31 @@ * chip crypto apis use either HSM or rollback to software implementation. */ -#include "CHIPCryptoPALHsm_SE05X_utils.h" +#include "CHIPCryptoPALHsm_se05x_utils.h" #include -#if ENABLE_HSM_HMAC_SHA256 - #define MAX_MAC_ONE_SHOT_DATA_LEN 900 namespace chip { namespace Crypto { -HMAC_shaHSM::HMAC_shaHSM() -{ - keyid = kKeyId_hmac_sha256_keyid; -} -HMAC_shaHSM::~HMAC_shaHSM() {} +extern CHIP_ERROR HMAC_SHA256_h(const uint8_t * key, size_t key_length, const uint8_t * message, size_t message_length, + uint8_t * out_buffer, size_t out_length); -CHIP_ERROR HMAC_shaHSM::HMAC_SHA256(const uint8_t * key, size_t key_length, const uint8_t * message, size_t message_length, - uint8_t * out_buffer, size_t out_length) +CHIP_ERROR HMAC_sha::HMAC_SHA256(const uint8_t * key, size_t key_length, const uint8_t * message, size_t message_length, + uint8_t * out_buffer, size_t out_length) { +#if !ENABLE_SE05X_HMAC_SHA256 + return HMAC_SHA256_h(key, key_length, message, message_length, out_buffer, out_length); +#else CHIP_ERROR error = CHIP_ERROR_INTERNAL; + uint32_t keyid = kKeyId_hmac_sha256_keyid; sss_mac_t ctx_mac = { 0 }; sss_object_t keyObject = { 0 }; + ChipLogDetail(Crypto, "HMAC_SHA256 : Using se05x for HMAC"); + VerifyOrReturnError(key != nullptr, CHIP_ERROR_INVALID_ARGUMENT); VerifyOrReturnError(key_length > 0, CHIP_ERROR_INVALID_ARGUMENT); VerifyOrReturnError(message != nullptr, CHIP_ERROR_INVALID_ARGUMENT); @@ -55,12 +56,12 @@ CHIP_ERROR HMAC_shaHSM::HMAC_SHA256(const uint8_t * key, size_t key_length, cons if (key_length > 256) { - return HMAC_sha::HMAC_SHA256(key, key_length, message, message_length, out_buffer, out_length); + return CHIP_ERROR_INTERNAL; // TODO - Add rollback } VerifyOrReturnError(keyid != kKeyId_NotInitialized, CHIP_ERROR_HSM); - se05x_sessionOpen(); + VerifyOrReturnError(se05x_sessionOpen() == CHIP_NO_ERROR, CHIP_ERROR_INTERNAL); VerifyOrReturnError(gex_sss_chip_ctx.ks.session != NULL, CHIP_ERROR_INTERNAL); sss_status_t status = sss_key_object_init(&keyObject, &gex_sss_chip_ctx.ks); @@ -110,12 +111,14 @@ CHIP_ERROR HMAC_shaHSM::HMAC_SHA256(const uint8_t * key, size_t key_length, cons sss_mac_context_free(&ctx_mac); } - sss_key_store_erase_key(&gex_sss_chip_ctx.ks, &keyObject); + if (keyObject.keyStore->session != NULL) + { + sss_key_store_erase_key(&gex_sss_chip_ctx.ks, &keyObject); + } return error; +#endif } } // namespace Crypto } // namespace chip - -#endif //#if ENABLE_HSM_HMAC_SHA256 diff --git a/src/crypto/hsm/nxp/CHIPCryptoPALHsm_SE05X_P256.cpp b/src/platform/nxp/crypto/se05x/CHIPCryptoPALHsm_se05x_p256.cpp similarity index 53% rename from src/crypto/hsm/nxp/CHIPCryptoPALHsm_SE05X_P256.cpp rename to src/platform/nxp/crypto/se05x/CHIPCryptoPALHsm_se05x_p256.cpp index a467f61fd8ea7d..a9c8cd94bdacb6 100644 --- a/src/crypto/hsm/nxp/CHIPCryptoPALHsm_SE05X_P256.cpp +++ b/src/platform/nxp/crypto/se05x/CHIPCryptoPALHsm_se05x_p256.cpp @@ -22,13 +22,12 @@ * chip crypto apis use either HSM or rollback to software implementation. */ -#include "CHIPCryptoPALHsm_SE05X_utils.h" +#include "CHIPCryptoPALHsm_se05x_utils.h" #include -#if ENABLE_HSM_GENERATE_EC_KEY - #define MAX_SHA_ONE_SHOT_DATA_LEN 900 #define NIST256_HEADER_OFFSET 26 +#define CRYPTO_KEYPAIR_KEYID_OFFSET 8 /* Used for CSR generation */ // Organisation info. @@ -47,84 +46,134 @@ const uint8_t kTlvHeader = 2; namespace chip { namespace Crypto { -P256KeypairHSM::~P256KeypairHSM() +#define EC_NIST_P256_KP_HEADER \ + { \ + 0x30, 0x81, 0x87, 0x02, 0x01, 0x00, 0x30, 0x13, 0x06, 0x07, 0x2A, 0x86, 0x48, 0xCE, 0x3D, 0x02, 0x01, 0x06, 0x08, 0x2A, \ + 0x86, 0x48, 0xCE, 0x3D, 0x03, 0x01, 0x07, 0x04, 0x6D, 0x30, 0x6B, 0x02, 0x01, 0x01, 0x04, 0x20, \ + } + +#define EC_NIST_P256_KP_PUB_HEADER \ + { \ + 0xA1, 0x44, 0x03, 0x42, 0x00, \ + } + +extern CHIP_ERROR Initialize_H(P256Keypair * pk, P256PublicKey * mPublicKey, P256KeypairContext * mKeypair); +extern CHIP_ERROR ECDSA_sign_msg_H(P256KeypairContext * mKeypair, const uint8_t * msg, const size_t msg_length, + P256ECDSASignature & out_signature); +extern CHIP_ERROR ECDH_derive_secret_H(P256KeypairContext * mKeypair, const P256PublicKey & remote_public_key, + P256ECDHDerivedSecret & out_secret); +extern CHIP_ERROR NewCertificateSigningRequest_H(P256KeypairContext * mKeypair, uint8_t * out_csr, size_t & csr_length); +extern CHIP_ERROR Deserialize_H(P256Keypair * pk, P256PublicKey * mPublicKey, P256KeypairContext * mKeypair, + P256SerializedKeypair & input); +extern CHIP_ERROR Serialize_H(const P256KeypairContext mKeypair, const P256PublicKey mPublicKey, P256SerializedKeypair & output); +extern CHIP_ERROR ECDSA_validate_msg_signature_H(const P256PublicKey * public_key, const uint8_t * msg, const size_t msg_length, + const P256ECDSASignature & signature); +extern CHIP_ERROR ECDSA_validate_hash_signature_H(const P256PublicKey * public_key, const uint8_t * hash, const size_t hash_length, + const P256ECDSASignature & signature); + +#if (ENABLE_SE05X_GENERATE_EC_KEY || ENABLE_SE05X_ECDSA_VERIFY) +static CHIP_ERROR parse_se05x_keyid_from_keypair(const P256KeypairContext mKeypair, uint32_t * key_id) { - if (keyid != kKeyId_NotInitialized) + if (0 != memcmp(&mKeypair.mBytes[0], se05x_magic_no, sizeof(se05x_magic_no))) { - if (provisioned_key == false) - { - ChipLogDetail(Crypto, "Deleting key with id - %x !", keyid); - se05x_delete_key(keyid); - } - else - { - ChipLogDetail(Crypto, "Provisioned key ! Not deleting key in HSM"); - } + return CHIP_ERROR_INTERNAL; + } + + *key_id += (mKeypair.mBytes[CRYPTO_KEYPAIR_KEYID_OFFSET] << (8 * 3) & 0xFF000000) | + (mKeypair.mBytes[CRYPTO_KEYPAIR_KEYID_OFFSET + 1] << (8 * 2) & 0x00FF0000) | + (mKeypair.mBytes[CRYPTO_KEYPAIR_KEYID_OFFSET + 2] << (8 * 1) & 0x0000FF00) | + (mKeypair.mBytes[CRYPTO_KEYPAIR_KEYID_OFFSET + 3] << (8 * 0) & 0x000000FF); + + return CHIP_NO_ERROR; +} +#endif //#if (ENABLE_SE05X_GENERATE_EC_KEY || ENABLE_SE05X_ECDSA_VERIFY) + +P256Keypair::~P256Keypair() +{ + uint32_t keyid = 0; + if (CHIP_NO_ERROR != parse_se05x_keyid_from_keypair(mKeypair, &keyid)) + { + Clear(); + } + else + { + // Delete the key in SE } } -CHIP_ERROR P256KeypairHSM::Initialize(ECPKeyTarget key_target) +CHIP_ERROR P256Keypair::Initialize(ECPKeyTarget key_target) { +#if !ENABLE_SE05X_GENERATE_EC_KEY + if (CHIP_NO_ERROR == Initialize_H(this, &mPublicKey, &mKeypair)) + { + mInitialized = true; + } + return error; +#else + sss_status_t status = kStatus_SSS_Fail; sss_object_t keyObject = { 0 }; uint8_t pubkey[128] = { 0, }; size_t pubKeyLen = sizeof(pubkey); size_t pbKeyBitLen = sizeof(pubkey) * 8; + uint32_t keyid = 0; + uint32_t options = kKeyObject_Mode_Transient; - if (keyid == 0) - { - ChipLogDetail(Crypto, "Keyid not set !. Set key id using 'SetKeyId' member class !"); - return CHIP_ERROR_INTERNAL; - } - - se05x_sessionOpen(); - - sss_status_t status = sss_key_object_init(&keyObject, &gex_sss_chip_ctx.ks); - VerifyOrReturnError(status == kStatus_SSS_Success, CHIP_ERROR_INTERNAL); + ChipLogDetail(Crypto, "se05x::Generate nist256 key using se05x"); - if (provisioned_key == false) + if (key_target == ECPKeyTarget::ECDH) { - - status = sss_key_object_allocate_handle(&keyObject, keyid, kSSS_KeyPart_Pair, kSSS_CipherType_EC_NIST_P, 256, - kKeyObject_Mode_Transient); - VerifyOrReturnError(status == kStatus_SSS_Success, CHIP_ERROR_INTERNAL); - - ChipLogDetail(Crypto, "Creating Nist256 key on SE05X !"); - - status = sss_key_store_generate_key(&gex_sss_chip_ctx.ks, &keyObject, 256, 0); - VerifyOrReturnError(status == kStatus_SSS_Success, CHIP_ERROR_INTERNAL); + keyid = kKeyId_case_ephemeral_keyid; } else { + // Add the logic to use different keyid + keyid = kKeyId_node_op_keyid_start; + options = kKeyObject_Mode_Persistent; + } - // if the key is provisioned already, only get the public key, - // and set it in public key member of this class. - ChipLogDetail(Crypto, "Provisioned key ! Not creating key in HSM"); + VerifyOrReturnError(se05x_sessionOpen() == CHIP_NO_ERROR, CHIP_ERROR_INTERNAL); - status = sss_key_object_get_handle(&keyObject, keyid); - VerifyOrReturnError(status == kStatus_SSS_Success, CHIP_ERROR_INTERNAL); - } + status = sss_key_object_init(&keyObject, &gex_sss_chip_ctx.ks); + VerifyOrReturnError(status == kStatus_SSS_Success, CHIP_ERROR_INTERNAL); + + status = sss_key_object_allocate_handle(&keyObject, keyid, kSSS_KeyPart_Pair, kSSS_CipherType_EC_NIST_P, 256, options); + VerifyOrReturnError(status == kStatus_SSS_Success, CHIP_ERROR_INTERNAL); + + status = sss_key_store_generate_key(&gex_sss_chip_ctx.ks, &keyObject, 256, 0); + VerifyOrReturnError(status == kStatus_SSS_Success, CHIP_ERROR_INTERNAL); status = sss_key_store_get_key(&gex_sss_chip_ctx.ks, &keyObject, pubkey, &pubKeyLen, &pbKeyBitLen); VerifyOrReturnError(status == kStatus_SSS_Success, CHIP_ERROR_INTERNAL); - { - /* Set the public key */ - P256PublicKeyHSM & public_key = const_cast(Pubkey()); - VerifyOrReturnError(pubKeyLen > NIST256_HEADER_OFFSET, CHIP_ERROR_INTERNAL); - VerifyOrReturnError((pubKeyLen - NIST256_HEADER_OFFSET) <= kP256_PublicKey_Length, CHIP_ERROR_INTERNAL); - memcpy((void *) Uint8::to_const_uchar(public_key), pubkey + NIST256_HEADER_OFFSET, pubKeyLen - NIST256_HEADER_OFFSET); - public_key.SetPublicKeyId(keyid); - } + /* Set the public key */ + P256PublicKey & public_key = const_cast(Pubkey()); + VerifyOrReturnError(pubKeyLen > NIST256_HEADER_OFFSET, CHIP_ERROR_INTERNAL); + VerifyOrReturnError((pubKeyLen - NIST256_HEADER_OFFSET) <= kP256_PublicKey_Length, CHIP_ERROR_INTERNAL); + memcpy((void *) Uint8::to_const_uchar(public_key), pubkey + NIST256_HEADER_OFFSET, pubKeyLen - NIST256_HEADER_OFFSET); + + memcpy(&mKeypair.mBytes[0], se05x_magic_no, sizeof(se05x_magic_no)); + mKeypair.mBytes[CRYPTO_KEYPAIR_KEYID_OFFSET] = (keyid >> (3 * 8)) & 0x000000FF; + mKeypair.mBytes[CRYPTO_KEYPAIR_KEYID_OFFSET + 1] = (keyid >> (2 * 8)) & 0x000000FF; + mKeypair.mBytes[CRYPTO_KEYPAIR_KEYID_OFFSET + 2] = (keyid >> (1 * 8)) & 0x000000FF; + mKeypair.mBytes[CRYPTO_KEYPAIR_KEYID_OFFSET + 3] = (keyid >> (0 * 8)) & 0x000000FF; + + mInitialized = true; return CHIP_NO_ERROR; +#endif // ENABLE_SE05X_GENERATE_EC_KEY } -CHIP_ERROR P256KeypairHSM::ECDSA_sign_msg(const uint8_t * msg, size_t msg_length, P256ECDSASignature & out_signature) const +CHIP_ERROR P256Keypair::ECDSA_sign_msg(const uint8_t * msg, size_t msg_length, P256ECDSASignature & out_signature) const { + VerifyOrReturnError(mInitialized, CHIP_ERROR_WELL_UNINITIALIZED); + +#if !ENABLE_SE05X_GENERATE_EC_KEY + return ECDSA_sign_msg_H(&mKeypair, msg, msg_length, out_signature); +#else CHIP_ERROR error = CHIP_ERROR_INTERNAL; - sss_digest_t digest_ctx = { 0 }; + uint32_t keyid = 0; sss_asymmetric_t asymm_ctx = { 0 }; uint8_t hash[kSHA256_Hash_Length] = { 0, @@ -136,44 +185,22 @@ CHIP_ERROR P256KeypairHSM::ECDSA_sign_msg(const uint8_t * msg, size_t msg_length size_t signature_se05x_len = sizeof(signature_se05x); MutableByteSpan out_raw_sig_span(out_signature.Bytes(), out_signature.Capacity()); - VerifyOrReturnError(msg != nullptr, CHIP_ERROR_INVALID_ARGUMENT); - VerifyOrReturnError(msg_length > 0, CHIP_ERROR_INVALID_ARGUMENT); - VerifyOrReturnError(out_signature != nullptr, CHIP_ERROR_INVALID_ARGUMENT); - VerifyOrReturnError(keyid != kKeyId_NotInitialized, CHIP_ERROR_HSM); - - ChipLogDetail(Crypto, "ECDSA_sign_msg: Using SE05X for Ecc Sign!"); - - se05x_sessionOpen(); - VerifyOrReturnError(gex_sss_chip_ctx.ks.session != NULL, CHIP_ERROR_INTERNAL); - - status = sss_digest_context_init(&digest_ctx, &gex_sss_chip_ctx.session, kAlgorithm_SSS_SHA256, kMode_SSS_Digest); - VerifyOrExit(status == kStatus_SSS_Success, error = CHIP_ERROR_INTERNAL); - - if (msg_length <= MAX_SHA_ONE_SHOT_DATA_LEN) + if (CHIP_NO_ERROR != parse_se05x_keyid_from_keypair(mKeypair, &keyid)) { - status = sss_digest_one_go(&digest_ctx, msg, msg_length, hash, &hashLen); - VerifyOrExit(status == kStatus_SSS_Success, error = CHIP_ERROR_INTERNAL); + ChipLogDetail(Crypto, "ECDSA_sign_msg : Not ref key. Using host for ecdsa sign"); + return ECDSA_sign_msg_H(&mKeypair, msg, msg_length, out_signature); } - else - { - /* Calculate SHA using multistep calls */ - size_t datalenTemp = 0; - size_t rem_len = msg_length; - status = sss_digest_init(&digest_ctx); - VerifyOrExit(status == kStatus_SSS_Success, error = CHIP_ERROR_INTERNAL); + VerifyOrReturnError(msg != nullptr, CHIP_ERROR_INVALID_ARGUMENT); + VerifyOrReturnError(msg_length > 0, CHIP_ERROR_INVALID_ARGUMENT); - while (rem_len > 0) - { - datalenTemp = (rem_len > MAX_SHA_ONE_SHOT_DATA_LEN) ? MAX_SHA_ONE_SHOT_DATA_LEN : rem_len; - status = sss_digest_update(&digest_ctx, (msg + (msg_length - rem_len)), datalenTemp); - VerifyOrExit(status == kStatus_SSS_Success, error = CHIP_ERROR_INTERNAL); - rem_len = rem_len - datalenTemp; - } + ChipLogDetail(Crypto, "ECDSA_sign_msg: Using se05x for ecdsa sign!"); - status = sss_digest_finish(&digest_ctx, hash, &hashLen); - VerifyOrExit(status == kStatus_SSS_Success, error = CHIP_ERROR_INTERNAL); - } + error = Hash_SHA256(msg, msg_length, hash); + SuccessOrExit(error); + + VerifyOrReturnError(se05x_sessionOpen() == CHIP_NO_ERROR, CHIP_ERROR_INTERNAL); + VerifyOrReturnError(gex_sss_chip_ctx.ks.session != NULL, CHIP_ERROR_INTERNAL); status = sss_key_object_init(&keyObject, &gex_sss_chip_ctx.ks); VerifyOrExit(status == kStatus_SSS_Success, error = CHIP_ERROR_INTERNAL); @@ -190,7 +217,7 @@ CHIP_ERROR P256KeypairHSM::ECDSA_sign_msg(const uint8_t * msg, size_t msg_length error = EcdsaAsn1SignatureToRaw(kP256_FE_Length, ByteSpan{ signature_se05x, signature_se05x_len }, out_raw_sig_span); SuccessOrExit(error); - SuccessOrExit(error = out_signature.SetLength(2 * kP256_FE_Length)); + out_signature.SetLength(2 * kP256_FE_Length); error = CHIP_NO_ERROR; exit: @@ -198,37 +225,28 @@ CHIP_ERROR P256KeypairHSM::ECDSA_sign_msg(const uint8_t * msg, size_t msg_length { sss_asymmetric_context_free(&asymm_ctx); } - if (digest_ctx.session != nullptr) - { - sss_digest_context_free(&digest_ctx); - } return error; +#endif // ENABLE_SE05X_GENERATE_EC_KEY } -CHIP_ERROR P256KeypairHSM::Serialize(P256SerializedKeypair & output) const +CHIP_ERROR P256Keypair::Serialize(P256SerializedKeypair & output) const { const size_t len = output.Length() == 0 ? output.Capacity() : output.Length(); Encoding::BufferWriter bbuf(output.Bytes(), len); - uint8_t privkey[kP256_PrivateKey_Length] = { - 0, - }; + if (0 != memcmp(&mKeypair.mBytes[0], se05x_magic_no, sizeof(se05x_magic_no))) { - /* Set the public key */ - P256PublicKeyHSM & public_key = const_cast(Pubkey()); - bbuf.Put(Uint8::to_uchar(public_key), public_key.Length()); + VerifyOrReturnError(mInitialized, CHIP_ERROR_WELL_UNINITIALIZED); + return Serialize_H(mKeypair, mPublicKey, output); } - VerifyOrReturnError(bbuf.Available() == sizeof(privkey), CHIP_ERROR_INTERNAL); - VerifyOrReturnError(sizeof(privkey) >= 4, CHIP_ERROR_INTERNAL); + /* Set the public key */ + P256PublicKey & public_key = const_cast(Pubkey()); + bbuf.Put(Uint8::to_uchar(public_key), public_key.Length()); - { - /* When HSM is used for ECC key generation, store key info in private key buffer */ - Encoding::LittleEndian::BufferWriter privkey_bbuf(privkey, sizeof(privkey)); - privkey_bbuf.Put32(keyid); - } + /* Set the private key se05x_magic_no */ + bbuf.Put(mKeypair.mBytes, kP256_PrivateKey_Length); - bbuf.Put(privkey, sizeof(privkey)); VerifyOrReturnError(bbuf.Fit(), CHIP_ERROR_BUFFER_TOO_SMALL); output.SetLength(bbuf.Needed()); @@ -236,48 +254,122 @@ CHIP_ERROR P256KeypairHSM::Serialize(P256SerializedKeypair & output) const return CHIP_NO_ERROR; } -CHIP_ERROR P256KeypairHSM::Deserialize(P256SerializedKeypair & input) +CHIP_ERROR P256Keypair::Deserialize(P256SerializedKeypair & input) { + CHIP_ERROR error = CHIP_ERROR_INTERNAL; + const uint8_t * privkey; /* Set the public key */ - P256PublicKeyHSM & public_key = const_cast(Pubkey()); + P256PublicKey & public_key = const_cast(Pubkey()); Encoding::BufferWriter bbuf((uint8_t *) Uint8::to_const_uchar(public_key), public_key.Length()); VerifyOrReturnError(input.Length() == public_key.Length() + kP256_PrivateKey_Length, CHIP_ERROR_INVALID_ARGUMENT); - bbuf.Put(static_cast(input), public_key.Length()); - /* Set private key info */ - VerifyOrReturnError(bbuf.Fit(), CHIP_ERROR_NO_MEMORY); + privkey = input.ConstBytes() /*Uint8::to_const_uchar(input) */ + public_key.Length(); + + if (0 == memcmp(privkey, se05x_magic_no, sizeof(se05x_magic_no))) { - /* When HSM is used for ECC key generation, key info in stored in private key buffer */ - const uint8_t * privkey = input.ConstBytes() + public_key.Length(); - keyid = Encoding::LittleEndian::Get32(privkey); - public_key.SetPublicKeyId(keyid); + /* se05x_magic_no + KeyID is passed */ + ChipLogDetail(Crypto, "Deserialize: ref key found"); + bbuf.Put(input.Bytes(), public_key.Length()); + VerifyOrReturnError(bbuf.Fit(), CHIP_ERROR_NO_MEMORY); + + memcpy(&mKeypair.mBytes[0], se05x_magic_no, sizeof(se05x_magic_no)); + mKeypair.mBytes[8] = *(privkey + 8); + mKeypair.mBytes[9] = *(privkey + 9); + mKeypair.mBytes[10] = *(privkey + 10); + mKeypair.mBytes[11] = *(privkey + 11); + // ChipLogDetail(Crypto, "Parsed keyId = 0x%02X%02X%02X%02X", mKeypair.mBytes[8], mKeypair.mBytes[9], + // mKeypair.mBytes[10],mKeypair.mBytes[11]); + + mInitialized = true; + + return CHIP_NO_ERROR; + } + else + { +#if !ENABLE_SE05X_KEY_IMPORT + if (CHIP_NO_ERROR == (error = Deserialize_H(this, &mPublicKey, &mKeypair, input))) + { + mInitialized = true; + } + return error; +#else + + sss_object_t sss_object = { 0 }; + sss_status_t sss_status = kStatus_SSS_Fail; + uint32_t keyid = 0; + uint8_t keyid_buffer[4] = { 0 }; + uint8_t key[128] = { 0 }; + uint8_t header[] = EC_NIST_P256_KP_HEADER; + uint8_t pub_header[] = EC_NIST_P256_KP_PUB_HEADER; + size_t key_length = 0; + + memcpy(&key[key_length], header, sizeof(header)); + key_length += sizeof(header); + if ((privkey[0] & 0x80)) + { + key[key_length++] = 0x00; + } + memcpy(&key[key_length], privkey, kP256_PrivateKey_Length); + key_length += kP256_PrivateKey_Length; + memcpy(&key[key_length], pub_header, sizeof(pub_header)); + key_length += sizeof(pub_header); + memcpy(&key[key_length], input.ConstBytes(), public_key.Length()); + key_length += public_key.Length(); + + error = DRBG_get_bytes(keyid_buffer, sizeof(keyid_buffer)); + VerifyOrReturnError(error == CHIP_NO_ERROR, error); + + keyid = (keyid_buffer[3] << (8 * 3)) + (keyid_buffer[2] << (8 * 2)) + (keyid_buffer[1] << (8 * 1)) + + (keyid_buffer[0] << (8 * 0)); + + sss_status = sss_key_object_init(&sss_object, &gex_sss_chip_ctx.ks); + VerifyOrReturnError(sss_status == kStatus_SSS_Success, CHIP_ERROR_INTERNAL); + sss_status = sss_key_object_allocate_handle(&sss_object, keyid, kSSS_KeyPart_Pair, kSSS_CipherType_EC_NIST_P, 256, + kKeyObject_Mode_Persistent); + VerifyOrReturnError(sss_status == kStatus_SSS_Success, CHIP_ERROR_INTERNAL); + sss_status = sss_key_store_set_key(&gex_sss_chip_ctx.ks, &sss_object, key, key_length, 256, NULL, 0); + VerifyOrReturnError(sss_status == kStatus_SSS_Success, CHIP_ERROR_INTERNAL); + + return CHIP_NO_ERROR; +#endif } - - return CHIP_NO_ERROR; } -CHIP_ERROR P256KeypairHSM::ECDH_derive_secret(const P256PublicKey & remote_public_key, P256ECDHDerivedSecret & out_secret) const +CHIP_ERROR P256Keypair::ECDH_derive_secret(const P256PublicKey & remote_public_key, P256ECDHDerivedSecret & out_secret) const { + VerifyOrReturnError(mInitialized, CHIP_ERROR_WELL_UNINITIALIZED); + +#if !ENABLE_SE05X_GENERATE_EC_KEY + return ECDH_derive_secret_H(&mKeypair, remote_public_key, out_secret); +#else size_t secret_length = (out_secret.Length() == 0) ? out_secret.Capacity() : out_secret.Length(); + uint32_t keyid = 0; - VerifyOrReturnError(keyid != kKeyId_NotInitialized, CHIP_ERROR_HSM); + if (CHIP_NO_ERROR != parse_se05x_keyid_from_keypair(mKeypair, &keyid)) + { + ChipLogDetail(Crypto, "ECDH_derive_secret : Not ref key. Using host for ecdh"); + return ECDH_derive_secret_H(&mKeypair, remote_public_key, out_secret); + } - ChipLogDetail(Crypto, "ECDH_derive_secret: Using SE05X for ECDH !"); + ChipLogDetail(Crypto, "ECDH_derive_secret : Using se05x for ecdh"); - se05x_sessionOpen(); + VerifyOrReturnError(se05x_sessionOpen() == CHIP_NO_ERROR, CHIP_ERROR_INTERNAL); VerifyOrReturnError(gex_sss_chip_ctx.ks.session != NULL, CHIP_ERROR_INTERNAL); const uint8_t * const rem_pubKey = Uint8::to_const_uchar(remote_public_key); - const size_t rem_pubKeyLen = remote_public_key.Length(); + const size_t rem_pubKeyLen = remote_public_key.Length(); VerifyOrReturnError(gex_sss_chip_ctx.ks.session != nullptr, CHIP_ERROR_INTERNAL); - const smStatus_t smstatus = Se05x_API_ECGenSharedSecret(&((sss_se05x_session_t *) &gex_sss_chip_ctx.session)->s_ctx, keyid, - rem_pubKey, rem_pubKeyLen, out_secret.Bytes(), &secret_length); + const smStatus_t smstatus = + Se05x_API_ECGenSharedSecret(&((sss_se05x_session_t *) &gex_sss_chip_ctx.session)->s_ctx, keyid, rem_pubKey, rem_pubKeyLen, + out_secret.Bytes() /*Uint8::to_uchar(out_secret)*/, &secret_length); VerifyOrReturnError(smstatus == SM_OK, CHIP_ERROR_INTERNAL); return out_secret.SetLength(secret_length); + +#endif // ENABLE_SE05X_GENERATE_EC_KEY } /* EC Public key HSM implementation */ @@ -293,8 +385,9 @@ CHIP_ERROR SE05X_Set_ECDSA_Public_Key(sss_object_t * keyObject, const uint8_t * const uint8_t nist256_header[] = { 0x30, 0x59, 0x30, 0x13, 0x06, 0x07, 0x2A, 0x86, 0x48, 0xCE, 0x3D, 0x02, 0x01, 0x06, 0x08, 0x2A, 0x86, 0x48, 0xCE, 0x3D, 0x03, 0x01, 0x07, 0x03, 0x42, 0x00 }; - se05x_sessionOpen(); + VerifyOrReturnError(se05x_sessionOpen() == CHIP_NO_ERROR, CHIP_ERROR_INTERNAL); VerifyOrReturnError(gex_sss_chip_ctx.ks.session != NULL, CHIP_ERROR_INTERNAL); + /* Set public key */ sss_status_t status = sss_key_object_init(keyObject, &gex_sss_chip_ctx.ks); VerifyOrReturnError(status == kStatus_SSS_Success, CHIP_ERROR_INTERNAL); @@ -316,74 +409,37 @@ CHIP_ERROR SE05X_Set_ECDSA_Public_Key(sss_object_t * keyObject, const uint8_t * return CHIP_NO_ERROR; } -CHIP_ERROR P256PublicKeyHSM::ECDSA_validate_msg_signature(const uint8_t * msg, size_t msg_length, - const P256ECDSASignature & signature) const +CHIP_ERROR P256PublicKey::ECDSA_validate_msg_signature(const uint8_t * msg, size_t msg_length, + const P256ECDSASignature & signature) const { - CHIP_ERROR error = CHIP_ERROR_INTERNAL; - sss_status_t status = kStatus_SSS_Success; +#if !ENABLE_SE05X_ECDSA_VERIFY + return ECDSA_validate_msg_signature_H(this, msg, msg_length, signature); +#else + CHIP_ERROR error = CHIP_ERROR_INTERNAL; + sss_status_t status = kStatus_SSS_Success; sss_asymmetric_t asymm_ctx = { 0 }; - sss_digest_t ctx_digest = { 0 }; - uint8_t hash[32] = { + uint8_t hash[32] = { 0, }; - size_t hash_length = sizeof(hash); - sss_object_t keyObject = { 0 }; + size_t hash_length = sizeof(hash); + sss_object_t keyObject = { 0 }; uint8_t signature_se05x[kMax_ECDSA_Signature_Length_Der] = { 0 }; - size_t signature_se05x_len = sizeof(signature_se05x); + size_t signature_se05x_len = sizeof(signature_se05x); MutableByteSpan out_der_sig_span(signature_se05x, signature_se05x_len); VerifyOrReturnError(msg != nullptr, CHIP_ERROR_INVALID_ARGUMENT); VerifyOrReturnError(msg_length > 0, CHIP_ERROR_INVALID_ARGUMENT); - ChipLogDetail(Crypto, "ECDSA_validate_msg_signature: Using SE05X for ECDSA verify (msg) !"); + ChipLogDetail(Crypto, "ECDSA_validate_msg_signature: Using se05x for ECDSA verify (msg) !"); - se05x_sessionOpen(); + VerifyOrReturnError(se05x_sessionOpen() == CHIP_NO_ERROR, CHIP_ERROR_INTERNAL); VerifyOrReturnError(gex_sss_chip_ctx.ks.session != NULL, CHIP_ERROR_INTERNAL); - /* Create hash of input data */ - status = sss_digest_context_init(&ctx_digest, &gex_sss_chip_ctx.session, kAlgorithm_SSS_SHA256, kMode_SSS_Digest); - VerifyOrExit(status == kStatus_SSS_Success, error = CHIP_ERROR_INTERNAL); - - if (msg_length <= MAX_SHA_ONE_SHOT_DATA_LEN) - { - status = sss_digest_one_go(&ctx_digest, msg, msg_length, hash, &hash_length); - VerifyOrExit(status == kStatus_SSS_Success, error = CHIP_ERROR_INTERNAL); - } - else - { - /* Calculate SHA using multistep calls */ - size_t datalenTemp = 0; - size_t rem_len = msg_length; - - status = sss_digest_init(&ctx_digest); - VerifyOrExit(status == kStatus_SSS_Success, error = CHIP_ERROR_INTERNAL); - - while (rem_len > 0) - { - datalenTemp = (rem_len > MAX_SHA_ONE_SHOT_DATA_LEN) ? MAX_SHA_ONE_SHOT_DATA_LEN : rem_len; - status = sss_digest_update(&ctx_digest, (msg + (msg_length - rem_len)), datalenTemp); - VerifyOrExit(status == kStatus_SSS_Success, error = CHIP_ERROR_INTERNAL); - rem_len = rem_len - datalenTemp; - } - - status = sss_digest_finish(&ctx_digest, hash, &hash_length); - VerifyOrExit(status == kStatus_SSS_Success, error = CHIP_ERROR_INTERNAL); - } - - if (PublicKeyid == kKeyId_NotInitialized) - { - error = SE05X_Set_ECDSA_Public_Key(&keyObject, bytes, kP256_PublicKey_Length); - SuccessOrExit(error); - error = CHIP_ERROR_INTERNAL; - } - else - { - status = sss_key_object_init(&keyObject, &gex_sss_chip_ctx.ks); - VerifyOrExit(status == kStatus_SSS_Success, error = CHIP_ERROR_INTERNAL); + error = Hash_SHA256(msg, msg_length, hash); + SuccessOrExit(error); - status = sss_key_object_get_handle(&keyObject, PublicKeyid); - VerifyOrExit(status == kStatus_SSS_Success, error = CHIP_ERROR_INTERNAL); - } + error = SE05X_Set_ECDSA_Public_Key(&keyObject, bytes, kP256_PublicKey_Length); + SuccessOrExit(error); /* ECC Verify */ status = @@ -406,52 +462,40 @@ CHIP_ERROR P256PublicKeyHSM::ECDSA_validate_msg_signature(const uint8_t * msg, s sss_asymmetric_context_free(&asymm_ctx); } - if (ctx_digest.session != NULL) - { - sss_digest_context_free(&ctx_digest); - } - - if (PublicKeyid == kKeyId_NotInitialized) + if (keyObject.keyStore->session != NULL) { sss_key_store_erase_key(&gex_sss_chip_ctx.ks, &keyObject); } return error; + +#endif // ENABLE_SE05X_ECDSA_VERIFY } -CHIP_ERROR P256PublicKeyHSM::ECDSA_validate_hash_signature(const uint8_t * hash, size_t hash_length, - const P256ECDSASignature & signature) const +CHIP_ERROR P256PublicKey::ECDSA_validate_hash_signature(const uint8_t * hash, size_t hash_length, + const P256ECDSASignature & signature) const { - CHIP_ERROR error = CHIP_ERROR_INTERNAL; - sss_status_t status = kStatus_SSS_Success; - sss_asymmetric_t asymm_ctx = { 0 }; - sss_object_t keyObject = { 0 }; +#if !ENABLE_SE05X_ECDSA_VERIFY + return ECDSA_validate_hash_signature_H(this, hash, hash_length, signature); +#else + CHIP_ERROR error = CHIP_ERROR_INTERNAL; + sss_status_t status = kStatus_SSS_Success; + sss_asymmetric_t asymm_ctx = { 0 }; + sss_object_t keyObject = { 0 }; uint8_t signature_se05x[kMax_ECDSA_Signature_Length_Der] = { 0 }; - size_t signature_se05x_len = sizeof(signature_se05x); + size_t signature_se05x_len = sizeof(signature_se05x); MutableByteSpan out_der_sig_span(signature_se05x, signature_se05x_len); VerifyOrReturnError(hash != nullptr, CHIP_ERROR_INVALID_ARGUMENT); VerifyOrReturnError(hash_length > 0, CHIP_ERROR_INVALID_ARGUMENT); - ChipLogDetail(Crypto, "ECDSA_validate_hash_signature: Using SE05X for ECDSA verify (hash) !"); + ChipLogDetail(Crypto, "ECDSA_validate_msg_signature: Using se05x for ECDSA verify (hash) !"); - se05x_sessionOpen(); + VerifyOrReturnError(se05x_sessionOpen() == CHIP_NO_ERROR, CHIP_ERROR_INTERNAL); VerifyOrReturnError(gex_sss_chip_ctx.ks.session != NULL, CHIP_ERROR_INTERNAL); - if (PublicKeyid == kKeyId_NotInitialized) - { - error = SE05X_Set_ECDSA_Public_Key(&keyObject, bytes, kP256_PublicKey_Length); - SuccessOrExit(error); - error = CHIP_ERROR_INTERNAL; - } - else - { - status = sss_key_object_init(&keyObject, &gex_sss_chip_ctx.ks); - VerifyOrExit(status == kStatus_SSS_Success, error = CHIP_ERROR_INTERNAL); - - status = sss_key_object_get_handle(&keyObject, PublicKeyid); - VerifyOrExit(status == kStatus_SSS_Success, error = CHIP_ERROR_INTERNAL); - } + error = SE05X_Set_ECDSA_Public_Key(&keyObject, bytes, kP256_PublicKey_Length); + SuccessOrExit(error); /* ECC Verify */ status = @@ -475,15 +519,17 @@ CHIP_ERROR P256PublicKeyHSM::ECDSA_validate_hash_signature(const uint8_t * hash, sss_asymmetric_context_free(&asymm_ctx); } - if (PublicKeyid == kKeyId_NotInitialized) + if (keyObject.keyStore->session != NULL) { sss_key_store_erase_key(&gex_sss_chip_ctx.ks, &keyObject); } return error; + +#endif // ENABLE_SE05X_ECDSA_VERIFY } -static void add_tlv(uint8_t * buf, size_t buf_index, uint8_t tag, size_t len, uint8_t * val) +void add_tlv(uint8_t * buf, size_t buf_index, uint8_t tag, size_t len, uint8_t * val) { buf[buf_index++] = (uint8_t) tag; buf[buf_index++] = (uint8_t) len; @@ -526,35 +572,46 @@ static void add_tlv(uint8_t * buf, size_t buf_index, uint8_t tag, size_t len, ui * */ -CHIP_ERROR P256KeypairHSM::NewCertificateSigningRequest(uint8_t * csr, size_t & csr_length) const +CHIP_ERROR P256Keypair::NewCertificateSigningRequest(uint8_t * csr, size_t & csr_length) const { - CHIP_ERROR error = CHIP_ERROR_INTERNAL; - sss_status_t status = kStatus_SSS_Success; +#if !ENABLE_SE05X_GENERATE_EC_KEY + return NewCertificateSigningRequest_H(&mKeypair, csr, csr_length); +#else + CHIP_ERROR error = CHIP_ERROR_INTERNAL; + sss_status_t status = kStatus_SSS_Success; sss_asymmetric_t asymm_ctx = { 0 }; - sss_object_t keyObject = { 0 }; - sss_digest_t digest_ctx = { 0 }; + sss_object_t keyObject = { 0 }; + uint32_t keyid = 0; uint8_t data_to_hash[128] = { 0 }; - size_t data_to_hash_len = sizeof(data_to_hash); - uint8_t pubkey[128] = { 0 }; - size_t pubKeyLen = 0; - uint8_t hash[32] = { 0 }; - size_t hash_length = sizeof(hash); - uint8_t signature[128] = { 0 }; - size_t signature_len = sizeof(signature); - - size_t csr_index = 0; + size_t data_to_hash_len = sizeof(data_to_hash); + uint8_t pubkey[128] = { 0 }; + size_t pubKeyLen = 0; + uint8_t hash[32] = { 0 }; + size_t hash_length = sizeof(hash); + uint8_t signature[128] = { 0 }; + size_t signature_len = sizeof(signature); + + size_t csr_index = 0; size_t buffer_index = data_to_hash_len; uint8_t organisation_oid[3] = { 0x55, 0x04, 0x0a }; // Version ::= INTEGER { v1(0), v2(1), v3(2) } - uint8_t version[3] = { 0x02, 0x01, 0x00 }; + uint8_t version[3] = { 0x02, 0x01, 0x00 }; uint8_t signature_oid[8] = { 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x04, 0x03, 0x02 }; uint8_t nist256_header[] = { 0x30, 0x59, 0x30, 0x13, 0x06, 0x07, 0x2A, 0x86, 0x48, 0xCE, 0x3D, 0x02, 0x01, 0x06, 0x08, 0x2A, 0x86, 0x48, 0xCE, 0x3D, 0x03, 0x01, 0x07, 0x03, 0x42, 0x00 }; - ChipLogDetail(Crypto, "NewCertificateSigningRequest: Using SE05X for creating CSR !"); + VerifyOrReturnError(mInitialized, CHIP_ERROR_WELL_UNINITIALIZED); + + if (CHIP_NO_ERROR != parse_se05x_keyid_from_keypair(mKeypair, &keyid)) + { + ChipLogDetail(Crypto, "NewCertificateSigningRequest : Not ref key. Using host for CSR"); + return NewCertificateSigningRequest_H(&mKeypair, csr, csr_length); + } + + ChipLogDetail(Crypto, "NewCertificateSigningRequest : Using se05x for CSR"); // No extensions are copied buffer_index -= kTlvHeader; @@ -562,7 +619,7 @@ CHIP_ERROR P256KeypairHSM::NewCertificateSigningRequest(uint8_t * csr, size_t & // Copy public key (with header) { - P256PublicKeyHSM & public_key = const_cast(Pubkey()); + P256PublicKey & public_key = const_cast(Pubkey()); VerifyOrExit((sizeof(nist256_header) + public_key.Length()) <= sizeof(pubkey), error = CHIP_ERROR_INTERNAL); @@ -616,12 +673,8 @@ CHIP_ERROR P256KeypairHSM::NewCertificateSigningRequest(uint8_t * csr, size_t & data_to_hash_len = (data_to_hash_len - buffer_index); memmove(data_to_hash, (data_to_hash + buffer_index), data_to_hash_len); - /* Create hash of `data_to_hash` buffer */ - status = sss_digest_context_init(&digest_ctx, &gex_sss_chip_ctx.session, kAlgorithm_SSS_SHA256, kMode_SSS_Digest); - VerifyOrExit(status == kStatus_SSS_Success, error = CHIP_ERROR_INTERNAL); - - status = sss_digest_one_go(&digest_ctx, data_to_hash, data_to_hash_len, hash, &hash_length); - VerifyOrExit(status == kStatus_SSS_Success, error = CHIP_ERROR_INTERNAL); + error = Hash_SHA256(data_to_hash, data_to_hash_len, hash); + SuccessOrExit(error); // Sign on hash status = sss_key_object_init(&keyObject, &gex_sss_chip_ctx.ks); @@ -685,15 +738,10 @@ CHIP_ERROR P256KeypairHSM::NewCertificateSigningRequest(uint8_t * csr, size_t & sss_asymmetric_context_free(&asymm_ctx); } - if (digest_ctx.session != NULL) - { - sss_digest_context_free(&digest_ctx); - } - return error; + +#endif // ENABLE_SE05X_GENERATE_EC_KEY } } // namespace Crypto } // namespace chip - -#endif //#if ENABLE_HSM_GENERATE_EC_KEY diff --git a/src/crypto/hsm/nxp/CHIPCryptoPALHsm_SE05X_PBKDF.cpp b/src/platform/nxp/crypto/se05x/CHIPCryptoPALHsm_se05x_pbkdf.cpp similarity index 78% rename from src/crypto/hsm/nxp/CHIPCryptoPALHsm_SE05X_PBKDF.cpp rename to src/platform/nxp/crypto/se05x/CHIPCryptoPALHsm_se05x_pbkdf.cpp index 9fe746bc1718d7..5de2a9e135a5cb 100644 --- a/src/crypto/hsm/nxp/CHIPCryptoPALHsm_SE05X_PBKDF.cpp +++ b/src/platform/nxp/crypto/se05x/CHIPCryptoPALHsm_se05x_pbkdf.cpp @@ -22,23 +22,21 @@ * chip crypto apis use either HSM or rollback to software implementation. */ -#include "CHIPCryptoPALHsm_SE05X_utils.h" +#include "CHIPCryptoPALHsm_se05x_utils.h" #include -#if ENABLE_HSM_PBKDF2_SHA256 - namespace chip { namespace Crypto { -PBKDF2_sha256HSM::PBKDF2_sha256HSM() -{ - keyid = kKeyId_pbkdf2_sha256_hmac_keyid; -} -PBKDF2_sha256HSM::~PBKDF2_sha256HSM() {} +extern CHIP_ERROR pbkdf2_sha256_h(const uint8_t * password, size_t plen, const uint8_t * salt, size_t slen, + unsigned int iteration_count, uint32_t key_length, uint8_t * output); -CHIP_ERROR PBKDF2_sha256HSM::pbkdf2_sha256(const uint8_t * password, size_t plen, const uint8_t * salt, size_t slen, - unsigned int iteration_count, uint32_t key_length, uint8_t * output) +CHIP_ERROR PBKDF2_sha256::pbkdf2_sha256(const uint8_t * password, size_t plen, const uint8_t * salt, size_t slen, + unsigned int iteration_count, uint32_t key_length, uint8_t * output) { +#if !ENABLE_SE05X_PBKDF2_SHA256 + return pbkdf2_sha256_h(password, plen, salt, slen, iteration_count, key_length, output); +#else CHIP_ERROR error = CHIP_ERROR_INTERNAL; VerifyOrReturnError(password != nullptr, CHIP_ERROR_INVALID_ARGUMENT); VerifyOrReturnError(plen > 0, CHIP_ERROR_INVALID_ARGUMENT); @@ -48,9 +46,9 @@ CHIP_ERROR PBKDF2_sha256HSM::pbkdf2_sha256(const uint8_t * password, size_t plen VerifyOrReturnError(slen <= kSpake2p_Max_PBKDF_Salt_Length, CHIP_ERROR_INVALID_ARGUMENT); VerifyOrReturnError(salt != nullptr, CHIP_ERROR_INVALID_ARGUMENT); - VerifyOrReturnError(keyid != kKeyId_NotInitialized, CHIP_ERROR_HSM); + const uint32_t keyid = kKeyId_pbkdf2_sha256_hmac_keyid; - ChipLogDetail(Crypto, "Using se05x for pbkdf2 sha256"); + ChipLogDetail(Crypto, "pbkdf2_sha256 : Using se05x for pbkdf2_sha256"); static sss_policy_u commonPol; commonPol.type = KPolicy_Common; @@ -72,7 +70,7 @@ CHIP_ERROR PBKDF2_sha256HSM::pbkdf2_sha256(const uint8_t * password, size_t plen policy_for_hmac_key.policies[0] = &hmac_withPol; policy_for_hmac_key.policies[1] = &commonPol; - se05x_sessionOpen(); + VerifyOrReturnError(se05x_sessionOpen() == CHIP_NO_ERROR, CHIP_ERROR_INTERNAL); VerifyOrReturnError(gex_sss_chip_ctx.ks.session != NULL, CHIP_ERROR_INTERNAL); sss_object_t hmacKeyObj = { @@ -94,13 +92,18 @@ CHIP_ERROR PBKDF2_sha256HSM::pbkdf2_sha256(const uint8_t * password, size_t plen (uint16_t) iteration_count, kSE05x_MACAlgo_HMAC_SHA256, (uint16_t) key_length, 0, /* derivedSessionKeyID */ output, (size_t *) &key_length); VerifyOrExit(smStatus == SM_OK, error = CHIP_ERROR_INTERNAL); + error = CHIP_NO_ERROR; exit: - sss_key_store_erase_key(&gex_sss_chip_ctx.ks, &hmacKeyObj); + if (hmacKeyObj.keyStore->session != NULL) + { + sss_key_store_erase_key(&gex_sss_chip_ctx.ks, &hmacKeyObj); + } + return error; + +#endif // ENABLE_SE05X_PBKDF2_SHA256 } } // namespace Crypto } // namespace chip - -#endif //#if ENABLE_HSM_PBKDF2_SHA256 diff --git a/src/platform/nxp/crypto/se05x/CHIPCryptoPALHsm_se05x_rng.cpp b/src/platform/nxp/crypto/se05x/CHIPCryptoPALHsm_se05x_rng.cpp new file mode 100644 index 00000000000000..adcfea10644d04 --- /dev/null +++ b/src/platform/nxp/crypto/se05x/CHIPCryptoPALHsm_se05x_rng.cpp @@ -0,0 +1,54 @@ +/* + * + * Copyright (c) 2021 Project CHIP Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/** + * @file + * HSM based implementation of CHIP crypto primitives + * Based on configurations in CHIPCryptoPALHsm_config.h file, + * chip crypto apis use either HSM or rollback to software implementation. + */ + +#include "CHIPCryptoPALHsm_se05x_utils.h" +#include + +namespace chip { +namespace Crypto { + +CHIP_ERROR DRBG_get_bytes(uint8_t * out_buffer, const size_t out_length) +{ + // TODO - Add rollback + sss_status_t status; + sss_rng_context_t ctx_rng = { 0 }; + + VerifyOrReturnError(out_buffer != nullptr, CHIP_ERROR_INVALID_ARGUMENT); + VerifyOrReturnError(out_length > 0, CHIP_ERROR_INVALID_ARGUMENT); + + VerifyOrReturnError(se05x_sessionOpen() == CHIP_NO_ERROR, CHIP_ERROR_INTERNAL); + + status = sss_rng_context_init(&ctx_rng, &gex_sss_chip_ctx.session /* Session */); + VerifyOrReturnError(status == kStatus_SSS_Success, CHIP_ERROR_INTERNAL); + + status = sss_rng_get_random(&ctx_rng, out_buffer, out_length); + VerifyOrReturnError(status == kStatus_SSS_Success, CHIP_ERROR_INTERNAL); + + sss_rng_context_free(&ctx_rng); + + return CHIP_NO_ERROR; +} + +} // namespace Crypto +} // namespace chip diff --git a/src/crypto/hsm/nxp/CHIPCryptoPALHsm_SE05X_Spake2p.cpp b/src/platform/nxp/crypto/se05x/CHIPCryptoPALHsm_se05x_spake2p.cpp similarity index 95% rename from src/crypto/hsm/nxp/CHIPCryptoPALHsm_SE05X_Spake2p.cpp rename to src/platform/nxp/crypto/se05x/CHIPCryptoPALHsm_se05x_spake2p.cpp index 48c7b021ef3e96..a60209f065aade 100644 --- a/src/crypto/hsm/nxp/CHIPCryptoPALHsm_SE05X_Spake2p.cpp +++ b/src/platform/nxp/crypto/se05x/CHIPCryptoPALHsm_se05x_spake2p.cpp @@ -22,16 +22,16 @@ * chip crypto apis use either HSM or rollback to software implementation. */ -#include "CHIPCryptoPALHsm_SE05X_utils.h" +#include "CHIPCryptoPALHsm_se05x_utils.h" -#if ((ENABLE_HSM_SPAKE_VERIFIER) || (ENABLE_HSM_SPAKE_PROVER)) +#if ((ENABLE_SE05X_SPAKE_VERIFIER) || (ENABLE_SE05X_SPAKE_PROVER)) -#if ENABLE_HSM_SPAKE_VERIFIER +#if ENABLE_SE05X_SPAKE_VERIFIER const uint32_t w0in_id_v = 0x7D200001; const uint32_t Lin_id_v = 0x7D200002; #endif -#if ENABLE_HSM_SPAKE_PROVER +#if ENABLE_SE05X_SPAKE_PROVER const uint32_t w0in_id_p = 0x7D200003; const uint32_t w1in_id_p = 0x7D200004; #endif @@ -42,7 +42,7 @@ void Spake2p_Finish_HSM(hsm_pake_context_t * phsm_pake_context) if (gex_sss_chip_ctx.ks.session != NULL) { Se05x_API_DeleteCryptoObject(&((sss_se05x_session_t *) &gex_sss_chip_ctx.session)->s_ctx, phsm_pake_context->spake_objId); - setObjID(phsm_pake_context->spake_objId, OBJ_ID_TABLE_OBJID_STATUS_FREE); + se05x_setCryptoObjID(phsm_pake_context->spake_objId, OBJ_ID_TABLE_OBJID_STATUS_FREE); if (spake_objects_created > 0) { @@ -59,7 +59,7 @@ CHIP_ERROR create_init_crypto_obj(chip::Crypto::CHIP_SPAKE2P_ROLE role, hsm_pake SE05x_CryptoModeSubType_t subtype; #if ENABLE_REENTRANCY - SE05x_CryptoObjectID_t spakeObjectId = getObjID(); + SE05x_CryptoObjectID_t spakeObjectId = se05x_getCryptoObjID(); #else SE05x_CryptoObjectID_t spakeObjectId = (role == chip::Crypto::CHIP_SPAKE2P_ROLE::VERIFIER) ? kSE05x_CryptoObject_PAKE_TYPE_B : kSE05x_CryptoObject_PAKE_TYPE_A; @@ -82,7 +82,7 @@ CHIP_ERROR create_init_crypto_obj(chip::Crypto::CHIP_SPAKE2P_ROLE role, hsm_pake return CHIP_ERROR_INTERNAL; } - se05x_sessionOpen(); + VerifyOrReturnError(se05x_sessionOpen() == CHIP_NO_ERROR, CHIP_ERROR_INTERNAL); VerifyOrReturnError(gex_sss_chip_ctx.ks.session != NULL, CHIP_ERROR_INTERNAL); subtype.pakeMode = kSE05x_SPAKE2PLUS_P256_SHA256_HKDF_HMAC; @@ -200,8 +200,8 @@ CHIP_ERROR Spake2pHSM_P256_SHA256_HKDF_HMAC::Init(const uint8_t * context, size_ static uint8_t alreadyInitialised = 0; if (alreadyInitialised == false) { - delete_crypto_objects(); - init_cryptoObj_mutex(); + se05x_delete_crypto_objects(); + se05x_init_cryptoObj_mutex(); alreadyInitialised = true; } #endif //#if ENABLE_REENTRANCY @@ -227,7 +227,7 @@ CHIP_ERROR Spake2pHSM_P256_SHA256_HKDF_HMAC::Init(const uint8_t * context, size_ return error; } -#if ENABLE_HSM_SPAKE_VERIFIER +#if ENABLE_SE05X_SPAKE_VERIFIER CHIP_ERROR Spake2pHSM_P256_SHA256_HKDF_HMAC::BeginVerifier(const uint8_t * my_identity, size_t my_identity_len, const uint8_t * peer_identity, size_t peer_identity_len, const uint8_t * w0in, size_t w0in_len, const uint8_t * Lin, @@ -280,7 +280,7 @@ CHIP_ERROR Spake2pHSM_P256_SHA256_HKDF_HMAC::BeginVerifier(const uint8_t * my_id } #endif -#if ENABLE_HSM_SPAKE_PROVER +#if ENABLE_SE05X_SPAKE_PROVER CHIP_ERROR Spake2pHSM_P256_SHA256_HKDF_HMAC::BeginProver(const uint8_t * my_identity, size_t my_identity_len, const uint8_t * peer_identity, size_t peer_identity_len, const uint8_t * w0in, size_t w0in_len, const uint8_t * w1in, @@ -345,13 +345,13 @@ CHIP_ERROR Spake2pHSM_P256_SHA256_HKDF_HMAC::ComputeRoundOne(const uint8_t * pab VerifyOrReturnError(state == CHIP_SPAKE2P_STATE::STARTED, CHIP_ERROR_INTERNAL); VerifyOrReturnError(*out_len >= point_size, CHIP_ERROR_INTERNAL); -#if !ENABLE_HSM_SPAKE_VERIFIER +#if !ENABLE_SE05X_SPAKE_VERIFIER const bool sw_rollback_verifier = (role == chip::Crypto::CHIP_SPAKE2P_ROLE::VERIFIER); #else constexpr bool sw_rollback_verifier = false; #endif -#if ((CHIP_CRYPTO_HSM) && (!ENABLE_HSM_SPAKE_PROVER)) +#if ((CHIP_CRYPTO_HSM) && (!ENABLE_SE05X_SPAKE_PROVER)) const bool sw_rollback_prover = (role == chip::Crypto::CHIP_SPAKE2P_ROLE::PROVER); #else constexpr bool sw_rollback_prover = false; @@ -376,13 +376,13 @@ CHIP_ERROR Spake2pHSM_P256_SHA256_HKDF_HMAC::ComputeRoundTwo(const uint8_t * in, VerifyOrReturnError(state == CHIP_SPAKE2P_STATE::R1, CHIP_ERROR_INTERNAL); VerifyOrReturnError(in_len == point_size, CHIP_ERROR_INTERNAL); -#if !ENABLE_HSM_SPAKE_VERIFIER +#if !ENABLE_SE05X_SPAKE_VERIFIER const bool sw_rollback_verifier = (role == chip::Crypto::CHIP_SPAKE2P_ROLE::VERIFIER); #else constexpr bool sw_rollback_verifier = false; #endif -#if !ENABLE_HSM_SPAKE_PROVER +#if !ENABLE_SE05X_SPAKE_PROVER const bool sw_rollback_prover = (role == chip::Crypto::CHIP_SPAKE2P_ROLE::PROVER); #else constexpr bool sw_rollback_prover = false; @@ -411,13 +411,13 @@ CHIP_ERROR Spake2pHSM_P256_SHA256_HKDF_HMAC::KeyConfirm(const uint8_t * in, size { VerifyOrReturnError(state == CHIP_SPAKE2P_STATE::R2, CHIP_ERROR_INTERNAL); -#if !ENABLE_HSM_SPAKE_VERIFIER +#if !ENABLE_SE05X_SPAKE_VERIFIER const bool sw_rollback_verifier = (role == chip::Crypto::CHIP_SPAKE2P_ROLE::VERIFIER); #else constexpr bool sw_rollback_verifier = false; #endif -#if !ENABLE_HSM_SPAKE_PROVER +#if !ENABLE_SE05X_SPAKE_PROVER const bool sw_rollback_prover = (role == chip::Crypto::CHIP_SPAKE2P_ROLE::PROVER); #else constexpr bool sw_rollback_prover = false; @@ -441,4 +441,4 @@ CHIP_ERROR Spake2pHSM_P256_SHA256_HKDF_HMAC::KeyConfirm(const uint8_t * in, size } // namespace Crypto } // namespace chip -#endif //#if ((ENABLE_HSM_SPAKE_VERIFIER) || (ENABLE_HSM_SPAKE_PROVER)) +#endif //#if ((ENABLE_SE05X_SPAKE_VERIFIER) || (ENABLE_SE05X_SPAKE_PROVER)) diff --git a/src/crypto/hsm/nxp/CHIPCryptoPALHsm_SE05X_utils.cpp b/src/platform/nxp/crypto/se05x/CHIPCryptoPALHsm_se05x_utils.cpp similarity index 90% rename from src/crypto/hsm/nxp/CHIPCryptoPALHsm_SE05X_utils.cpp rename to src/platform/nxp/crypto/se05x/CHIPCryptoPALHsm_se05x_utils.cpp index 2545ecf5a657c1..ed5edc566b6cb9 100644 --- a/src/crypto/hsm/nxp/CHIPCryptoPALHsm_SE05X_utils.cpp +++ b/src/platform/nxp/crypto/se05x/CHIPCryptoPALHsm_se05x_utils.cpp @@ -22,7 +22,7 @@ * chip crypto apis use either HSM or rollback to software implementation. */ -#include "CHIPCryptoPALHsm_SE05X_utils.h" +#include "CHIPCryptoPALHsm_se05x_utils.h" #include "fsl_sss_policy.h" ex_sss_boot_ctx_t gex_sss_chip_ctx; @@ -76,39 +76,40 @@ static Mutex sSEObjMutex; #endif //#if ENABLE_REENTRANCY /* Open session to se05x */ -void se05x_sessionOpen(void) +CHIP_ERROR se05x_sessionOpen(void) { static int is_session_open = 0; if (is_session_open) { - return; + return CHIP_NO_ERROR; } memset(&gex_sss_chip_ctx, 0, sizeof(gex_sss_chip_ctx)); - const char * portName = nullptr; - sss_status_t status = ex_sss_boot_connectstring(0, NULL, &portName); + char * portName = nullptr; + sss_status_t status = ex_sss_boot_connectstring(0, NULL, &portName); if (kStatus_SSS_Success != status) { - ChipLogError(Crypto, "se05x error: %s\n", "ex_sss_boot_connectstring failed"); - return; + ChipLogError(Crypto, "se05x error: ex_sss_boot_connectstring failed"); + return CHIP_ERROR_INTERNAL; } status = ex_sss_boot_open(&gex_sss_chip_ctx, portName); if (kStatus_SSS_Success != status) { - ChipLogError(Crypto, "se05x error: %s\n", "ex_sss_boot_open failed"); - return; + ChipLogError(Crypto, "se05x error: ex_sss_boot_open failed"); + return CHIP_ERROR_INTERNAL; } status = ex_sss_key_store_and_object_init(&gex_sss_chip_ctx); if (kStatus_SSS_Success != status) { - ChipLogError(Crypto, "se05x error: %s\n", "ex_sss_key_store_and_object_init failed"); - return; + ChipLogError(Crypto, "se05x error: ex_sss_key_store_and_object_init failed"); + return CHIP_ERROR_INTERNAL; } is_session_open = 1; + return CHIP_NO_ERROR; } /* Delete key in se05x */ @@ -117,7 +118,11 @@ void se05x_delete_key(uint32_t keyid) smStatus_t smstatus = SM_NOT_OK; SE05x_Result_t exists = kSE05x_Result_NA; - se05x_sessionOpen(); + if (se05x_sessionOpen() != CHIP_NO_ERROR) + { + ChipLogError(Crypto, "se05x error: Error in session open"); + return; + } if (gex_sss_chip_ctx.ks.session != NULL) { @@ -130,19 +135,20 @@ void se05x_delete_key(uint32_t keyid) smstatus = Se05x_API_DeleteSecureObject(&((sss_se05x_session_t *) &gex_sss_chip_ctx.session)->s_ctx, keyid); if (smstatus != SM_OK) { - ChipLogError(Crypto, "se05x error: %s\n", "Error in deleting key"); + ChipLogError(Crypto, "se05x error: Error in deleting key"); } } else { - ChipLogError(Crypto, "se05x warn: %s\n", "Key doesnot exists"); + ChipLogError(Crypto, "se05x warn: Key doesnot exists"); } } else { - ChipLogError(Crypto, "se05x error: %s\n", "Error in Se05x_API_CheckObjectExists"); + ChipLogError(Crypto, "se05x error: Error in Se05x_API_CheckObjectExists"); } } + return; } /* Set key in se05x */ @@ -223,7 +229,7 @@ CHIP_ERROR se05xGetCertificate(uint32_t keyId, uint8_t * buf, size_t * buflen) certBitLen = (*buflen) * 8; - se05x_sessionOpen(); + VerifyOrReturnError(se05x_sessionOpen() == CHIP_NO_ERROR, CHIP_ERROR_INTERNAL); status = sss_key_object_init(&keyObject, &gex_sss_chip_ctx.ks); VerifyOrReturnError(status == kStatus_SSS_Success, CHIP_ERROR_INTERNAL); @@ -276,7 +282,7 @@ CHIP_ERROR se05xPerformInternalSign(uint32_t keyId, uint8_t * sigBuf, size_t * s #if ENABLE_REENTRANCY /* Init crypto object mutext */ -void init_cryptoObj_mutex(void) +void se05x_init_cryptoObj_mutex(void) { #if !CHIP_SYSTEM_CONFIG_NO_LOCKING Mutex::Init(sSEObjMutex); @@ -285,7 +291,7 @@ void init_cryptoObj_mutex(void) } /* Delete all crypto objects in se05x */ -void delete_crypto_objects(void) +void se05x_delete_crypto_objects(void) { static int obj_deleted = 0; smStatus_t smstatus = SM_NOT_OK; @@ -299,7 +305,12 @@ void delete_crypto_objects(void) { return; } - se05x_sessionOpen(); + + if (se05x_sessionOpen() != CHIP_NO_ERROR) + { + return; + } + if (gex_sss_chip_ctx.ks.session != NULL) { smstatus = Se05x_API_ReadCryptoObjectList(&((sss_se05x_session_t *) &gex_sss_chip_ctx.session)->s_ctx, list, &listlen); @@ -322,7 +333,7 @@ void delete_crypto_objects(void) } /* Get unused object id */ -SE05x_CryptoObjectID_t getObjID(void) +SE05x_CryptoObjectID_t se05x_getCryptoObjID(void) { SE05x_CryptoObjectID_t objId = (SE05x_CryptoObjectID_t) 0; SE05x_Result_t exists = kSE05x_Result_NA; @@ -353,7 +364,7 @@ SE05x_CryptoObjectID_t getObjID(void) } /* Set object id status */ -void setObjID(SE05x_CryptoObjectID_t objId, uint8_t status) +void se05x_setCryptoObjID(SE05x_CryptoObjectID_t objId, uint8_t status) { LOCK_SECURE_ELEMENT(); for (int i = 0; i < MAX_SPAKE_CRYPTO_OBJECT; i++) diff --git a/src/crypto/hsm/nxp/CHIPCryptoPALHsm_SE05X_utils.h b/src/platform/nxp/crypto/se05x/CHIPCryptoPALHsm_se05x_utils.h similarity index 82% rename from src/crypto/hsm/nxp/CHIPCryptoPALHsm_SE05X_utils.h rename to src/platform/nxp/crypto/se05x/CHIPCryptoPALHsm_se05x_utils.h index 75e59a64109649..a18e53e140f4a9 100644 --- a/src/crypto/hsm/nxp/CHIPCryptoPALHsm_SE05X_utils.h +++ b/src/platform/nxp/crypto/se05x/CHIPCryptoPALHsm_se05x_utils.h @@ -19,11 +19,11 @@ #include +#include #include -#include #include -#include +#include #include #include #include @@ -45,8 +45,9 @@ enum keyid_values kKeyId_pbkdf2_sha256_hmac_keyid = 0x7D000000, kKeyId_hkdf_sha256_hmac_keyid, kKeyId_hmac_sha256_keyid, - kKeyId_sha256_ecc_pub_keyid, - kKeyId_case_ephemeral_keyid, + kKeyId_sha256_ecc_pub_keyid, // Used for ECDSA verify + kKeyId_case_ephemeral_keyid, // Used for ECDH + kKeyId_node_op_keyid_start, // Node operational key pair }; // Enable the below macro to make spake HSM imlementation reentrant. @@ -71,7 +72,7 @@ extern "C" { #endif /* Open session to se05x */ -void se05x_sessionOpen(void); +CHIP_ERROR se05x_sessionOpen(void); /* Delete key in se05x */ void se05x_delete_key(uint32_t keyid); @@ -83,16 +84,16 @@ CHIP_ERROR se05x_set_key_for_spake(uint32_t keyid, const uint8_t * key, size_t k #if ENABLE_REENTRANCY /* Init crypto object mutext */ -void init_cryptoObj_mutex(void); +void se05x_init_cryptoObj_mutex(void); /* Delete all crypto objects in se05x */ -void delete_crypto_objects(void); +void se05x_delete_crypto_objects(void); /* Get unused object id */ -SE05x_CryptoObjectID_t getObjID(void); +SE05x_CryptoObjectID_t se05x_getCryptoObjID(void); /* Set object id status */ -void setObjID(SE05x_CryptoObjectID_t objId, uint8_t status); +void se05x_setCryptoObjID(SE05x_CryptoObjectID_t objId, uint8_t status); #endif //#if ENABLE_REENTRANCY diff --git a/src/platform/nxp/crypto/se05x/CHIPCryptoPAL_HostFallBack.cpp b/src/platform/nxp/crypto/se05x/CHIPCryptoPAL_HostFallBack.cpp new file mode 100644 index 00000000000000..c1e8d366656722 --- /dev/null +++ b/src/platform/nxp/crypto/se05x/CHIPCryptoPAL_HostFallBack.cpp @@ -0,0 +1,563 @@ +/* + * + * Copyright (c) 2020-2022 Project CHIP Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/** + * @file + * mbedTLS based implementation of CHIP crypto primitives + */ + +#include "CHIPCryptoPAL.h" + +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#if defined(MBEDTLS_X509_CRT_PARSE_C) +#include +#endif // defined(MBEDTLS_X509_CRT_PARSE_C) +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +namespace chip { +namespace Crypto { + +#define MAX_ERROR_STR_LEN 128 +#define NUM_BYTES_IN_SHA256_HASH 32 + +// In mbedTLS 3.0.0 direct access to structure fields was replaced with using MBEDTLS_PRIVATE macro. +#if (MBEDTLS_VERSION_NUMBER >= 0x03000000) +#define CHIP_CRYPTO_PAL_PRIVATE(x) MBEDTLS_PRIVATE(x) +#else +#define CHIP_CRYPTO_PAL_PRIVATE(x) x +#endif + +#if (MBEDTLS_VERSION_NUMBER >= 0x03000000 && MBEDTLS_VERSION_NUMBER < 0x03010000) +#define CHIP_CRYPTO_PAL_PRIVATE_X509(x) MBEDTLS_PRIVATE(x) +#else +#define CHIP_CRYPTO_PAL_PRIVATE_X509(x) x +#endif + +static void _log_mbedTLS_error(int error_code) +{ + if (error_code != 0) + { +#if defined(MBEDTLS_ERROR_C) + char error_str[MAX_ERROR_STR_LEN]; + mbedtls_strerror(error_code, error_str, sizeof(error_str)); + ChipLogError(Crypto, "mbedTLS error: %s", error_str); +#else + // Error codes defined in 16-bit negative hex numbers. Ease lookup by printing likewise + ChipLogError(Crypto, "mbedTLS error: -0x%04X", -static_cast(error_code)); +#endif + } +} + +static_assert(kMAX_Hash_SHA256_Context_Size >= sizeof(mbedtls_sha256_context), + "kMAX_Hash_SHA256_Context_Size is too small for the size of underlying mbedtls_sha256_context"); + +static inline mbedtls_sha256_context * to_inner_hash_sha256_context(HashSHA256OpaqueContext * context) +{ + return SafePointerCast(context); +} + +static int CryptoRNG(void * ctxt, uint8_t * out_buffer, size_t out_length) +{ + return (chip::Crypto::DRBG_get_bytes(out_buffer, out_length) == CHIP_NO_ERROR) ? 0 : 1; +} + +extern mbedtls_ecp_group_id MapECPGroupId(SupportedECPKeyTypes keyType); + +static inline mbedtls_ecp_keypair * to_keypair(P256KeypairContext * context) +{ + return SafePointerCast(context); +} + +static inline const mbedtls_ecp_keypair * to_const_keypair(const P256KeypairContext * context) +{ + return SafePointerCast(context); +} + +void ClearSecretData(uint8_t * buf, size_t len) +{ + mbedtls_platform_zeroize(buf, len); +} + +CHIP_ERROR Initialize_H(P256Keypair * pk, P256PublicKey * mPublicKey, P256KeypairContext * mKeypair) +{ + CHIP_ERROR error = CHIP_NO_ERROR; + int result = 0; + + size_t pubkey_size = 0; + + pk->Clear(); + + mbedtls_ecp_group_id group = MapECPGroupId(mPublicKey->Type()); + + mbedtls_ecp_keypair * keypair = to_keypair(mKeypair); + mbedtls_ecp_keypair_init(keypair); + + result = mbedtls_ecp_gen_key(group, keypair, CryptoRNG, nullptr); + VerifyOrExit(result == 0, error = CHIP_ERROR_INTERNAL); + + result = mbedtls_ecp_point_write_binary(&keypair->CHIP_CRYPTO_PAL_PRIVATE(grp), &keypair->CHIP_CRYPTO_PAL_PRIVATE(Q), + MBEDTLS_ECP_PF_UNCOMPRESSED, &pubkey_size, Uint8::to_uchar(mPublicKey->Bytes()), + mPublicKey->Length()); + VerifyOrExit(result == 0, error = CHIP_ERROR_INVALID_ARGUMENT); + VerifyOrExit(pubkey_size == mPublicKey->Length(), error = CHIP_ERROR_INVALID_ARGUMENT); + + keypair = nullptr; + // mInitialized to be set in caller function + // pk.mInitialized = true; + +exit: + if (keypair != nullptr) + { + mbedtls_ecp_keypair_free(keypair); + keypair = nullptr; + } + + _log_mbedTLS_error(result); + return error; +} + +CHIP_ERROR ECDSA_sign_msg_H(P256KeypairContext * mKeypair, const uint8_t * msg, const size_t msg_length, + P256ECDSASignature & out_signature) +{ + // To be checked by the caller + // VerifyOrReturnError(mInitialized, CHIP_ERROR_WELL_UNINITIALIZED); + VerifyOrReturnError((msg != nullptr) && (msg_length > 0), CHIP_ERROR_INVALID_ARGUMENT); + + uint8_t digest[kSHA256_Hash_Length]; + memset(&digest[0], 0, sizeof(digest)); + ReturnErrorOnFailure(Hash_SHA256(msg, msg_length, &digest[0])); + +#if defined(MBEDTLS_ECDSA_C) + CHIP_ERROR error = CHIP_NO_ERROR; + int result = 0; + mbedtls_mpi r, s; + mbedtls_mpi_init(&r); + mbedtls_mpi_init(&s); + + const mbedtls_ecp_keypair * keypair = to_const_keypair(mKeypair); + + mbedtls_ecdsa_context ecdsa_ctxt; + mbedtls_ecdsa_init(&ecdsa_ctxt); + + result = mbedtls_ecdsa_from_keypair(&ecdsa_ctxt, keypair); + VerifyOrExit(result == 0, error = CHIP_ERROR_INTERNAL); + + result = mbedtls_ecdsa_sign(&ecdsa_ctxt.CHIP_CRYPTO_PAL_PRIVATE(grp), &r, &s, &ecdsa_ctxt.CHIP_CRYPTO_PAL_PRIVATE(d), + Uint8::to_const_uchar(digest), sizeof(digest), CryptoRNG, nullptr); + + VerifyOrExit(result == 0, error = CHIP_ERROR_INTERNAL); + + VerifyOrExit((mbedtls_mpi_size(&r) <= kP256_FE_Length) && (mbedtls_mpi_size(&s) <= kP256_FE_Length), + error = CHIP_ERROR_INTERNAL); + + // Concatenate r and s to output. Sizes were checked above. + result = mbedtls_mpi_write_binary(&r, out_signature.Bytes() + 0u, kP256_FE_Length); + VerifyOrExit(result == 0, error = CHIP_ERROR_INTERNAL); + + result = mbedtls_mpi_write_binary(&s, out_signature.Bytes() + kP256_FE_Length, kP256_FE_Length); + VerifyOrExit(result == 0, error = CHIP_ERROR_INTERNAL); + + VerifyOrExit(out_signature.SetLength(kP256_ECDSA_Signature_Length_Raw) == CHIP_NO_ERROR, error = CHIP_ERROR_INTERNAL); + +exit: + keypair = nullptr; + mbedtls_ecdsa_free(&ecdsa_ctxt); + mbedtls_mpi_free(&s); + mbedtls_mpi_free(&r); + _log_mbedTLS_error(result); + return error; +#else + return CHIP_ERROR_NOT_IMPLEMENTED; +#endif +} + +CHIP_ERROR ECDH_derive_secret_H(P256KeypairContext * mKeypair, const P256PublicKey & remote_public_key, + P256ECDHDerivedSecret & out_secret) +{ +#if defined(MBEDTLS_ECDH_C) + + CHIP_ERROR error = CHIP_NO_ERROR; + int result = 0; + size_t secret_length = (out_secret.Length() == 0) ? out_secret.Capacity() : out_secret.Length(); + + mbedtls_ecp_group ecp_grp; + mbedtls_ecp_group_init(&ecp_grp); + + mbedtls_mpi mpi_secret; + mbedtls_mpi_init(&mpi_secret); + + mbedtls_ecp_point ecp_pubkey; + mbedtls_ecp_point_init(&ecp_pubkey); + + const mbedtls_ecp_keypair * keypair = to_const_keypair(mKeypair); + + // To be checked by the caller + // VerifyOrExit(mInitialized, error = CHIP_ERROR_WELL_UNINITIALIZED); + + result = mbedtls_ecp_group_load(&ecp_grp, MapECPGroupId(remote_public_key.Type())); + VerifyOrExit(result == 0, error = CHIP_ERROR_INTERNAL); + + result = + mbedtls_ecp_point_read_binary(&ecp_grp, &ecp_pubkey, Uint8::to_const_uchar(remote_public_key), remote_public_key.Length()); + VerifyOrExit(result == 0, error = CHIP_ERROR_INVALID_ARGUMENT); + + result = + mbedtls_ecdh_compute_shared(&ecp_grp, &mpi_secret, &ecp_pubkey, &keypair->CHIP_CRYPTO_PAL_PRIVATE(d), CryptoRNG, nullptr); + VerifyOrExit(result == 0, error = CHIP_ERROR_INTERNAL); + + result = mbedtls_mpi_write_binary(&mpi_secret, out_secret.Bytes() /*Uint8::to_uchar(out_secret)*/, secret_length); + VerifyOrExit(result == 0, error = CHIP_ERROR_INTERNAL); + out_secret.SetLength(secret_length); + +exit: + keypair = nullptr; + mbedtls_ecp_group_free(&ecp_grp); + mbedtls_mpi_free(&mpi_secret); + mbedtls_ecp_point_free(&ecp_pubkey); + _log_mbedTLS_error(result); + return error; + +#else + return CHIP_ERROR_NOT_IMPLEMENTED; +#endif +} + +CHIP_ERROR ECDSA_validate_hash_signature_H(const P256PublicKey * public_key, const uint8_t * hash, const size_t hash_length, + const P256ECDSASignature & signature) +{ +#if defined(MBEDTLS_ECDSA_C) + VerifyOrReturnError(hash != nullptr, CHIP_ERROR_INVALID_ARGUMENT); + VerifyOrReturnError(hash_length == kSHA256_Hash_Length, CHIP_ERROR_INVALID_ARGUMENT); + VerifyOrReturnError(signature.Length() == kP256_ECDSA_Signature_Length_Raw, CHIP_ERROR_INVALID_ARGUMENT); + + CHIP_ERROR error = CHIP_NO_ERROR; + int result = 0; + mbedtls_mpi r, s; + + mbedtls_mpi_init(&r); + mbedtls_mpi_init(&s); + + mbedtls_ecp_keypair keypair; + mbedtls_ecp_keypair_init(&keypair); + + mbedtls_ecdsa_context ecdsa_ctxt; + mbedtls_ecdsa_init(&ecdsa_ctxt); + + result = mbedtls_ecp_group_load(&keypair.CHIP_CRYPTO_PAL_PRIVATE(grp), MapECPGroupId(public_key->Type())); + + VerifyOrExit(result == 0, error = CHIP_ERROR_INVALID_ARGUMENT); + + result = mbedtls_ecp_point_read_binary(&keypair.CHIP_CRYPTO_PAL_PRIVATE(grp), &keypair.CHIP_CRYPTO_PAL_PRIVATE(Q), + Uint8::to_const_uchar(*public_key), public_key->Length()); + + VerifyOrExit(result == 0, error = CHIP_ERROR_INVALID_ARGUMENT); + + result = mbedtls_ecdsa_from_keypair(&ecdsa_ctxt, &keypair); + VerifyOrExit(result == 0, error = CHIP_ERROR_INTERNAL); + + // Read the big nums from the signature + result = mbedtls_mpi_read_binary(&r, Uint8::to_const_uchar(signature.ConstBytes()) + 0u, kP256_FE_Length); + VerifyOrExit(result == 0, error = CHIP_ERROR_INTERNAL); + + result = mbedtls_mpi_read_binary(&s, Uint8::to_const_uchar(signature.ConstBytes()) + kP256_FE_Length, kP256_FE_Length); + VerifyOrExit(result == 0, error = CHIP_ERROR_INTERNAL); + + result = mbedtls_ecdsa_verify(&ecdsa_ctxt.CHIP_CRYPTO_PAL_PRIVATE(grp), Uint8::to_const_uchar(hash), hash_length, + &ecdsa_ctxt.CHIP_CRYPTO_PAL_PRIVATE(Q), &r, &s); + + VerifyOrExit(result == 0, error = CHIP_ERROR_INVALID_SIGNATURE); + +exit: + mbedtls_ecdsa_free(&ecdsa_ctxt); + mbedtls_ecp_keypair_free(&keypair); + mbedtls_mpi_free(&s); + mbedtls_mpi_free(&r); + _log_mbedTLS_error(result); + return error; +#else + return CHIP_ERROR_NOT_IMPLEMENTED; +#endif +} + +CHIP_ERROR ECDSA_validate_msg_signature_H(const P256PublicKey * public_key, const uint8_t * msg, const size_t msg_length, + const P256ECDSASignature & signature) +{ +#if defined(MBEDTLS_ECDSA_C) + VerifyOrReturnError((msg != nullptr) && (msg_length > 0), CHIP_ERROR_INVALID_ARGUMENT); + + uint8_t digest[kSHA256_Hash_Length]; + memset(&digest[0], 0, sizeof(digest)); + ReturnErrorOnFailure(Hash_SHA256(msg, msg_length, &digest[0])); + + return ECDSA_validate_hash_signature_H(public_key, &digest[0], sizeof(digest), signature); +#else + return CHIP_ERROR_NOT_IMPLEMENTED; +#endif +} + +CHIP_ERROR NewCertificateSigningRequest_H(P256KeypairContext * mKeypair, uint8_t * out_csr, size_t & csr_length) +{ +#if defined(MBEDTLS_X509_CSR_WRITE_C) + CHIP_ERROR error = CHIP_NO_ERROR; + int result = 0; + size_t out_length; + + mbedtls_x509write_csr csr; + mbedtls_x509write_csr_init(&csr); + + mbedtls_pk_context pk; + pk.CHIP_CRYPTO_PAL_PRIVATE(pk_info) = mbedtls_pk_info_from_type(MBEDTLS_PK_ECKEY); + pk.CHIP_CRYPTO_PAL_PRIVATE(pk_ctx) = to_keypair(mKeypair); + VerifyOrExit(pk.CHIP_CRYPTO_PAL_PRIVATE(pk_info) != nullptr, error = CHIP_ERROR_INTERNAL); + + // To be checked by the caller + // VerifyOrExit(mInitialized, error = CHIP_ERROR_WELL_UNINITIALIZED); + + mbedtls_x509write_csr_set_key(&csr, &pk); + + mbedtls_x509write_csr_set_md_alg(&csr, MBEDTLS_MD_SHA256); + + // TODO: mbedTLS CSR parser fails if the subject name is not set (or if empty). + // CHIP Spec doesn't specify the subject name that can be used. + // Figure out the correct value and update this code. + result = mbedtls_x509write_csr_set_subject_name(&csr, "O=CSR"); + VerifyOrExit(result == 0, error = CHIP_ERROR_INTERNAL); + + result = mbedtls_x509write_csr_der(&csr, out_csr, csr_length, CryptoRNG, nullptr); + VerifyOrExit(result > 0, error = CHIP_ERROR_INTERNAL); + VerifyOrExit(CanCastTo(result), error = CHIP_ERROR_INTERNAL); + + out_length = static_cast(result); + result = 0; + VerifyOrExit(out_length <= csr_length, error = CHIP_ERROR_INTERNAL); + + if (csr_length != out_length) + { + // mbedTLS API writes the CSR at the end of the provided buffer. + // Let's move it to the start of the buffer. + size_t offset = csr_length - out_length; + memmove(out_csr, &out_csr[offset], out_length); + } + + csr_length = out_length; + +exit: + mbedtls_x509write_csr_free(&csr); + + _log_mbedTLS_error(result); + return error; +#else + ChipLogError(Crypto, "MBEDTLS_X509_CSR_WRITE_C is not enabled. CSR cannot be created"); + return CHIP_ERROR_UNSUPPORTED_CHIP_FEATURE; +#endif +} + +CHIP_ERROR Serialize_H(const P256KeypairContext mKeypair, const P256PublicKey mPublicKey, P256SerializedKeypair & output) +{ + const mbedtls_ecp_keypair * keypair = to_const_keypair(&mKeypair); + size_t len = output.Length() == 0 ? output.Capacity() : output.Length(); + Encoding::BufferWriter bbuf(output.Bytes(), len); + uint8_t privkey[kP256_PrivateKey_Length]; + CHIP_ERROR error = CHIP_NO_ERROR; + int result = 0; + + bbuf.Put(mPublicKey, mPublicKey.Length()); + + VerifyOrExit(bbuf.Available() == sizeof(privkey), error = CHIP_ERROR_INTERNAL); + + VerifyOrExit(mbedtls_mpi_size(&keypair->CHIP_CRYPTO_PAL_PRIVATE(d)) <= bbuf.Available(), error = CHIP_ERROR_INTERNAL); + result = mbedtls_mpi_write_binary(&keypair->CHIP_CRYPTO_PAL_PRIVATE(d), Uint8::to_uchar(privkey), sizeof(privkey)); + + VerifyOrExit(result == 0, error = CHIP_ERROR_INTERNAL); + + bbuf.Put(privkey, sizeof(privkey)); + VerifyOrExit(bbuf.Fit(), error = CHIP_ERROR_BUFFER_TOO_SMALL); + + output.SetLength(bbuf.Needed()); + +exit: + ClearSecretData(privkey, sizeof(privkey)); + _log_mbedTLS_error(result); + return error; +} + +CHIP_ERROR Deserialize_H(P256Keypair * pk, P256PublicKey * mPublicKey, P256KeypairContext * mKeypair, P256SerializedKeypair & input) +{ + Encoding::BufferWriter bbuf(*mPublicKey, mPublicKey->Length()); + + int result = 0; + CHIP_ERROR error = CHIP_NO_ERROR; + + pk->Clear(); + + mbedtls_ecp_keypair * keypair = to_keypair(mKeypair); + mbedtls_ecp_keypair_init(keypair); + + result = mbedtls_ecp_group_load(&keypair->CHIP_CRYPTO_PAL_PRIVATE(grp), MapECPGroupId(mPublicKey->Type())); + + VerifyOrExit(result == 0, error = CHIP_ERROR_INTERNAL); + + VerifyOrExit(input.Length() == mPublicKey->Length() + kP256_PrivateKey_Length, error = CHIP_ERROR_INVALID_ARGUMENT); + bbuf.Put(input.ConstBytes(), mPublicKey->Length()); + VerifyOrExit(bbuf.Fit(), error = CHIP_ERROR_NO_MEMORY); + + printf("\n"); + for (size_t i = 0; i < mPublicKey->Length(); i++) + { + printf("0x%02X ", Uint8::to_const_uchar(*mPublicKey)[i]); + } + printf("\n"); + + result = mbedtls_ecp_point_read_binary(&keypair->CHIP_CRYPTO_PAL_PRIVATE(grp), &keypair->CHIP_CRYPTO_PAL_PRIVATE(Q), + Uint8::to_const_uchar(*mPublicKey), mPublicKey->Length()); + VerifyOrExit(result == 0, error = CHIP_ERROR_INVALID_ARGUMENT); + + { + const uint8_t * privkey = input.ConstBytes() /*Uint8::to_const_uchar(input)*/ + mPublicKey->Length(); + + result = mbedtls_mpi_read_binary(&keypair->CHIP_CRYPTO_PAL_PRIVATE(d), privkey, kP256_PrivateKey_Length); + VerifyOrExit(result == 0, error = CHIP_ERROR_INVALID_ARGUMENT); + } + +exit: + _log_mbedTLS_error(result); + return error; +} + +CHIP_ERROR HKDF_SHA256_H(const uint8_t * secret, const size_t secret_length, const uint8_t * salt, const size_t salt_length, + const uint8_t * info, const size_t info_length, uint8_t * out_buffer, size_t out_length) +{ + VerifyOrReturnError(secret != nullptr, CHIP_ERROR_INVALID_ARGUMENT); + VerifyOrReturnError(secret_length > 0, CHIP_ERROR_INVALID_ARGUMENT); + + // Salt is optional + if (salt_length > 0) + { + VerifyOrReturnError(salt != nullptr, CHIP_ERROR_INVALID_ARGUMENT); + } + + VerifyOrReturnError(info_length > 0, CHIP_ERROR_INVALID_ARGUMENT); + VerifyOrReturnError(info != nullptr, CHIP_ERROR_INVALID_ARGUMENT); + VerifyOrReturnError(out_length > 0, CHIP_ERROR_INVALID_ARGUMENT); + VerifyOrReturnError(out_buffer != nullptr, CHIP_ERROR_INVALID_ARGUMENT); + + const mbedtls_md_info_t * const md = mbedtls_md_info_from_type(MBEDTLS_MD_SHA256); + VerifyOrReturnError(md != nullptr, CHIP_ERROR_INTERNAL); + + const int result = mbedtls_hkdf(md, Uint8::to_const_uchar(salt), salt_length, Uint8::to_const_uchar(secret), secret_length, + Uint8::to_const_uchar(info), info_length, Uint8::to_uchar(out_buffer), out_length); + _log_mbedTLS_error(result); + VerifyOrReturnError(result == 0, CHIP_ERROR_INTERNAL); + + return CHIP_NO_ERROR; +} + +CHIP_ERROR pbkdf2_sha256_h(const uint8_t * password, size_t plen, const uint8_t * salt, size_t slen, unsigned int iteration_count, + uint32_t key_length, uint8_t * output) +{ + CHIP_ERROR error = CHIP_NO_ERROR; + int result = 0; + const mbedtls_md_info_t * md_info; + mbedtls_md_context_t md_ctxt; + constexpr int use_hmac = 1; + + bool free_md_ctxt = false; + + VerifyOrExit(password != nullptr, error = CHIP_ERROR_INVALID_ARGUMENT); + VerifyOrExit(plen > 0, error = CHIP_ERROR_INVALID_ARGUMENT); + VerifyOrExit(salt != nullptr, error = CHIP_ERROR_INVALID_ARGUMENT); + VerifyOrExit(slen >= kSpake2p_Min_PBKDF_Salt_Length, error = CHIP_ERROR_INVALID_ARGUMENT); + VerifyOrExit(slen <= kSpake2p_Max_PBKDF_Salt_Length, error = CHIP_ERROR_INVALID_ARGUMENT); + VerifyOrExit(key_length > 0, error = CHIP_ERROR_INVALID_ARGUMENT); + VerifyOrExit(output != nullptr, error = CHIP_ERROR_INVALID_ARGUMENT); + + md_info = mbedtls_md_info_from_type(MBEDTLS_MD_SHA256); + VerifyOrExit(md_info != nullptr, error = CHIP_ERROR_INTERNAL); + + mbedtls_md_init(&md_ctxt); + free_md_ctxt = true; + + result = mbedtls_md_setup(&md_ctxt, md_info, use_hmac); + VerifyOrExit(result == 0, error = CHIP_ERROR_INTERNAL); + + result = mbedtls_pkcs5_pbkdf2_hmac(&md_ctxt, Uint8::to_const_uchar(password), plen, Uint8::to_const_uchar(salt), slen, + iteration_count, key_length, Uint8::to_uchar(output)); + + VerifyOrExit(result == 0, error = CHIP_ERROR_INTERNAL); + +exit: + _log_mbedTLS_error(result); + + if (free_md_ctxt) + { + mbedtls_md_free(&md_ctxt); + } + + return error; +} + +CHIP_ERROR HMAC_SHA256_h(const uint8_t * key, size_t key_length, const uint8_t * message, size_t message_length, + uint8_t * out_buffer, size_t out_length) +{ + VerifyOrReturnError(key != nullptr, CHIP_ERROR_INVALID_ARGUMENT); + VerifyOrReturnError(key_length > 0, CHIP_ERROR_INVALID_ARGUMENT); + VerifyOrReturnError(message != nullptr, CHIP_ERROR_INVALID_ARGUMENT); + VerifyOrReturnError(message_length > 0, CHIP_ERROR_INVALID_ARGUMENT); + VerifyOrReturnError(out_length >= kSHA256_Hash_Length, CHIP_ERROR_INVALID_ARGUMENT); + VerifyOrReturnError(out_buffer != nullptr, CHIP_ERROR_INVALID_ARGUMENT); + + const mbedtls_md_info_t * const md = mbedtls_md_info_from_type(MBEDTLS_MD_SHA256); + VerifyOrReturnError(md != nullptr, CHIP_ERROR_INTERNAL); + + const int result = + mbedtls_md_hmac(md, Uint8::to_const_uchar(key), key_length, Uint8::to_const_uchar(message), message_length, out_buffer); + + _log_mbedTLS_error(result); + VerifyOrReturnError(result == 0, CHIP_ERROR_INTERNAL); + + return CHIP_NO_ERROR; +} + +} // namespace Crypto +} // namespace chip diff --git a/src/platform/nxp/crypto/se05x/CHIPCryptoPAL_se05x.h b/src/platform/nxp/crypto/se05x/CHIPCryptoPAL_se05x.h new file mode 100644 index 00000000000000..b1adef99b9ef52 --- /dev/null +++ b/src/platform/nxp/crypto/se05x/CHIPCryptoPAL_se05x.h @@ -0,0 +1,83 @@ +/* + * + * Copyright (c) 2020 Project CHIP Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/** + * @file + * Header that exposes the platform agnostic CHIP crypto primitives + */ + +#pragma once + +#include "CHIPCryptoPALHsm_se05x_config.h" +#include + +#if ((ENABLE_SE05X_SPAKE_VERIFIER) || (ENABLE_SE05X_SPAKE_PROVER)) +typedef struct hsm_pake_context_s +{ + uint8_t spake_context[32]; + size_t spake_context_len; + uint8_t spake_objId; +} hsm_pake_context_t; +#endif //#if ((ENABLE_SE05X_SPAKE_VERIFIER) || (ENABLE_SE05X_SPAKE_PROVER)) + +namespace chip { +namespace Crypto { + +#define NXP_CRYPTO_KEY_MAGIC \ + { \ + 0xA5, 0xA6, 0xB5, 0xB6, 0xA5, 0xA6, 0xB5, 0xB6 \ + } + +static const uint8_t se05x_magic_no[] = NXP_CRYPTO_KEY_MAGIC; + +#if ((ENABLE_SE05X_SPAKE_VERIFIER) || (ENABLE_SE05X_SPAKE_PROVER)) +/* Spake HSM class */ + +class Spake2pHSM_P256_SHA256_HKDF_HMAC : public Spake2p_P256_SHA256_HKDF_HMAC +{ +public: + Spake2pHSM_P256_SHA256_HKDF_HMAC() {} + + ~Spake2pHSM_P256_SHA256_HKDF_HMAC() {} + + CHIP_ERROR Init(const uint8_t * context, size_t context_len) override; + +#if ENABLE_SE05X_SPAKE_VERIFIER + CHIP_ERROR BeginVerifier(const uint8_t * my_identity, size_t my_identity_len, const uint8_t * peer_identity, + size_t peer_identity_len, const uint8_t * w0in, size_t w0in_len, const uint8_t * Lin, + size_t Lin_len) override; +#endif + +#if ENABLE_SE05X_SPAKE_PROVER + CHIP_ERROR BeginProver(const uint8_t * my_identity, size_t my_identity_len, const uint8_t * peer_identity, + size_t peer_identity_len, const uint8_t * w0in, size_t w0in_len, const uint8_t * w1in, + size_t w1in_len) override; +#endif + + CHIP_ERROR ComputeRoundOne(const uint8_t * pab, size_t pab_len, uint8_t * out, size_t * out_len) override; + + CHIP_ERROR ComputeRoundTwo(const uint8_t * in, size_t in_len, uint8_t * out, size_t * out_len) override; + + CHIP_ERROR KeyConfirm(const uint8_t * in, size_t in_len) override; + + hsm_pake_context_t hsm_pake_context; +}; + +#endif //#if ((ENABLE_SE05X_SPAKE_VERIFIER) || (ENABLE_SE05X_SPAKE_PROVER)) + +} // namespace Crypto +} // namespace chip diff --git a/src/platform/nxp/crypto/se05x/args.gni b/src/platform/nxp/crypto/se05x/args.gni new file mode 100644 index 00000000000000..964e619aff2c9e --- /dev/null +++ b/src/platform/nxp/crypto/se05x/args.gni @@ -0,0 +1,20 @@ +# Copyright (c) 2020 Project CHIP Authors +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +import("//build_overrides/chip.gni") +import("${chip_root}/src/crypto/crypto.gni") + +nxp_crypto_impl = "se05x" +chip_crypto = "platform" +nxp_crypto_mw_root = "//third_party/simw-top-mini" diff --git a/src/platform/qpg/Logging.cpp b/src/platform/qpg/Logging.cpp index daee235e1c0ae2..37c716028f667b 100644 --- a/src/platform/qpg/Logging.cpp +++ b/src/platform/qpg/Logging.cpp @@ -8,6 +8,7 @@ #include #include #include +#include #include #include @@ -44,6 +45,28 @@ namespace chip { namespace Logging { namespace Platform { +/** + * @brief Add a timestamp in hh:mm:ss.ms format and the given prefix string to the given char buffer + * The time stamp is derived from the boot time + * + * @param logBuffer: pointer to the buffer where to add the information + * prefix: A prefix to add to the trace e.g. The category + * maxSize: Space availaible in the given buffer. + */ +static size_t AddTimeStampAndPrefixStr(char * logBuffer, const char * prefix, size_t maxSize) +{ + // Derive the hours, minutes, seconds and milliseconds since boot time millisecond counter + uint64_t bootTime = chip::System::SystemClock().GetMonotonicMilliseconds64().count(); + uint16_t milliseconds = bootTime % 1000; + uint32_t totalSeconds = bootTime / 1000; + uint8_t seconds = totalSeconds % 60; + totalSeconds /= 60; + uint8_t minutes = totalSeconds % 60; + uint32_t hours = totalSeconds / 60; + + return snprintf(logBuffer, maxSize, "[%02lu:%02u:%02u.%03u]%s", hours, minutes, seconds, milliseconds, prefix); +} + /** * CHIP log output function. */ @@ -51,31 +74,28 @@ namespace Platform { void ENFORCE_FORMAT(3, 0) LogV(const char * module, uint8_t category, const char * msg, va_list v) { char formattedMsg[CHIP_CONFIG_LOG_MESSAGE_MAX_SIZE]; - size_t prefixLen; - - prefixLen = 0; + size_t formattedMsgLen; // No build-time switches in Qorvo logging module. // Add small prefix to show logging category for now. - formattedMsg[prefixLen++] = '['; switch (category) { case kLogCategory_Error: - formattedMsg[prefixLen++] = 'E'; + formattedMsgLen = AddTimeStampAndPrefixStr(formattedMsg, "[E]", CHIP_CONFIG_LOG_MESSAGE_MAX_SIZE); break; case kLogCategory_Detail: - formattedMsg[prefixLen++] = 'D'; + formattedMsgLen = AddTimeStampAndPrefixStr(formattedMsg, "[D]", CHIP_CONFIG_LOG_MESSAGE_MAX_SIZE); break; case kLogCategory_Progress: default: - formattedMsg[prefixLen++] = 'P'; + formattedMsgLen = AddTimeStampAndPrefixStr(formattedMsg, "[P]", CHIP_CONFIG_LOG_MESSAGE_MAX_SIZE); break; } - snprintf(formattedMsg + prefixLen, sizeof(formattedMsg) - prefixLen, "][%s] ", module); + snprintf(formattedMsg + formattedMsgLen, sizeof(formattedMsg) - formattedMsgLen, "[%s] ", module); formattedMsg[sizeof(formattedMsg) - 2] = 0; // -2 to allow at least one char for the vsnprintf - prefixLen = strlen(formattedMsg); + formattedMsgLen = strlen(formattedMsg); - vsnprintf(formattedMsg + prefixLen, sizeof(formattedMsg) - prefixLen, msg, v); + vsnprintf(formattedMsg + formattedMsgLen, sizeof(formattedMsg) - formattedMsgLen, msg, v); qvCHIP_Printf(kPrintfModuleLogging, formattedMsg); diff --git a/src/protocols/secure_channel/CASESession.cpp b/src/protocols/secure_channel/CASESession.cpp index aaccba973b2f08..4974dd76a283cd 100644 --- a/src/protocols/secure_channel/CASESession.cpp +++ b/src/protocols/secure_channel/CASESession.cpp @@ -48,9 +48,6 @@ #include #include #include -#if CHIP_CRYPTO_HSM -#include -#endif namespace { @@ -1685,17 +1682,8 @@ CHIP_ERROR CASESession::HandleSigma3b(HandleSigma3Data & data, bool & cancel) // current flow of code, a malicious node can trigger a DoS style attack on the device. // The same change should be made in Sigma2 processing. // Step 7 - Validate Signature -#ifdef ENABLE_HSM_ECDSA_VERIFY - { - P256PublicKeyHSM initiatorPublicKeyHSM; - memcpy(Uint8::to_uchar(initiatorPublicKeyHSM), initiatorPublicKey.Bytes(), initiatorPublicKey.Length()); - ReturnErrorOnFailure(initiatorPublicKeyHSM.ECDSA_validate_msg_signature(data.msg_R3_Signed.Get(), data.msg_r3_signed_len, - data.tbsData3Signature)); - } -#else ReturnErrorOnFailure( initiatorPublicKey.ECDSA_validate_msg_signature(data.msg_R3_Signed.Get(), data.msg_r3_signed_len, data.tbsData3Signature)); -#endif return CHIP_NO_ERROR; } diff --git a/src/protocols/secure_channel/PASESession.h b/src/protocols/secure_channel/PASESession.h index 19918b7a3515d5..39508d8342d7b8 100644 --- a/src/protocols/secure_channel/PASESession.h +++ b/src/protocols/secure_channel/PASESession.h @@ -27,9 +27,6 @@ #pragma once #include -#if CHIP_CRYPTO_HSM -#include -#endif #include #include #include @@ -213,11 +210,7 @@ class DLL_EXPORT PASESession : public Messaging::UnsolicitedMessageHandler, // mNextExpectedMsg is set when we are expecting a message. Optional mNextExpectedMsg; -#ifdef ENABLE_HSM_SPAKE - Spake2pHSM_P256_SHA256_HKDF_HMAC mSpake2p; -#else Spake2p_P256_SHA256_HKDF_HMAC mSpake2p; -#endif Spake2pVerifier mPASEVerifier; diff --git a/src/python_testing/TC_CGEN_2_4.py b/src/python_testing/TC_CGEN_2_4.py index 682e4b02f927d8..1f0e86b5cd172d 100644 --- a/src/python_testing/TC_CGEN_2_4.py +++ b/src/python_testing/TC_CGEN_2_4.py @@ -23,18 +23,19 @@ import chip.clusters.enum import chip.FabricAdmin from chip import ChipDeviceCtrl +from chip.ChipDeviceCtrl import CommissioningParameters from matter_testing_support import MatterBaseTest, async_test_body, default_matter_test_main from mobly import asserts class TC_CGEN_2_4(MatterBaseTest): - def OpenCommissioningWindow(self) -> int: + def OpenCommissioningWindow(self) -> CommissioningParameters: try: - pin, code = self.th1.OpenCommissioningWindow( + params = self.th1.OpenCommissioningWindow( nodeid=self.dut_node_id, timeout=600, iteration=10000, discriminator=self.matter_test_config.discriminators[0], option=1) time.sleep(5) - return pin, code + return params except Exception as e: logging.exception('Error running OpenCommissioningWindow %s', e) @@ -44,16 +45,16 @@ async def CommissionToStageSendCompleteAndCleanup( self, stage: int, expectedErrorPart: chip.native.ErrorSDKPart, expectedErrCode: int): logging.info("-----------------Fail on step {}-------------------------".format(stage)) - pin, code = self.OpenCommissioningWindow() + params = self.OpenCommissioningWindow() self.th2.ResetTestCommissioner() # This will run the commissioning up to the point where stage x is run and the # response is sent before the test commissioner simulates a failure self.th2.SetTestCommissionerPrematureCompleteAfter(stage) - success, errcode = self.th2.CommissionOnNetwork( - nodeId=self.dut_node_id, setupPinCode=pin, + errcode = self.th2.CommissionOnNetwork( + nodeId=self.dut_node_id, setupPinCode=params.setupPinCode, filterType=ChipDeviceCtrl.DiscoveryFilterType.LONG_DISCRIMINATOR, filter=self.matter_test_config.discriminators[0]) - logging.info('Commissioning complete done. Successful? {}, errorcode = {}'.format(success, errcode)) - asserts.assert_false(success, 'Commissioning complete did not error as expected') + logging.info('Commissioning complete done. Successful? {}, errorcode = {}'.format(errcode.is_success, errcode)) + asserts.assert_false(errcode.is_success, 'Commissioning complete did not error as expected') asserts.assert_true(errcode.sdk_part == expectedErrorPart, 'Unexpected error type returned from CommissioningComplete') asserts.assert_true(errcode.sdk_code == expectedErrCode, 'Unexpected error code returned from CommissioningComplete') revokeCmd = Clusters.AdministratorCommissioning.Commands.RevokeCommissioning() @@ -85,14 +86,14 @@ async def test_TC_CGEN_2_4(self): await self.CommissionToStageSendCompleteAndCleanup(13, chip.native.ErrorSDKPart.IM_CLUSTER_STATUS, 0x02) logging.info('Step 15 - TH1 opens a commissioning window') - pin, code = self.OpenCommissioningWindow() + params = self.OpenCommissioningWindow() logging.info('Step 16 - TH2 fully commissions the DUT') self.th2.ResetTestCommissioner() - success, errcode = self.th2.CommissionOnNetwork( - nodeId=self.dut_node_id, setupPinCode=pin, + errcode = self.th2.CommissionOnNetwork( + nodeId=self.dut_node_id, setupPinCode=params.setupPinCode, filterType=ChipDeviceCtrl.DiscoveryFilterType.LONG_DISCRIMINATOR, filter=self.matter_test_config.discriminators[0]) - logging.info('Commissioning complete done. Successful? {}, errorcode = {}'.format(success, errcode)) + logging.info('Commissioning complete done. Successful? {}, errorcode = {}'.format(errcode.is_success, errcode)) logging.info('Step 17 - TH1 sends an arm failsafe') cmd = Clusters.GeneralCommissioning.Commands.ArmFailSafe(expiryLengthSeconds=900, breadcrumb=0) diff --git a/src/python_testing/TC_DA_1_5.py b/src/python_testing/TC_DA_1_5.py index f27d2f136e5687..567d7577604288 100644 --- a/src/python_testing/TC_DA_1_5.py +++ b/src/python_testing/TC_DA_1_5.py @@ -162,7 +162,7 @@ async def test_TC_DA_1_5(self): await self.send_single_cmd(cmd=gcomm.Commands.ArmFailSafe(expiryLengthSeconds=0, breadcrumb=1)) self.print_step(13, "Open commissioning window") - pin, _ = self.default_controller.OpenCommissioningWindow( + params = self.default_controller.OpenCommissioningWindow( nodeid=self.dut_node_id, timeout=600, iteration=10000, discriminator=1234, option=1) self.print_step(14, "Commission to TH2") @@ -170,10 +170,10 @@ async def test_TC_DA_1_5(self): new_fabric_admin = new_certificate_authority.NewFabricAdmin(vendorId=0xFFF1, fabricId=2) TH2 = new_fabric_admin.NewController(nodeId=112233) - success, _ = TH2.CommissionOnNetwork( - nodeId=self.dut_node_id, setupPinCode=pin, + errcode = TH2.CommissionOnNetwork( + nodeId=self.dut_node_id, setupPinCode=params.setupPinCode, filterType=ChipDeviceCtrl.DiscoveryFilterType.LONG_DISCRIMINATOR, filter=1234) - asserts.assert_true(success, 'Commissioning on TH2 did not complete successfully') + asserts.assert_true(errcode.is_success, 'Commissioning on TH2 did not complete successfully') self.print_step(15, "Read NOCs list for TH1") temp = await self.read_single_attribute_check_success( diff --git a/src/test_driver/efr32/.gn b/src/test_driver/efr32/.gn index f7a835ede9461e..9082b04c220ef7 100644 --- a/src/test_driver/efr32/.gn +++ b/src/test_driver/efr32/.gn @@ -27,7 +27,7 @@ default_args = { pw_build_PIP_CONSTRAINTS = [ "//third_party/connectedhomeip/scripts/setup/constraints.txt" ] pw_build_PIP_REQUIREMENTS = - [ "//third_party/connectedhomeip/scripts/setup/requirements.txt" ] + [ "//third_party/connectedhomeip/scripts/setup/requirements.build.txt" ] import("//args.gni") } diff --git a/src/tracing/backend.h b/src/tracing/backend.h index bc6501dbf6b4be..adf6b75a97828e 100644 --- a/src/tracing/backend.h +++ b/src/tracing/backend.h @@ -58,7 +58,7 @@ class Backend : public ::chip::IntrusiveListNodeBase<> virtual void TraceInstant(Instant instant) = 0; virtual void LogMessageSend(MessageSendInfo &) { TraceInstant(Instant::Log_MessageSend); } - virtual void LogMessageReceived(MessageReceiveInfo &) { TraceInstant(Instant::Log_MessageReceived); } + virtual void LogMessageReceived(MessageReceivedInfo &) { TraceInstant(Instant::Log_MessageReceived); } virtual void LogNodeLookup(NodeLookupInfo &) { TraceInstant(Instant::Log_NodeLookup); } virtual void LogNodeDiscovered(NodeDiscoveredInfo &) { TraceInstant(Instant::Log_NodeDiscovered); } diff --git a/src/tracing/log_declares.h b/src/tracing/log_declares.h index 8cc4e11a7e2cb3..5e502d0c93af6c 100644 --- a/src/tracing/log_declares.h +++ b/src/tracing/log_declares.h @@ -23,7 +23,7 @@ namespace Tracing { // on actual types. This allows tracing to be used anywhere lib/support could be used. struct MessageSendInfo; -struct MessageReceiveInfo; +struct MessageReceivedInfo; struct NodeLookupInfo; struct NodeDiscoveredInfo; struct NodeDiscoveryFailedInfo; diff --git a/src/tracing/log_json/BUILD.gn b/src/tracing/log_json/BUILD.gn index 1b8a3c8efdbbd4..655fda8e6a2c97 100644 --- a/src/tracing/log_json/BUILD.gn +++ b/src/tracing/log_json/BUILD.gn @@ -26,6 +26,7 @@ static_library("log_json") { public_deps = [ "${chip_root}/src/lib/address_resolve", "${chip_root}/src/tracing", + "${chip_root}/src/transport", "${chip_root}/third_party/jsoncpp", ] } diff --git a/src/tracing/log_json/log_json_tracing.cpp b/src/tracing/log_json/log_json_tracing.cpp index 2a89300f0eced6..933009d67bea94 100644 --- a/src/tracing/log_json/log_json_tracing.cpp +++ b/src/tracing/log_json/log_json_tracing.cpp @@ -21,6 +21,7 @@ #include #include #include +#include #include @@ -219,6 +220,63 @@ void LogJsonValue(Json::Value const & value) ChipLogProgress(Automation, "%s", output.str().c_str()); } +void DecodePayloadHeader(Json::Value & value, const PayloadHeader * payloadHeader) +{ + + value["exchangeFlags"] = payloadHeader->GetExchangeFlags(); + value["exchangeId"] = payloadHeader->GetExchangeID(); + value["protocolId"] = payloadHeader->GetProtocolID().ToFullyQualifiedSpecForm(); + value["messageType"] = payloadHeader->GetMessageType(); + value["initiator"] = payloadHeader->IsInitiator(); + value["needsAck"] = payloadHeader->NeedsAck(); + + const Optional & acknowledgedMessageCounter = payloadHeader->GetAckMessageCounter(); + if (acknowledgedMessageCounter.HasValue()) + { + value["ackMessageCounter"] = acknowledgedMessageCounter.Value(); + } +} + +void DecodePacketHeader(Json::Value & value, const PacketHeader * packetHeader) +{ + value["msgCounter"] = packetHeader->GetMessageCounter(); + value["sessionId"] = packetHeader->GetSessionId(); + value["flags"] = packetHeader->GetMessageFlags(); + value["securityFlags"] = packetHeader->GetSecurityFlags(); + + { + const Optional & nodeId = packetHeader->GetSourceNodeId(); + if (nodeId.HasValue()) + { + value["sourceNodeId"] = nodeId.Value(); + } + } + + { + const Optional & nodeId = packetHeader->GetDestinationNodeId(); + if (nodeId.HasValue()) + { + value["destinationNodeId"] = nodeId.Value(); + } + } + + { + const Optional & groupId = packetHeader->GetDestinationGroupId(); + if (groupId.HasValue()) + { + value["groupId"] = groupId.Value(); + } + } +} + +void DecodePayloadData(Json::Value & value, chip::ByteSpan payload) +{ + value["payloadSize"] = static_cast(payload.size()); + + // TODO: a decode would be useful however it likely requires more decode + // metadata +} + } // namespace void LogJsonBackend::TraceBegin(Scope scope) @@ -245,17 +303,54 @@ void LogJsonBackend::TraceInstant(Instant instant) LogJsonValue(value); } -void LogJsonBackend::LogMessageSend(MessageSendInfo &) +void LogJsonBackend::LogMessageSend(MessageSendInfo & info) { Json::Value value; - value["TODO"] = "LogMessageSend"; + value["event"] = "MessageSend"; + + switch (info.messageType) + { + case OutgoingMessageType::kGroupMessage: + value["messageType"] = "Group"; + break; + case OutgoingMessageType::kSecureSession: + value["messageType"] = "Secure"; + break; + case OutgoingMessageType::kUnauthenticated: + value["messageType"] = "Unauthenticated"; + break; + } + + DecodePayloadHeader(value["payloadHeader"], info.payloadHeader); + DecodePacketHeader(value["packetHeader"], info.packetHeader); + DecodePayloadData(value["payload"], info.payload); + LogJsonValue(value); } -void LogJsonBackend::LogMessageReceived(MessageReceiveInfo &) +void LogJsonBackend::LogMessageReceived(MessageReceivedInfo & info) { Json::Value value; - value["TODO"] = "LogMessageReceived"; + + value["event"] = "MessageReceived"; + + switch (info.messageType) + { + case IncomingMessageType::kGroupMessage: + value["messageType"] = "Group"; + break; + case IncomingMessageType::kSecureUnicast: + value["messageType"] = "Secure"; + break; + case IncomingMessageType::kUnauthenticated: + value["messageType"] = "Unauthenticated"; + break; + } + + DecodePayloadHeader(value["payloadHeader"], info.payloadHeader); + DecodePacketHeader(value["packetHeader"], info.packetHeader); + DecodePayloadData(value["payload"], info.payload); + LogJsonValue(value); } diff --git a/src/tracing/log_json/log_json_tracing.h b/src/tracing/log_json/log_json_tracing.h index ca15c8f27e6448..ef462c9c37be95 100644 --- a/src/tracing/log_json/log_json_tracing.h +++ b/src/tracing/log_json/log_json_tracing.h @@ -35,7 +35,7 @@ class LogJsonBackend : public ::chip::Tracing::Backend void TraceEnd(Scope scope) override; void TraceInstant(Instant instant) override; void LogMessageSend(MessageSendInfo &) override; - void LogMessageReceived(MessageReceiveInfo &) override; + void LogMessageReceived(MessageReceivedInfo &) override; void LogNodeLookup(NodeLookupInfo &) override; void LogNodeDiscovered(NodeDiscoveredInfo &) override; void LogNodeDiscoveryFailed(NodeDiscoveryFailedInfo &) override; diff --git a/src/tracing/registry.cpp b/src/tracing/registry.cpp index f3497a27f2643f..bb9862383f2857 100644 --- a/src/tracing/registry.cpp +++ b/src/tracing/registry.cpp @@ -74,7 +74,7 @@ void LogMessageSend(::chip::Tracing::MessageSendInfo & info) } } -void LogMessageReceived(::chip::Tracing::MessageReceiveInfo & info) +void LogMessageReceived(::chip::Tracing::MessageReceivedInfo & info) { for (auto & backend : gTracingBackends) { diff --git a/src/tracing/registry.h b/src/tracing/registry.h index b1596144dbc00f..b3a5a6aaf1564f 100644 --- a/src/tracing/registry.h +++ b/src/tracing/registry.h @@ -64,7 +64,7 @@ void End(::chip::Tracing::Scope scope); void Instant(::chip::Tracing::Instant instant); void LogMessageSend(::chip::Tracing::MessageSendInfo & info); -void LogMessageReceived(::chip::Tracing::MessageReceiveInfo & info); +void LogMessageReceived(::chip::Tracing::MessageReceivedInfo & info); void LogNodeLookup(::chip::Tracing::NodeLookupInfo & info); void LogNodeDiscovered(::chip::Tracing::NodeDiscoveredInfo & info); void LogNodeDiscoveryFailed(::chip::Tracing::NodeDiscoveryFailedInfo & info); diff --git a/src/transport/BUILD.gn b/src/transport/BUILD.gn index a632f41af3a3d3..70168e64cb5924 100644 --- a/src/transport/BUILD.gn +++ b/src/transport/BUILD.gn @@ -45,6 +45,7 @@ static_library("transport") { "SessionManager.h", "SessionMessageCounter.h", "SessionMessageDelegate.h", + "TracingStructs.h", "TransportMgr.h", "TransportMgrBase.cpp", "TransportMgrBase.h", @@ -64,6 +65,7 @@ static_library("transport") { "${chip_root}/src/lib/support", "${chip_root}/src/platform", "${chip_root}/src/setup_payload", + "${chip_root}/src/tracing", "${chip_root}/src/transport/raw", "${nlio_root}:nlio", ] diff --git a/src/transport/SessionManager.cpp b/src/transport/SessionManager.cpp index 1aba11a75764db..30494b0d60fe1a 100644 --- a/src/transport/SessionManager.cpp +++ b/src/transport/SessionManager.cpp @@ -40,9 +40,11 @@ #include #include #include +#include #include #include #include +#include #include // Global object @@ -178,6 +180,9 @@ CHIP_ERROR SessionManager::PrepareMessage(const SessionHandle & sessionHandle, P } // Trace before any encryption + MATTER_LOG_MESSAGE_SEND(chip::Tracing::OutgoingMessageType::kGroupMessage, &payloadHeader, &packetHeader, + chip::ByteSpan(message->Start(), message->TotalLength())); + CHIP_TRACE_MESSAGE_SENT(payloadHeader, packetHeader, message->Start(), message->TotalLength()); Crypto::SymmetricKeyContext * keyContext = @@ -213,6 +218,8 @@ CHIP_ERROR SessionManager::PrepareMessage(const SessionHandle & sessionHandle, P .SetSessionType(Header::SessionType::kUnicastSession); // Trace before any encryption + MATTER_LOG_MESSAGE_SEND(chip::Tracing::OutgoingMessageType::kSecureSession, &payloadHeader, &packetHeader, + chip::ByteSpan(message->Start(), message->TotalLength())); CHIP_TRACE_MESSAGE_SENT(payloadHeader, packetHeader, message->Start(), message->TotalLength()); CryptoContext::NonceStorage nonce; @@ -244,6 +251,8 @@ CHIP_ERROR SessionManager::PrepareMessage(const SessionHandle & sessionHandle, P } // Trace after all headers are settled. + MATTER_LOG_MESSAGE_SEND(chip::Tracing::OutgoingMessageType::kUnauthenticated, &payloadHeader, &packetHeader, + chip::ByteSpan(message->Start(), message->TotalLength())); CHIP_TRACE_MESSAGE_SENT(payloadHeader, packetHeader, message->Start(), message->TotalLength()); ReturnErrorOnFailure(payloadHeader.EncodeBeforeData(message)); @@ -641,12 +650,18 @@ void SessionManager::UnauthenticatedMessageDispatch(const PacketHeader & partial // CHIP_ERROR_DUPLICATE_MESSAGE_RECEIVED. unsecuredSession->GetPeerMessageCounter().CommitUnencrypted(packetHeader.GetMessageCounter()); } - if (mCB != nullptr) { + MATTER_LOG_MESSAGE_RECEIVED(chip::Tracing::IncomingMessageType::kUnauthenticated, &payloadHeader, &packetHeader, + unsecuredSession, &peerAddress, chip::ByteSpan(msg->Start(), msg->TotalLength())); + CHIP_TRACE_MESSAGE_RECEIVED(payloadHeader, packetHeader, unsecuredSession, peerAddress, msg->Start(), msg->TotalLength()); mCB->OnMessageReceived(packetHeader, payloadHeader, session, isDuplicate, std::move(msg)); } + else + { + ChipLogError(Inet, "Received UNSECURED message was not processed."); + } } void SessionManager::SecureUnicastMessageDispatch(const PacketHeader & partialPacketHeader, @@ -751,9 +766,15 @@ void SessionManager::SecureUnicastMessageDispatch(const PacketHeader & partialPa if (mCB != nullptr) { + MATTER_LOG_MESSAGE_RECEIVED(chip::Tracing::IncomingMessageType::kSecureUnicast, &payloadHeader, &packetHeader, + secureSession, &peerAddress, chip::ByteSpan(msg->Start(), msg->TotalLength())); CHIP_TRACE_MESSAGE_RECEIVED(payloadHeader, packetHeader, secureSession, peerAddress, msg->Start(), msg->TotalLength()); mCB->OnMessageReceived(packetHeader, payloadHeader, session.Value(), isDuplicate, std::move(msg)); } + else + { + ChipLogError(Inet, "Received SECURED message was not processed."); + } } /** @@ -958,10 +979,18 @@ void SessionManager::SecureGroupMessageDispatch(const PacketHeader & partialPack // TODO : When MCSP is done, clean up session creation logic Transport::IncomingGroupSession groupSession(groupContext.group_id, groupContext.fabric_index, packetHeaderCopy.GetSourceNodeId().Value()); + + MATTER_LOG_MESSAGE_RECEIVED(chip::Tracing::IncomingMessageType::kGroupMessage, &payloadHeader, &packetHeaderCopy, + &groupSession, &peerAddress, chip::ByteSpan(msg->Start(), msg->TotalLength())); + CHIP_TRACE_MESSAGE_RECEIVED(payloadHeader, packetHeaderCopy, &groupSession, peerAddress, msg->Start(), msg->TotalLength()); mCB->OnMessageReceived(packetHeaderCopy, payloadHeader, SessionHandle(groupSession), SessionMessageDelegate::DuplicateMessage::No, std::move(msg)); } + else + { + ChipLogError(Inet, "Received GROUP message was not processed."); + } } Optional SessionManager::FindSecureSessionForNode(ScopedNodeId peerNodeId, diff --git a/src/transport/TracingStructs.h b/src/transport/TracingStructs.h new file mode 100644 index 00000000000000..5f57663e46dba2 --- /dev/null +++ b/src/transport/TracingStructs.h @@ -0,0 +1,64 @@ +/* + * Copyright (c) 2023 Project CHIP Authors + * All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#pragma once + +#include +#include +#include + +namespace chip { +namespace Tracing { + +/// Concrete definitions of the message tracing info that session managers +/// report + +enum class OutgoingMessageType +{ + kGroupMessage, + kSecureSession, + kUnauthenticated, +}; + +/// A message is about to be sent +struct MessageSendInfo +{ + OutgoingMessageType messageType; + const PayloadHeader * payloadHeader; + const PacketHeader * packetHeader; + const chip::ByteSpan payload; +}; + +enum class IncomingMessageType +{ + kGroupMessage, + kSecureUnicast, + kUnauthenticated, +}; + +/// A message has been received +struct MessageReceivedInfo +{ + const IncomingMessageType messageType; + const PayloadHeader * payloadHeader; + const PacketHeader * packetHeader; + const Transport::Session * session; + const Transport::PeerAddress * peerAddress; + const chip::ByteSpan payload; +}; + +} // namespace Tracing +} // namespace chip diff --git a/src/transport/raw/MessageHeader.h b/src/transport/raw/MessageHeader.h index 4f7856232179c5..ec957315714bbb 100644 --- a/src/transport/raw/MessageHeader.h +++ b/src/transport/raw/MessageHeader.h @@ -511,7 +511,7 @@ class PayloadHeader uint8_t GetMessageType() const { return mMessageType; } /** Get the raw exchange flags from this header. */ - uint8_t GetExhangeFlags() const { return mExchangeFlags.Raw(); } + uint8_t GetExchangeFlags() const { return mExchangeFlags.Raw(); } /** Check whether the header has a given secure message type */ bool HasMessageType(uint8_t type) const { return mMessageType == type; } diff --git a/third_party/mbedtls/repo b/third_party/mbedtls/repo index 8eaf2d2ac93c43..d5f4039227a896 160000 --- a/third_party/mbedtls/repo +++ b/third_party/mbedtls/repo @@ -1 +1 @@ -Subproject commit 8eaf2d2ac93c432399a7c580496a45ad16519a17 +Subproject commit d5f4039227a896db6886fc552993953f8f6dff6a diff --git a/third_party/openthread/repo b/third_party/openthread/repo index 9b99fbfd092380..36b1b838d9416d 160000 --- a/third_party/openthread/repo +++ b/third_party/openthread/repo @@ -1 +1 @@ -Subproject commit 9b99fbfd092380b0b8760bcb4863ea7c5f46e476 +Subproject commit 36b1b838d9416d46765fb60610db59bb433a3ce7 diff --git a/third_party/pigweed/repo b/third_party/pigweed/repo index d8e4b80c79540b..45b1073516c7f9 160000 --- a/third_party/pigweed/repo +++ b/third_party/pigweed/repo @@ -1 +1 @@ -Subproject commit d8e4b80c79540b12d367e4581250d133c8415596 +Subproject commit 45b1073516c7f9bd949f1004505abc89f31abbd4 diff --git a/third_party/simw-top-mini/BUILD.gn b/third_party/simw-top-mini/BUILD.gn index 0cd9eb9dc2a009..ed80ad0aea0db5 100644 --- a/third_party/simw-top-mini/BUILD.gn +++ b/third_party/simw-top-mini/BUILD.gn @@ -13,6 +13,10 @@ # limitations under the License. import("//build_overrides/chip.gni") +import("//build_overrides/nlassert.gni") + +import("${chip_root}/build/chip/buildconfig_header.gni") +import("${chip_root}/src/crypto/crypto.gni") import("${chip_root}/src/platform/device.gni") import("${chip_root}/third_party/simw-top-mini/simw_config.gni") @@ -25,7 +29,7 @@ config("se05x_config") { "SMCOM_T1oI2C", ] - #defines += ["FLOW_VERBOSE"] + # defines += ["FLOW_VERBOSE"] if (chip_device_platform == "k32w0") { defines += [ @@ -35,82 +39,76 @@ config("se05x_config") { ] } - if (chip_rpi_se05x_t4t_demo == 1) { - defines += [ "CHIP_RPI_SE05X_T4T_DEMO" ] - } - include_dirs = [ - "${chip_root}/third_party/simw-top-mini/repo", - "${chip_root}/third_party/simw-top-mini/repo/sss/inc", - "${chip_root}/third_party/simw-top-mini/repo/sss/port/default", - "${chip_root}/third_party/simw-top-mini/repo/sss/ex/src", - "${chip_root}/third_party/simw-top-mini/repo/sss/ex/inc", - "${chip_root}/third_party/simw-top-mini/repo/hostlib/hostLib/inc", - "${chip_root}/third_party/simw-top-mini/repo/hostlib/hostLib/libCommon/infra", - "${chip_root}/third_party/simw-top-mini/repo/hostlib/hostLib/libCommon/smCom", - "${chip_root}/third_party/simw-top-mini/repo/hostlib/hostLib/libCommon/log", - "${chip_root}/third_party/simw-top-mini/repo/hostlib/hostLib/libCommon/smCom/T1oI2C", - "${chip_root}/third_party/simw-top-mini/repo/hostlib/hostLib/se05x_03_xx_xx", - "${chip_root}/third_party/simw-top-mini/repo/hostlib/hostLib/platform/inc", - "${chip_root}/third_party/simw-top-mini/repo/hostlib/hostLib/libCommon/smCom", + "repo", + "repo/sss/inc", + "repo/sss/port/default", + "repo/sss/ex/src", + "repo/sss/ex/inc", + "repo/hostlib/hostLib/inc", + "repo/hostlib/hostLib/libCommon/infra", + "repo/hostlib/hostLib/libCommon/smCom", + "repo/hostlib/hostLib/libCommon/log", + "repo/hostlib/hostLib/se05x_03_xx_xx", + "repo/hostlib/hostLib/platform/inc", + "repo/hostlib/hostLib/libCommon/smCom", ] + include_dirs += [ "repo/hostlib/hostLib/libCommon/smCom/T1oI2C" ] if (chip_device_platform == "k32w0") { include_dirs += [ - "${chip_root}/third_party/simw-top-mini/repo/demos/ksdk/common/boards/DK6/wireless_examples/chip", - "${chip_root}/third_party/simw-top-mini/repo/demos/ksdk/common/freertos/boards/DK6", + "repo/demos/ksdk/common/boards/DK6/wireless_examples/chip", + "repo/demos/ksdk/common/freertos/boards/DK6", ] } } -source_set("se05x") { +static_library("se05x") { sources = [ - "${chip_root}/third_party/simw-top-mini/repo/hostlib/hostLib/libCommon/infra/global_platf.c", - "${chip_root}/third_party/simw-top-mini/repo/hostlib/hostLib/libCommon/infra/sm_apdu.c", - "${chip_root}/third_party/simw-top-mini/repo/hostlib/hostLib/libCommon/infra/sm_connect.c", - "${chip_root}/third_party/simw-top-mini/repo/hostlib/hostLib/libCommon/infra/sm_errors.c", - "${chip_root}/third_party/simw-top-mini/repo/hostlib/hostLib/libCommon/infra/sm_printf.c", - "${chip_root}/third_party/simw-top-mini/repo/hostlib/hostLib/libCommon/log/nxLog.c", - "${chip_root}/third_party/simw-top-mini/repo/hostlib/hostLib/libCommon/smCom/smCom.c", - "${chip_root}/third_party/simw-top-mini/repo/hostlib/hostLib/platform/generic/se05x_t4t_utils.cpp", - "${chip_root}/third_party/simw-top-mini/repo/hostlib/hostLib/platform/rsp/se05x_reset.c", - "${chip_root}/third_party/simw-top-mini/repo/hostlib/hostLib/se05x/src/se05x_ECC_curves.c", - "${chip_root}/third_party/simw-top-mini/repo/hostlib/hostLib/se05x/src/se05x_mw.c", - "${chip_root}/third_party/simw-top-mini/repo/hostlib/hostLib/se05x/src/se05x_tlv.c", - "${chip_root}/third_party/simw-top-mini/repo/hostlib/hostLib/se05x_03_xx_xx/se05x_APDU.c", - "${chip_root}/third_party/simw-top-mini/repo/sss/ex/src/ex_sss_boot.c", - "${chip_root}/third_party/simw-top-mini/repo/sss/ex/src/ex_sss_boot_connectstring.c", - "${chip_root}/third_party/simw-top-mini/repo/sss/ex/src/ex_sss_se05x.c", - "${chip_root}/third_party/simw-top-mini/repo/sss/ex/src/ex_sss_se05x_auth.c", - "${chip_root}/third_party/simw-top-mini/repo/sss/src/fsl_sss_apis.c", - "${chip_root}/third_party/simw-top-mini/repo/sss/src/fsl_sss_util_asn1_der.c", - "${chip_root}/third_party/simw-top-mini/repo/sss/src/fsl_sss_util_rsa_sign_utils.c", - "${chip_root}/third_party/simw-top-mini/repo/sss/src/keystore/keystore_cmn.c", - "${chip_root}/third_party/simw-top-mini/repo/sss/src/keystore/keystore_pc.c", - "${chip_root}/third_party/simw-top-mini/repo/sss/src/mbedtls/fsl_sss_mbedtls_apis.c", - "${chip_root}/third_party/simw-top-mini/repo/sss/src/se05x/fsl_sss_se05x_apis.c", - "${chip_root}/third_party/simw-top-mini/repo/sss/src/se05x/fsl_sss_se05x_mw.c", - "${chip_root}/third_party/simw-top-mini/repo/sss/src/se05x/fsl_sss_se05x_policy.c", + "repo/hostlib/hostLib/libCommon/infra/global_platf.c", + "repo/hostlib/hostLib/libCommon/infra/sm_apdu.c", + "repo/hostlib/hostLib/libCommon/infra/sm_connect.c", + "repo/hostlib/hostLib/libCommon/infra/sm_errors.c", + "repo/hostlib/hostLib/libCommon/infra/sm_printf.c", + "repo/hostlib/hostLib/libCommon/log/nxLog.c", + "repo/hostlib/hostLib/libCommon/smCom/smCom.c", + "repo/hostlib/hostLib/platform/rsp/se05x_reset.c", + "repo/hostlib/hostLib/se05x/src/se05x_ECC_curves.c", + "repo/hostlib/hostLib/se05x/src/se05x_mw.c", + "repo/hostlib/hostLib/se05x/src/se05x_tlv.c", + "repo/hostlib/hostLib/se05x_03_xx_xx/se05x_APDU.c", + "repo/sss/ex/src/ex_sss_boot.c", + "repo/sss/ex/src/ex_sss_boot_connectstring.c", + "repo/sss/ex/src/ex_sss_se05x.c", + "repo/sss/ex/src/ex_sss_se05x_auth.c", + "repo/sss/src/fsl_sss_apis.c", + "repo/sss/src/fsl_sss_util_asn1_der.c", + "repo/sss/src/fsl_sss_util_rsa_sign_utils.c", + "repo/sss/src/keystore/keystore_cmn.c", + "repo/sss/src/keystore/keystore_pc.c", + "repo/sss/src/mbedtls/fsl_sss_mbedtls_apis.c", + "repo/sss/src/se05x/fsl_sss_se05x_apis.c", + "repo/sss/src/se05x/fsl_sss_se05x_mw.c", + "repo/sss/src/se05x/fsl_sss_se05x_policy.c", ] sources += [ - "${chip_root}/third_party/simw-top-mini/repo/hostlib/hostLib/libCommon/smCom/T1oI2C/phNxpEsePal_i2c.c", - "${chip_root}/third_party/simw-top-mini/repo/hostlib/hostLib/libCommon/smCom/T1oI2C/phNxpEseProto7816_3.c", - "${chip_root}/third_party/simw-top-mini/repo/hostlib/hostLib/libCommon/smCom/T1oI2C/phNxpEse_Api.c", - "${chip_root}/third_party/simw-top-mini/repo/hostlib/hostLib/libCommon/smCom/smComT1oI2C.c", + "repo/hostlib/hostLib/libCommon/smCom/T1oI2C/phNxpEsePal_i2c.c", + "repo/hostlib/hostLib/libCommon/smCom/T1oI2C/phNxpEseProto7816_3.c", + "repo/hostlib/hostLib/libCommon/smCom/T1oI2C/phNxpEse_Api.c", + "repo/hostlib/hostLib/libCommon/smCom/smComT1oI2C.c", ] if (chip_device_platform == "k32w0") { sources += [ - "${chip_root}/third_party/simw-top-mini/repo/hostlib/hostLib/platform/ksdk/i2c_dk6.c", - "${chip_root}/third_party/simw-top-mini/repo/hostlib/hostLib/platform/ksdk/timer_kinetis_freertos.c", + "repo/hostlib/hostLib/platform/ksdk/i2c_dk6.c", + "repo/hostlib/hostLib/platform/ksdk/timer_kinetis_freertos.c", ] } else if (chip_device_platform == "linux") { sources += [ - "${chip_root}/third_party/simw-top-mini/repo/hostlib/hostLib/platform/generic/sm_timer.c", - "${chip_root}/third_party/simw-top-mini/repo/hostlib/hostLib/platform/linux/i2c_a7.c", + "repo/hostlib/hostLib/platform/generic/sm_timer.c", + "repo/hostlib/hostLib/platform/linux/i2c_a7.c", ] } - public_deps = [ "${chip_root}/third_party/mbedtls:mbedtls" ] - configs += [ ":se05x_config" ] + public_configs = [ ":se05x_config" ] } diff --git a/third_party/simw-top-mini/repo b/third_party/simw-top-mini/repo index be0dfb64b28dea..2e9189d97010b5 160000 --- a/third_party/simw-top-mini/repo +++ b/third_party/simw-top-mini/repo @@ -1 +1 @@ -Subproject commit be0dfb64b28dea3509425755e3b4b5b35c38d327 +Subproject commit 2e9189d97010b5d9d380d975ee09b7277221f890 diff --git a/third_party/simw-top-mini/simw_config.gni b/third_party/simw-top-mini/simw_config.gni index 2bffa51eaa6c42..d5871fed7c72d9 100644 --- a/third_party/simw-top-mini/simw_config.gni +++ b/third_party/simw-top-mini/simw_config.gni @@ -13,7 +13,3 @@ # limitations under the License. # Configuration file - -declare_args() { - chip_rpi_se05x_t4t_demo = 0 -} diff --git a/zzz_generated/chip-tool/zap-generated/test/Commands.h b/zzz_generated/chip-tool/zap-generated/test/Commands.h index cb11f6427d4461..676f52894f4490 100644 --- a/zzz_generated/chip-tool/zap-generated/test/Commands.h +++ b/zzz_generated/chip-tool/zap-generated/test/Commands.h @@ -79946,7 +79946,7 @@ class TestClusterComplexTypesSuite : public TestCommand class TestConstraintsSuite : public TestCommand { public: - TestConstraintsSuite(CredentialIssuerCommands * credsIssuerConfig) : TestCommand("TestConstraints", 57, credsIssuerConfig) + TestConstraintsSuite(CredentialIssuerCommands * credsIssuerConfig) : TestCommand("TestConstraints", 61, credsIssuerConfig) { AddArgument("nodeId", 0, UINT64_MAX, &mNodeId); AddArgument("cluster", &mCluster); @@ -80258,6 +80258,28 @@ class TestConstraintsSuite : public TestCommand VerifyOrReturn(CheckValue("status", chip::to_underlying(status.mStatus), 0)); break; case 45: + VerifyOrReturn(CheckValue("status", chip::to_underlying(status.mStatus), 0)); + break; + case 46: + VerifyOrReturn(CheckValue("status", chip::to_underlying(status.mStatus), 0)); + { + chip::app::DataModel::Nullable value; + VerifyOrReturn(CheckDecodeValue(chip::app::DataModel::Decode(*data, value))); + VerifyOrReturn(CheckConstraintMinLength("value", value, 5)); + } + break; + case 47: + VerifyOrReturn(CheckValue("status", chip::to_underlying(status.mStatus), 0)); + { + chip::app::DataModel::Nullable value; + VerifyOrReturn(CheckDecodeValue(chip::app::DataModel::Decode(*data, value))); + VerifyOrReturn(CheckConstraintMaxLength("value", value, 20)); + } + break; + case 48: + VerifyOrReturn(CheckValue("status", chip::to_underlying(status.mStatus), 0)); + break; + case 49: VerifyOrReturn(CheckValue("status", chip::to_underlying(status.mStatus), 0)); { chip::app::DataModel::Nullable value; @@ -80266,30 +80288,30 @@ class TestConstraintsSuite : public TestCommand VerifyOrReturn(CheckValue("nullableInt8u.Value()", value.Value(), 0U)); } break; - case 46: + case 50: VerifyOrReturn(CheckValue("status", chip::to_underlying(status.mStatus), 0)); break; - case 47: + case 51: VerifyOrReturn(CheckValue("status", chip::to_underlying(status.mStatus), 0)); { chip::app::DataModel::Nullable value; VerifyOrReturn(CheckDecodeValue(chip::app::DataModel::Decode(*data, value))); } break; - case 48: + case 52: VerifyOrReturn(CheckValue("status", chip::to_underlying(status.mStatus), 0)); break; - case 49: + case 53: VerifyOrReturn(CheckValue("status", chip::to_underlying(status.mStatus), 0)); { chip::app::DataModel::Nullable value; VerifyOrReturn(CheckDecodeValue(chip::app::DataModel::Decode(*data, value))); } break; - case 50: + case 54: VerifyOrReturn(CheckValue("status", chip::to_underlying(status.mStatus), 0)); break; - case 51: + case 55: VerifyOrReturn(CheckValue("status", chip::to_underlying(status.mStatus), 0)); { chip::app::DataModel::Nullable value; @@ -80299,27 +80321,27 @@ class TestConstraintsSuite : public TestCommand chip::ByteSpan(chip::Uint8::from_const_char(""), 0))); } break; - case 52: + case 56: VerifyOrReturn(CheckValue("status", chip::to_underlying(status.mStatus), 0)); break; - case 53: + case 57: VerifyOrReturn(CheckValue("status", chip::to_underlying(status.mStatus), 0)); { chip::app::DataModel::Nullable value; VerifyOrReturn(CheckDecodeValue(chip::app::DataModel::Decode(*data, value))); } break; - case 54: + case 58: VerifyOrReturn(CheckValue("status", chip::to_underlying(status.mStatus), 0)); break; - case 55: + case 59: VerifyOrReturn(CheckValue("status", chip::to_underlying(status.mStatus), 0)); { chip::app::DataModel::Nullable value; VerifyOrReturn(CheckDecodeValue(chip::app::DataModel::Decode(*data, value))); } break; - case 56: + case 60: VerifyOrReturn(CheckValue("status", chip::to_underlying(status.mStatus), 0)); break; default: @@ -80632,12 +80654,39 @@ class TestConstraintsSuite : public TestCommand chip::NullOptional, chip::NullOptional); } case 45: { - LogStep(45, "Read attribute NULLABLE_INT8U Default Value"); + LogStep(45, "Write attribute NULLABLE_CHAR_STRING Value"); + ListFreer listFreer; + chip::app::DataModel::Nullable value; + value.SetNull(); + return WriteAttribute(kIdentityAlpha, GetEndpoint(1), UnitTesting::Id, UnitTesting::Attributes::NullableCharString::Id, + value, chip::NullOptional, chip::NullOptional); + } + case 46: { + LogStep(46, "Read attribute NULLABLE_CHAR_STRING Value MinLength Constraints"); + return ReadAttribute(kIdentityAlpha, GetEndpoint(1), UnitTesting::Id, UnitTesting::Attributes::NullableCharString::Id, + true, chip::NullOptional); + } + case 47: { + LogStep(47, "Read attribute NULLABLE_CHAR_STRING Value MaxLength Constraints"); + return ReadAttribute(kIdentityAlpha, GetEndpoint(1), UnitTesting::Id, UnitTesting::Attributes::NullableCharString::Id, + true, chip::NullOptional); + } + case 48: { + LogStep(48, "Write attribute NULLABLE_CHAR_STRING Value Back to Default Value"); + ListFreer listFreer; + chip::app::DataModel::Nullable value; + value.SetNonNull(); + value.Value() = chip::Span("garbage: not in length on purpose", 0); + return WriteAttribute(kIdentityAlpha, GetEndpoint(1), UnitTesting::Id, UnitTesting::Attributes::NullableCharString::Id, + value, chip::NullOptional, chip::NullOptional); + } + case 49: { + LogStep(49, "Read attribute NULLABLE_INT8U Default Value"); return ReadAttribute(kIdentityAlpha, GetEndpoint(1), UnitTesting::Id, UnitTesting::Attributes::NullableInt8u::Id, true, chip::NullOptional); } - case 46: { - LogStep(46, "Write attribute NULLABLE_INT8U with a value"); + case 50: { + LogStep(50, "Write attribute NULLABLE_INT8U with a value"); ListFreer listFreer; chip::app::DataModel::Nullable value; value.SetNonNull(); @@ -80645,26 +80694,26 @@ class TestConstraintsSuite : public TestCommand return WriteAttribute(kIdentityAlpha, GetEndpoint(1), UnitTesting::Id, UnitTesting::Attributes::NullableInt8u::Id, value, chip::NullOptional, chip::NullOptional); } - case 47: { - LogStep(47, "Read attribute NULLABLE_INT8U with a value"); + case 51: { + LogStep(51, "Read attribute NULLABLE_INT8U with a value"); return ReadAttribute(kIdentityAlpha, GetEndpoint(1), UnitTesting::Id, UnitTesting::Attributes::NullableInt8u::Id, true, chip::NullOptional); } - case 48: { - LogStep(48, "Write attribute NULLABLE_INT8U without a value"); + case 52: { + LogStep(52, "Write attribute NULLABLE_INT8U without a value"); ListFreer listFreer; chip::app::DataModel::Nullable value; value.SetNull(); return WriteAttribute(kIdentityAlpha, GetEndpoint(1), UnitTesting::Id, UnitTesting::Attributes::NullableInt8u::Id, value, chip::NullOptional, chip::NullOptional); } - case 49: { - LogStep(49, "Read attribute NULLABLE_INT8U with a value"); + case 53: { + LogStep(53, "Read attribute NULLABLE_INT8U with a value"); return ReadAttribute(kIdentityAlpha, GetEndpoint(1), UnitTesting::Id, UnitTesting::Attributes::NullableInt8u::Id, true, chip::NullOptional); } - case 50: { - LogStep(50, "Write attribute NULLABLE_INT8U back to Default Value"); + case 54: { + LogStep(54, "Write attribute NULLABLE_INT8U back to Default Value"); ListFreer listFreer; chip::app::DataModel::Nullable value; value.SetNonNull(); @@ -80672,13 +80721,13 @@ class TestConstraintsSuite : public TestCommand return WriteAttribute(kIdentityAlpha, GetEndpoint(1), UnitTesting::Id, UnitTesting::Attributes::NullableInt8u::Id, value, chip::NullOptional, chip::NullOptional); } - case 51: { - LogStep(51, "Read attribute NULLABLE_OCTET_STRING Default Value"); + case 55: { + LogStep(55, "Read attribute NULLABLE_OCTET_STRING Default Value"); return ReadAttribute(kIdentityAlpha, GetEndpoint(1), UnitTesting::Id, UnitTesting::Attributes::NullableOctetString::Id, true, chip::NullOptional); } - case 52: { - LogStep(52, "Write attribute NULLABLE_OCTET_STRING"); + case 56: { + LogStep(56, "Write attribute NULLABLE_OCTET_STRING"); ListFreer listFreer; chip::app::DataModel::Nullable value; value.SetNonNull(); @@ -80686,26 +80735,26 @@ class TestConstraintsSuite : public TestCommand return WriteAttribute(kIdentityAlpha, GetEndpoint(1), UnitTesting::Id, UnitTesting::Attributes::NullableOctetString::Id, value, chip::NullOptional, chip::NullOptional); } - case 53: { - LogStep(53, "Read attribute NULLABLE_OCTET_STRING"); + case 57: { + LogStep(57, "Read attribute NULLABLE_OCTET_STRING"); return ReadAttribute(kIdentityAlpha, GetEndpoint(1), UnitTesting::Id, UnitTesting::Attributes::NullableOctetString::Id, true, chip::NullOptional); } - case 54: { - LogStep(54, "Write attribute NULLABLE_OCTET_STRING"); + case 58: { + LogStep(58, "Write attribute NULLABLE_OCTET_STRING"); ListFreer listFreer; chip::app::DataModel::Nullable value; value.SetNull(); return WriteAttribute(kIdentityAlpha, GetEndpoint(1), UnitTesting::Id, UnitTesting::Attributes::NullableOctetString::Id, value, chip::NullOptional, chip::NullOptional); } - case 55: { - LogStep(55, "Read attribute NULLABLE_OCTET_STRING"); + case 59: { + LogStep(59, "Read attribute NULLABLE_OCTET_STRING"); return ReadAttribute(kIdentityAlpha, GetEndpoint(1), UnitTesting::Id, UnitTesting::Attributes::NullableOctetString::Id, true, chip::NullOptional); } - case 56: { - LogStep(56, "Write attribute NULLABLE_OCTET_STRING back to Default Value"); + case 60: { + LogStep(60, "Write attribute NULLABLE_OCTET_STRING back to Default Value"); ListFreer listFreer; chip::app::DataModel::Nullable value; value.SetNonNull(); diff --git a/zzz_generated/darwin-framework-tool/zap-generated/cluster/Commands.h b/zzz_generated/darwin-framework-tool/zap-generated/cluster/Commands.h index a0ad2c6fd475b1..16b8371bd637f3 100644 --- a/zzz_generated/darwin-framework-tool/zap-generated/cluster/Commands.h +++ b/zzz_generated/darwin-framework-tool/zap-generated/cluster/Commands.h @@ -45032,1056 +45032,6 @@ class SubscribeAttributeOperationalStateClusterRevision : public SubscribeAttrib } }; -/*----------------------------------------------------------------------------*\ -| Cluster RvcOperationalState | 0x0061 | -|------------------------------------------------------------------------------| -| Commands: | | -| * Pause | 0x00 | -| * Stop | 0x01 | -| * Start | 0x02 | -| * Resume | 0x03 | -|------------------------------------------------------------------------------| -| Attributes: | | -| * PhaseList | 0x0000 | -| * CurrentPhase | 0x0001 | -| * CountdownTime | 0x0002 | -| * OperationalStateList | 0x0003 | -| * OperationalState | 0x0004 | -| * OperationalError | 0x0005 | -| * GeneratedCommandList | 0xFFF8 | -| * AcceptedCommandList | 0xFFF9 | -| * EventList | 0xFFFA | -| * AttributeList | 0xFFFB | -| * FeatureMap | 0xFFFC | -| * ClusterRevision | 0xFFFD | -|------------------------------------------------------------------------------| -| Events: | | -| * OperationalError | 0x0000 | -| * OperationCompletion | 0x0001 | -\*----------------------------------------------------------------------------*/ - -/* - * Command Pause - */ -class RvcOperationalStatePause : public ClusterCommand { -public: - RvcOperationalStatePause() - : ClusterCommand("pause") - { - ClusterCommand::AddArguments(); - } - - CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override - { - ChipLogProgress(chipTool, "Sending cluster (0x00000061) command (0x00000000) on endpoint %u", endpointId); - - dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL); - __auto_type * cluster = [[MTRBaseClusterRVCOperationalState alloc] initWithDevice:device - endpointID:@(endpointId) - queue:callbackQueue]; - __auto_type * params = [[MTRRVCOperationalStateClusterPauseParams alloc] init]; - params.timedInvokeTimeoutMs - = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil; - uint16_t repeatCount = mRepeatCount.ValueOr(1); - uint16_t __block responsesNeeded = repeatCount; - while (repeatCount--) { - [cluster pauseWithParams:params - completion:^(MTRRVCOperationalStateClusterOperationalCommandResponseParams * _Nullable values, - NSError * _Nullable error) { - NSLog(@"Values: %@", values); - responsesNeeded--; - if (error != nil) { - mError = error; - LogNSError("Error", error); - } - if (responsesNeeded == 0) { - SetCommandExitStatus(mError); - } - }]; - } - return CHIP_NO_ERROR; - } - -private: -}; - -/* - * Command Stop - */ -class RvcOperationalStateStop : public ClusterCommand { -public: - RvcOperationalStateStop() - : ClusterCommand("stop") - { - ClusterCommand::AddArguments(); - } - - CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override - { - ChipLogProgress(chipTool, "Sending cluster (0x00000061) command (0x00000001) on endpoint %u", endpointId); - - dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL); - __auto_type * cluster = [[MTRBaseClusterRVCOperationalState alloc] initWithDevice:device - endpointID:@(endpointId) - queue:callbackQueue]; - __auto_type * params = [[MTRRVCOperationalStateClusterStopParams alloc] init]; - params.timedInvokeTimeoutMs - = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil; - uint16_t repeatCount = mRepeatCount.ValueOr(1); - uint16_t __block responsesNeeded = repeatCount; - while (repeatCount--) { - [cluster stopWithParams:params - completion:^(MTRRVCOperationalStateClusterOperationalCommandResponseParams * _Nullable values, - NSError * _Nullable error) { - NSLog(@"Values: %@", values); - responsesNeeded--; - if (error != nil) { - mError = error; - LogNSError("Error", error); - } - if (responsesNeeded == 0) { - SetCommandExitStatus(mError); - } - }]; - } - return CHIP_NO_ERROR; - } - -private: -}; - -/* - * Command Start - */ -class RvcOperationalStateStart : public ClusterCommand { -public: - RvcOperationalStateStart() - : ClusterCommand("start") - { - ClusterCommand::AddArguments(); - } - - CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override - { - ChipLogProgress(chipTool, "Sending cluster (0x00000061) command (0x00000002) on endpoint %u", endpointId); - - dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL); - __auto_type * cluster = [[MTRBaseClusterRVCOperationalState alloc] initWithDevice:device - endpointID:@(endpointId) - queue:callbackQueue]; - __auto_type * params = [[MTRRVCOperationalStateClusterStartParams alloc] init]; - params.timedInvokeTimeoutMs - = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil; - uint16_t repeatCount = mRepeatCount.ValueOr(1); - uint16_t __block responsesNeeded = repeatCount; - while (repeatCount--) { - [cluster startWithParams:params - completion:^(MTRRVCOperationalStateClusterOperationalCommandResponseParams * _Nullable values, - NSError * _Nullable error) { - NSLog(@"Values: %@", values); - responsesNeeded--; - if (error != nil) { - mError = error; - LogNSError("Error", error); - } - if (responsesNeeded == 0) { - SetCommandExitStatus(mError); - } - }]; - } - return CHIP_NO_ERROR; - } - -private: -}; - -/* - * Command Resume - */ -class RvcOperationalStateResume : public ClusterCommand { -public: - RvcOperationalStateResume() - : ClusterCommand("resume") - { - ClusterCommand::AddArguments(); - } - - CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override - { - ChipLogProgress(chipTool, "Sending cluster (0x00000061) command (0x00000003) on endpoint %u", endpointId); - - dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL); - __auto_type * cluster = [[MTRBaseClusterRVCOperationalState alloc] initWithDevice:device - endpointID:@(endpointId) - queue:callbackQueue]; - __auto_type * params = [[MTRRVCOperationalStateClusterResumeParams alloc] init]; - params.timedInvokeTimeoutMs - = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil; - uint16_t repeatCount = mRepeatCount.ValueOr(1); - uint16_t __block responsesNeeded = repeatCount; - while (repeatCount--) { - [cluster resumeWithParams:params - completion:^(MTRRVCOperationalStateClusterOperationalCommandResponseParams * _Nullable values, - NSError * _Nullable error) { - NSLog(@"Values: %@", values); - responsesNeeded--; - if (error != nil) { - mError = error; - LogNSError("Error", error); - } - if (responsesNeeded == 0) { - SetCommandExitStatus(mError); - } - }]; - } - return CHIP_NO_ERROR; - } - -private: -}; - -/* - * Attribute PhaseList - */ -class ReadRvcOperationalStatePhaseList : public ReadAttribute { -public: - ReadRvcOperationalStatePhaseList() - : ReadAttribute("phase-list") - { - } - - ~ReadRvcOperationalStatePhaseList() {} - - CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override - { - ChipLogProgress(chipTool, "Sending cluster (0x00000061) ReadAttribute (0x00000000) on endpoint %u", endpointId); - - dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL); - __auto_type * cluster = [[MTRBaseClusterRVCOperationalState alloc] initWithDevice:device - endpointID:@(endpointId) - queue:callbackQueue]; - [cluster readAttributePhaseListWithCompletion:^(NSArray * _Nullable value, NSError * _Nullable error) { - NSLog(@"RVCOperationalState.PhaseList response %@", [value description]); - if (error != nil) { - LogNSError("RVCOperationalState PhaseList read Error", error); - } - SetCommandExitStatus(error); - }]; - return CHIP_NO_ERROR; - } -}; - -class SubscribeAttributeRvcOperationalStatePhaseList : public SubscribeAttribute { -public: - SubscribeAttributeRvcOperationalStatePhaseList() - : SubscribeAttribute("phase-list") - { - } - - ~SubscribeAttributeRvcOperationalStatePhaseList() {} - - CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override - { - ChipLogProgress(chipTool, "Sending cluster (0x00000061) ReportAttribute (0x00000000) on endpoint %u", endpointId); - dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL); - __auto_type * cluster = [[MTRBaseClusterRVCOperationalState alloc] initWithDevice:device - endpointID:@(endpointId) - queue:callbackQueue]; - __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)]; - if (mKeepSubscriptions.HasValue()) { - params.replaceExistingSubscriptions = !mKeepSubscriptions.Value(); - } - if (mFabricFiltered.HasValue()) { - params.filterByFabric = mFabricFiltered.Value(); - } - if (mAutoResubscribe.HasValue()) { - params.resubscribeAutomatically = mAutoResubscribe.Value(); - } - [cluster subscribeAttributePhaseListWithParams:params - subscriptionEstablished:^() { - mSubscriptionEstablished = YES; - } - reportHandler:^(NSArray * _Nullable value, NSError * _Nullable error) { - NSLog(@"RVCOperationalState.PhaseList response %@", [value description]); - SetCommandExitStatus(error); - }]; - - return CHIP_NO_ERROR; - } -}; - -/* - * Attribute CurrentPhase - */ -class ReadRvcOperationalStateCurrentPhase : public ReadAttribute { -public: - ReadRvcOperationalStateCurrentPhase() - : ReadAttribute("current-phase") - { - } - - ~ReadRvcOperationalStateCurrentPhase() {} - - CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override - { - ChipLogProgress(chipTool, "Sending cluster (0x00000061) ReadAttribute (0x00000001) on endpoint %u", endpointId); - - dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL); - __auto_type * cluster = [[MTRBaseClusterRVCOperationalState alloc] initWithDevice:device - endpointID:@(endpointId) - queue:callbackQueue]; - [cluster readAttributeCurrentPhaseWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) { - NSLog(@"RVCOperationalState.CurrentPhase response %@", [value description]); - if (error != nil) { - LogNSError("RVCOperationalState CurrentPhase read Error", error); - } - SetCommandExitStatus(error); - }]; - return CHIP_NO_ERROR; - } -}; - -class SubscribeAttributeRvcOperationalStateCurrentPhase : public SubscribeAttribute { -public: - SubscribeAttributeRvcOperationalStateCurrentPhase() - : SubscribeAttribute("current-phase") - { - } - - ~SubscribeAttributeRvcOperationalStateCurrentPhase() {} - - CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override - { - ChipLogProgress(chipTool, "Sending cluster (0x00000061) ReportAttribute (0x00000001) on endpoint %u", endpointId); - dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL); - __auto_type * cluster = [[MTRBaseClusterRVCOperationalState alloc] initWithDevice:device - endpointID:@(endpointId) - queue:callbackQueue]; - __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)]; - if (mKeepSubscriptions.HasValue()) { - params.replaceExistingSubscriptions = !mKeepSubscriptions.Value(); - } - if (mFabricFiltered.HasValue()) { - params.filterByFabric = mFabricFiltered.Value(); - } - if (mAutoResubscribe.HasValue()) { - params.resubscribeAutomatically = mAutoResubscribe.Value(); - } - [cluster subscribeAttributeCurrentPhaseWithParams:params - subscriptionEstablished:^() { - mSubscriptionEstablished = YES; - } - reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) { - NSLog(@"RVCOperationalState.CurrentPhase response %@", [value description]); - SetCommandExitStatus(error); - }]; - - return CHIP_NO_ERROR; - } -}; - -/* - * Attribute CountdownTime - */ -class ReadRvcOperationalStateCountdownTime : public ReadAttribute { -public: - ReadRvcOperationalStateCountdownTime() - : ReadAttribute("countdown-time") - { - } - - ~ReadRvcOperationalStateCountdownTime() {} - - CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override - { - ChipLogProgress(chipTool, "Sending cluster (0x00000061) ReadAttribute (0x00000002) on endpoint %u", endpointId); - - dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL); - __auto_type * cluster = [[MTRBaseClusterRVCOperationalState alloc] initWithDevice:device - endpointID:@(endpointId) - queue:callbackQueue]; - [cluster readAttributeCountdownTimeWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) { - NSLog(@"RVCOperationalState.CountdownTime response %@", [value description]); - if (error != nil) { - LogNSError("RVCOperationalState CountdownTime read Error", error); - } - SetCommandExitStatus(error); - }]; - return CHIP_NO_ERROR; - } -}; - -class SubscribeAttributeRvcOperationalStateCountdownTime : public SubscribeAttribute { -public: - SubscribeAttributeRvcOperationalStateCountdownTime() - : SubscribeAttribute("countdown-time") - { - } - - ~SubscribeAttributeRvcOperationalStateCountdownTime() {} - - CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override - { - ChipLogProgress(chipTool, "Sending cluster (0x00000061) ReportAttribute (0x00000002) on endpoint %u", endpointId); - dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL); - __auto_type * cluster = [[MTRBaseClusterRVCOperationalState alloc] initWithDevice:device - endpointID:@(endpointId) - queue:callbackQueue]; - __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)]; - if (mKeepSubscriptions.HasValue()) { - params.replaceExistingSubscriptions = !mKeepSubscriptions.Value(); - } - if (mFabricFiltered.HasValue()) { - params.filterByFabric = mFabricFiltered.Value(); - } - if (mAutoResubscribe.HasValue()) { - params.resubscribeAutomatically = mAutoResubscribe.Value(); - } - [cluster subscribeAttributeCountdownTimeWithParams:params - subscriptionEstablished:^() { - mSubscriptionEstablished = YES; - } - reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) { - NSLog(@"RVCOperationalState.CountdownTime response %@", [value description]); - SetCommandExitStatus(error); - }]; - - return CHIP_NO_ERROR; - } -}; - -/* - * Attribute OperationalStateList - */ -class ReadRvcOperationalStateOperationalStateList : public ReadAttribute { -public: - ReadRvcOperationalStateOperationalStateList() - : ReadAttribute("operational-state-list") - { - } - - ~ReadRvcOperationalStateOperationalStateList() {} - - CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override - { - ChipLogProgress(chipTool, "Sending cluster (0x00000061) ReadAttribute (0x00000003) on endpoint %u", endpointId); - - dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL); - __auto_type * cluster = [[MTRBaseClusterRVCOperationalState alloc] initWithDevice:device - endpointID:@(endpointId) - queue:callbackQueue]; - [cluster readAttributeOperationalStateListWithCompletion:^(NSArray * _Nullable value, NSError * _Nullable error) { - NSLog(@"RVCOperationalState.OperationalStateList response %@", [value description]); - if (error != nil) { - LogNSError("RVCOperationalState OperationalStateList read Error", error); - } - SetCommandExitStatus(error); - }]; - return CHIP_NO_ERROR; - } -}; - -class SubscribeAttributeRvcOperationalStateOperationalStateList : public SubscribeAttribute { -public: - SubscribeAttributeRvcOperationalStateOperationalStateList() - : SubscribeAttribute("operational-state-list") - { - } - - ~SubscribeAttributeRvcOperationalStateOperationalStateList() {} - - CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override - { - ChipLogProgress(chipTool, "Sending cluster (0x00000061) ReportAttribute (0x00000003) on endpoint %u", endpointId); - dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL); - __auto_type * cluster = [[MTRBaseClusterRVCOperationalState alloc] initWithDevice:device - endpointID:@(endpointId) - queue:callbackQueue]; - __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)]; - if (mKeepSubscriptions.HasValue()) { - params.replaceExistingSubscriptions = !mKeepSubscriptions.Value(); - } - if (mFabricFiltered.HasValue()) { - params.filterByFabric = mFabricFiltered.Value(); - } - if (mAutoResubscribe.HasValue()) { - params.resubscribeAutomatically = mAutoResubscribe.Value(); - } - [cluster subscribeAttributeOperationalStateListWithParams:params - subscriptionEstablished:^() { - mSubscriptionEstablished = YES; - } - reportHandler:^(NSArray * _Nullable value, NSError * _Nullable error) { - NSLog(@"RVCOperationalState.OperationalStateList response %@", [value description]); - SetCommandExitStatus(error); - }]; - - return CHIP_NO_ERROR; - } -}; - -/* - * Attribute OperationalState - */ -class ReadRvcOperationalStateOperationalState : public ReadAttribute { -public: - ReadRvcOperationalStateOperationalState() - : ReadAttribute("operational-state") - { - } - - ~ReadRvcOperationalStateOperationalState() {} - - CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override - { - ChipLogProgress(chipTool, "Sending cluster (0x00000061) ReadAttribute (0x00000004) on endpoint %u", endpointId); - - dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL); - __auto_type * cluster = [[MTRBaseClusterRVCOperationalState alloc] initWithDevice:device - endpointID:@(endpointId) - queue:callbackQueue]; - [cluster readAttributeOperationalStateWithCompletion:^( - MTRRVCOperationalStateClusterOperationalStateStruct * _Nullable value, NSError * _Nullable error) { - NSLog(@"RVCOperationalState.OperationalState response %@", [value description]); - if (error != nil) { - LogNSError("RVCOperationalState OperationalState read Error", error); - } - SetCommandExitStatus(error); - }]; - return CHIP_NO_ERROR; - } -}; - -class SubscribeAttributeRvcOperationalStateOperationalState : public SubscribeAttribute { -public: - SubscribeAttributeRvcOperationalStateOperationalState() - : SubscribeAttribute("operational-state") - { - } - - ~SubscribeAttributeRvcOperationalStateOperationalState() {} - - CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override - { - ChipLogProgress(chipTool, "Sending cluster (0x00000061) ReportAttribute (0x00000004) on endpoint %u", endpointId); - dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL); - __auto_type * cluster = [[MTRBaseClusterRVCOperationalState alloc] initWithDevice:device - endpointID:@(endpointId) - queue:callbackQueue]; - __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)]; - if (mKeepSubscriptions.HasValue()) { - params.replaceExistingSubscriptions = !mKeepSubscriptions.Value(); - } - if (mFabricFiltered.HasValue()) { - params.filterByFabric = mFabricFiltered.Value(); - } - if (mAutoResubscribe.HasValue()) { - params.resubscribeAutomatically = mAutoResubscribe.Value(); - } - [cluster subscribeAttributeOperationalStateWithParams:params - subscriptionEstablished:^() { - mSubscriptionEstablished = YES; - } - reportHandler:^(MTRRVCOperationalStateClusterOperationalStateStruct * _Nullable value, NSError * _Nullable error) { - NSLog(@"RVCOperationalState.OperationalState response %@", [value description]); - SetCommandExitStatus(error); - }]; - - return CHIP_NO_ERROR; - } -}; - -/* - * Attribute OperationalError - */ -class ReadRvcOperationalStateOperationalError : public ReadAttribute { -public: - ReadRvcOperationalStateOperationalError() - : ReadAttribute("operational-error") - { - } - - ~ReadRvcOperationalStateOperationalError() {} - - CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override - { - ChipLogProgress(chipTool, "Sending cluster (0x00000061) ReadAttribute (0x00000005) on endpoint %u", endpointId); - - dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL); - __auto_type * cluster = [[MTRBaseClusterRVCOperationalState alloc] initWithDevice:device - endpointID:@(endpointId) - queue:callbackQueue]; - [cluster readAttributeOperationalErrorWithCompletion:^( - MTRRVCOperationalStateClusterErrorStateStruct * _Nullable value, NSError * _Nullable error) { - NSLog(@"RVCOperationalState.OperationalError response %@", [value description]); - if (error != nil) { - LogNSError("RVCOperationalState OperationalError read Error", error); - } - SetCommandExitStatus(error); - }]; - return CHIP_NO_ERROR; - } -}; - -class SubscribeAttributeRvcOperationalStateOperationalError : public SubscribeAttribute { -public: - SubscribeAttributeRvcOperationalStateOperationalError() - : SubscribeAttribute("operational-error") - { - } - - ~SubscribeAttributeRvcOperationalStateOperationalError() {} - - CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override - { - ChipLogProgress(chipTool, "Sending cluster (0x00000061) ReportAttribute (0x00000005) on endpoint %u", endpointId); - dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL); - __auto_type * cluster = [[MTRBaseClusterRVCOperationalState alloc] initWithDevice:device - endpointID:@(endpointId) - queue:callbackQueue]; - __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)]; - if (mKeepSubscriptions.HasValue()) { - params.replaceExistingSubscriptions = !mKeepSubscriptions.Value(); - } - if (mFabricFiltered.HasValue()) { - params.filterByFabric = mFabricFiltered.Value(); - } - if (mAutoResubscribe.HasValue()) { - params.resubscribeAutomatically = mAutoResubscribe.Value(); - } - [cluster subscribeAttributeOperationalErrorWithParams:params - subscriptionEstablished:^() { - mSubscriptionEstablished = YES; - } - reportHandler:^(MTRRVCOperationalStateClusterErrorStateStruct * _Nullable value, NSError * _Nullable error) { - NSLog(@"RVCOperationalState.OperationalError response %@", [value description]); - SetCommandExitStatus(error); - }]; - - return CHIP_NO_ERROR; - } -}; - -/* - * Attribute GeneratedCommandList - */ -class ReadRvcOperationalStateGeneratedCommandList : public ReadAttribute { -public: - ReadRvcOperationalStateGeneratedCommandList() - : ReadAttribute("generated-command-list") - { - } - - ~ReadRvcOperationalStateGeneratedCommandList() {} - - CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override - { - ChipLogProgress(chipTool, "Sending cluster (0x00000061) ReadAttribute (0x0000FFF8) on endpoint %u", endpointId); - - dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL); - __auto_type * cluster = [[MTRBaseClusterRVCOperationalState alloc] initWithDevice:device - endpointID:@(endpointId) - queue:callbackQueue]; - [cluster readAttributeGeneratedCommandListWithCompletion:^(NSArray * _Nullable value, NSError * _Nullable error) { - NSLog(@"RVCOperationalState.GeneratedCommandList response %@", [value description]); - if (error != nil) { - LogNSError("RVCOperationalState GeneratedCommandList read Error", error); - } - SetCommandExitStatus(error); - }]; - return CHIP_NO_ERROR; - } -}; - -class SubscribeAttributeRvcOperationalStateGeneratedCommandList : public SubscribeAttribute { -public: - SubscribeAttributeRvcOperationalStateGeneratedCommandList() - : SubscribeAttribute("generated-command-list") - { - } - - ~SubscribeAttributeRvcOperationalStateGeneratedCommandList() {} - - CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override - { - ChipLogProgress(chipTool, "Sending cluster (0x00000061) ReportAttribute (0x0000FFF8) on endpoint %u", endpointId); - dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL); - __auto_type * cluster = [[MTRBaseClusterRVCOperationalState alloc] initWithDevice:device - endpointID:@(endpointId) - queue:callbackQueue]; - __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)]; - if (mKeepSubscriptions.HasValue()) { - params.replaceExistingSubscriptions = !mKeepSubscriptions.Value(); - } - if (mFabricFiltered.HasValue()) { - params.filterByFabric = mFabricFiltered.Value(); - } - if (mAutoResubscribe.HasValue()) { - params.resubscribeAutomatically = mAutoResubscribe.Value(); - } - [cluster subscribeAttributeGeneratedCommandListWithParams:params - subscriptionEstablished:^() { - mSubscriptionEstablished = YES; - } - reportHandler:^(NSArray * _Nullable value, NSError * _Nullable error) { - NSLog(@"RVCOperationalState.GeneratedCommandList response %@", [value description]); - SetCommandExitStatus(error); - }]; - - return CHIP_NO_ERROR; - } -}; - -/* - * Attribute AcceptedCommandList - */ -class ReadRvcOperationalStateAcceptedCommandList : public ReadAttribute { -public: - ReadRvcOperationalStateAcceptedCommandList() - : ReadAttribute("accepted-command-list") - { - } - - ~ReadRvcOperationalStateAcceptedCommandList() {} - - CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override - { - ChipLogProgress(chipTool, "Sending cluster (0x00000061) ReadAttribute (0x0000FFF9) on endpoint %u", endpointId); - - dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL); - __auto_type * cluster = [[MTRBaseClusterRVCOperationalState alloc] initWithDevice:device - endpointID:@(endpointId) - queue:callbackQueue]; - [cluster readAttributeAcceptedCommandListWithCompletion:^(NSArray * _Nullable value, NSError * _Nullable error) { - NSLog(@"RVCOperationalState.AcceptedCommandList response %@", [value description]); - if (error != nil) { - LogNSError("RVCOperationalState AcceptedCommandList read Error", error); - } - SetCommandExitStatus(error); - }]; - return CHIP_NO_ERROR; - } -}; - -class SubscribeAttributeRvcOperationalStateAcceptedCommandList : public SubscribeAttribute { -public: - SubscribeAttributeRvcOperationalStateAcceptedCommandList() - : SubscribeAttribute("accepted-command-list") - { - } - - ~SubscribeAttributeRvcOperationalStateAcceptedCommandList() {} - - CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override - { - ChipLogProgress(chipTool, "Sending cluster (0x00000061) ReportAttribute (0x0000FFF9) on endpoint %u", endpointId); - dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL); - __auto_type * cluster = [[MTRBaseClusterRVCOperationalState alloc] initWithDevice:device - endpointID:@(endpointId) - queue:callbackQueue]; - __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)]; - if (mKeepSubscriptions.HasValue()) { - params.replaceExistingSubscriptions = !mKeepSubscriptions.Value(); - } - if (mFabricFiltered.HasValue()) { - params.filterByFabric = mFabricFiltered.Value(); - } - if (mAutoResubscribe.HasValue()) { - params.resubscribeAutomatically = mAutoResubscribe.Value(); - } - [cluster subscribeAttributeAcceptedCommandListWithParams:params - subscriptionEstablished:^() { - mSubscriptionEstablished = YES; - } - reportHandler:^(NSArray * _Nullable value, NSError * _Nullable error) { - NSLog(@"RVCOperationalState.AcceptedCommandList response %@", [value description]); - SetCommandExitStatus(error); - }]; - - return CHIP_NO_ERROR; - } -}; - -/* - * Attribute EventList - */ -class ReadRvcOperationalStateEventList : public ReadAttribute { -public: - ReadRvcOperationalStateEventList() - : ReadAttribute("event-list") - { - } - - ~ReadRvcOperationalStateEventList() {} - - CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override - { - ChipLogProgress(chipTool, "Sending cluster (0x00000061) ReadAttribute (0x0000FFFA) on endpoint %u", endpointId); - - dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL); - __auto_type * cluster = [[MTRBaseClusterRVCOperationalState alloc] initWithDevice:device - endpointID:@(endpointId) - queue:callbackQueue]; - [cluster readAttributeEventListWithCompletion:^(NSArray * _Nullable value, NSError * _Nullable error) { - NSLog(@"RVCOperationalState.EventList response %@", [value description]); - if (error != nil) { - LogNSError("RVCOperationalState EventList read Error", error); - } - SetCommandExitStatus(error); - }]; - return CHIP_NO_ERROR; - } -}; - -class SubscribeAttributeRvcOperationalStateEventList : public SubscribeAttribute { -public: - SubscribeAttributeRvcOperationalStateEventList() - : SubscribeAttribute("event-list") - { - } - - ~SubscribeAttributeRvcOperationalStateEventList() {} - - CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override - { - ChipLogProgress(chipTool, "Sending cluster (0x00000061) ReportAttribute (0x0000FFFA) on endpoint %u", endpointId); - dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL); - __auto_type * cluster = [[MTRBaseClusterRVCOperationalState alloc] initWithDevice:device - endpointID:@(endpointId) - queue:callbackQueue]; - __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)]; - if (mKeepSubscriptions.HasValue()) { - params.replaceExistingSubscriptions = !mKeepSubscriptions.Value(); - } - if (mFabricFiltered.HasValue()) { - params.filterByFabric = mFabricFiltered.Value(); - } - if (mAutoResubscribe.HasValue()) { - params.resubscribeAutomatically = mAutoResubscribe.Value(); - } - [cluster subscribeAttributeEventListWithParams:params - subscriptionEstablished:^() { - mSubscriptionEstablished = YES; - } - reportHandler:^(NSArray * _Nullable value, NSError * _Nullable error) { - NSLog(@"RVCOperationalState.EventList response %@", [value description]); - SetCommandExitStatus(error); - }]; - - return CHIP_NO_ERROR; - } -}; - -/* - * Attribute AttributeList - */ -class ReadRvcOperationalStateAttributeList : public ReadAttribute { -public: - ReadRvcOperationalStateAttributeList() - : ReadAttribute("attribute-list") - { - } - - ~ReadRvcOperationalStateAttributeList() {} - - CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override - { - ChipLogProgress(chipTool, "Sending cluster (0x00000061) ReadAttribute (0x0000FFFB) on endpoint %u", endpointId); - - dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL); - __auto_type * cluster = [[MTRBaseClusterRVCOperationalState alloc] initWithDevice:device - endpointID:@(endpointId) - queue:callbackQueue]; - [cluster readAttributeAttributeListWithCompletion:^(NSArray * _Nullable value, NSError * _Nullable error) { - NSLog(@"RVCOperationalState.AttributeList response %@", [value description]); - if (error != nil) { - LogNSError("RVCOperationalState AttributeList read Error", error); - } - SetCommandExitStatus(error); - }]; - return CHIP_NO_ERROR; - } -}; - -class SubscribeAttributeRvcOperationalStateAttributeList : public SubscribeAttribute { -public: - SubscribeAttributeRvcOperationalStateAttributeList() - : SubscribeAttribute("attribute-list") - { - } - - ~SubscribeAttributeRvcOperationalStateAttributeList() {} - - CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override - { - ChipLogProgress(chipTool, "Sending cluster (0x00000061) ReportAttribute (0x0000FFFB) on endpoint %u", endpointId); - dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL); - __auto_type * cluster = [[MTRBaseClusterRVCOperationalState alloc] initWithDevice:device - endpointID:@(endpointId) - queue:callbackQueue]; - __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)]; - if (mKeepSubscriptions.HasValue()) { - params.replaceExistingSubscriptions = !mKeepSubscriptions.Value(); - } - if (mFabricFiltered.HasValue()) { - params.filterByFabric = mFabricFiltered.Value(); - } - if (mAutoResubscribe.HasValue()) { - params.resubscribeAutomatically = mAutoResubscribe.Value(); - } - [cluster subscribeAttributeAttributeListWithParams:params - subscriptionEstablished:^() { - mSubscriptionEstablished = YES; - } - reportHandler:^(NSArray * _Nullable value, NSError * _Nullable error) { - NSLog(@"RVCOperationalState.AttributeList response %@", [value description]); - SetCommandExitStatus(error); - }]; - - return CHIP_NO_ERROR; - } -}; - -/* - * Attribute FeatureMap - */ -class ReadRvcOperationalStateFeatureMap : public ReadAttribute { -public: - ReadRvcOperationalStateFeatureMap() - : ReadAttribute("feature-map") - { - } - - ~ReadRvcOperationalStateFeatureMap() {} - - CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override - { - ChipLogProgress(chipTool, "Sending cluster (0x00000061) ReadAttribute (0x0000FFFC) on endpoint %u", endpointId); - - dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL); - __auto_type * cluster = [[MTRBaseClusterRVCOperationalState alloc] initWithDevice:device - endpointID:@(endpointId) - queue:callbackQueue]; - [cluster readAttributeFeatureMapWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) { - NSLog(@"RVCOperationalState.FeatureMap response %@", [value description]); - if (error != nil) { - LogNSError("RVCOperationalState FeatureMap read Error", error); - } - SetCommandExitStatus(error); - }]; - return CHIP_NO_ERROR; - } -}; - -class SubscribeAttributeRvcOperationalStateFeatureMap : public SubscribeAttribute { -public: - SubscribeAttributeRvcOperationalStateFeatureMap() - : SubscribeAttribute("feature-map") - { - } - - ~SubscribeAttributeRvcOperationalStateFeatureMap() {} - - CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override - { - ChipLogProgress(chipTool, "Sending cluster (0x00000061) ReportAttribute (0x0000FFFC) on endpoint %u", endpointId); - dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL); - __auto_type * cluster = [[MTRBaseClusterRVCOperationalState alloc] initWithDevice:device - endpointID:@(endpointId) - queue:callbackQueue]; - __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)]; - if (mKeepSubscriptions.HasValue()) { - params.replaceExistingSubscriptions = !mKeepSubscriptions.Value(); - } - if (mFabricFiltered.HasValue()) { - params.filterByFabric = mFabricFiltered.Value(); - } - if (mAutoResubscribe.HasValue()) { - params.resubscribeAutomatically = mAutoResubscribe.Value(); - } - [cluster subscribeAttributeFeatureMapWithParams:params - subscriptionEstablished:^() { - mSubscriptionEstablished = YES; - } - reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) { - NSLog(@"RVCOperationalState.FeatureMap response %@", [value description]); - SetCommandExitStatus(error); - }]; - - return CHIP_NO_ERROR; - } -}; - -/* - * Attribute ClusterRevision - */ -class ReadRvcOperationalStateClusterRevision : public ReadAttribute { -public: - ReadRvcOperationalStateClusterRevision() - : ReadAttribute("cluster-revision") - { - } - - ~ReadRvcOperationalStateClusterRevision() {} - - CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override - { - ChipLogProgress(chipTool, "Sending cluster (0x00000061) ReadAttribute (0x0000FFFD) on endpoint %u", endpointId); - - dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL); - __auto_type * cluster = [[MTRBaseClusterRVCOperationalState alloc] initWithDevice:device - endpointID:@(endpointId) - queue:callbackQueue]; - [cluster readAttributeClusterRevisionWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) { - NSLog(@"RVCOperationalState.ClusterRevision response %@", [value description]); - if (error != nil) { - LogNSError("RVCOperationalState ClusterRevision read Error", error); - } - SetCommandExitStatus(error); - }]; - return CHIP_NO_ERROR; - } -}; - -class SubscribeAttributeRvcOperationalStateClusterRevision : public SubscribeAttribute { -public: - SubscribeAttributeRvcOperationalStateClusterRevision() - : SubscribeAttribute("cluster-revision") - { - } - - ~SubscribeAttributeRvcOperationalStateClusterRevision() {} - - CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override - { - ChipLogProgress(chipTool, "Sending cluster (0x00000061) ReportAttribute (0x0000FFFD) on endpoint %u", endpointId); - dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL); - __auto_type * cluster = [[MTRBaseClusterRVCOperationalState alloc] initWithDevice:device - endpointID:@(endpointId) - queue:callbackQueue]; - __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)]; - if (mKeepSubscriptions.HasValue()) { - params.replaceExistingSubscriptions = !mKeepSubscriptions.Value(); - } - if (mFabricFiltered.HasValue()) { - params.filterByFabric = mFabricFiltered.Value(); - } - if (mAutoResubscribe.HasValue()) { - params.resubscribeAutomatically = mAutoResubscribe.Value(); - } - [cluster subscribeAttributeClusterRevisionWithParams:params - subscriptionEstablished:^() { - mSubscriptionEstablished = YES; - } - reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) { - NSLog(@"RVCOperationalState.ClusterRevision response %@", [value description]); - SetCommandExitStatus(error); - }]; - - return CHIP_NO_ERROR; - } -}; - /*----------------------------------------------------------------------------*\ | Cluster HepaFilterMonitoring | 0x0071 | |------------------------------------------------------------------------------| @@ -123645,51 +122595,6 @@ void registerClusterOperationalState(Commands & commands) commands.Register(clusterName, clusterCommands); } -void registerClusterRvcOperationalState(Commands & commands) -{ - using namespace chip::app::Clusters::RvcOperationalState; - - const char * clusterName = "RvcOperationalState"; - - commands_list clusterCommands = { - make_unique(Id), // - make_unique(), // - make_unique(), // - make_unique(), // - make_unique(), // - make_unique(Id), // - make_unique(), // - make_unique(Id), // - make_unique(Id), // - make_unique(), // - make_unique(), // - make_unique(), // - make_unique(), // - make_unique(), // - make_unique(), // - make_unique(), // - make_unique(), // - make_unique(), // - make_unique(), // - make_unique(), // - make_unique(), // - make_unique(), // - make_unique(), // - make_unique(), // - make_unique(), // - make_unique(), // - make_unique(), // - make_unique(), // - make_unique(), // - make_unique(), // - make_unique(), // - make_unique(), // - make_unique(Id), // - make_unique(Id), // - }; - - commands.Register(clusterName, clusterCommands); -} void registerClusterHepaFilterMonitoring(Commands & commands) { using namespace chip::app::Clusters::HepaFilterMonitoring; @@ -126396,7 +125301,6 @@ void registerClusters(Commands & commands) registerClusterAirQuality(commands); registerClusterSmokeCoAlarm(commands); registerClusterOperationalState(commands); - registerClusterRvcOperationalState(commands); registerClusterHepaFilterMonitoring(commands); registerClusterActivatedCarbonFilterMonitoring(commands); registerClusterDoorLock(commands); diff --git a/zzz_generated/darwin-framework-tool/zap-generated/test/Commands.h b/zzz_generated/darwin-framework-tool/zap-generated/test/Commands.h index 908c734985d6c9..b5e5873650ad46 100644 --- a/zzz_generated/darwin-framework-tool/zap-generated/test/Commands.h +++ b/zzz_generated/darwin-framework-tool/zap-generated/test/Commands.h @@ -119418,52 +119418,68 @@ class TestConstraints : public TestCommandBridge { err = TestWriteAttributeCharStringValueBackToDefaultValue_44(); break; case 45: - ChipLogProgress(chipTool, " ***** Test Step 45 : Read attribute NULLABLE_INT8U Default Value\n"); - err = TestReadAttributeNullableInt8uDefaultValue_45(); + ChipLogProgress(chipTool, " ***** Test Step 45 : Write attribute NULLABLE_CHAR_STRING Value\n"); + err = TestWriteAttributeNullableCharStringValue_45(); break; case 46: - ChipLogProgress(chipTool, " ***** Test Step 46 : Write attribute NULLABLE_INT8U with a value\n"); - err = TestWriteAttributeNullableInt8uWithAValue_46(); + ChipLogProgress(chipTool, " ***** Test Step 46 : Read attribute NULLABLE_CHAR_STRING Value MinLength Constraints\n"); + err = TestReadAttributeNullableCharStringValueMinLengthConstraints_46(); break; case 47: - ChipLogProgress(chipTool, " ***** Test Step 47 : Read attribute NULLABLE_INT8U with a value\n"); - err = TestReadAttributeNullableInt8uWithAValue_47(); + ChipLogProgress(chipTool, " ***** Test Step 47 : Read attribute NULLABLE_CHAR_STRING Value MaxLength Constraints\n"); + err = TestReadAttributeNullableCharStringValueMaxLengthConstraints_47(); break; case 48: - ChipLogProgress(chipTool, " ***** Test Step 48 : Write attribute NULLABLE_INT8U without a value\n"); - err = TestWriteAttributeNullableInt8uWithoutAValue_48(); + ChipLogProgress(chipTool, " ***** Test Step 48 : Write attribute NULLABLE_CHAR_STRING Value Back to Default Value\n"); + err = TestWriteAttributeNullableCharStringValueBackToDefaultValue_48(); break; case 49: - ChipLogProgress(chipTool, " ***** Test Step 49 : Read attribute NULLABLE_INT8U with a value\n"); - err = TestReadAttributeNullableInt8uWithAValue_49(); + ChipLogProgress(chipTool, " ***** Test Step 49 : Read attribute NULLABLE_INT8U Default Value\n"); + err = TestReadAttributeNullableInt8uDefaultValue_49(); break; case 50: - ChipLogProgress(chipTool, " ***** Test Step 50 : Write attribute NULLABLE_INT8U back to Default Value\n"); - err = TestWriteAttributeNullableInt8uBackToDefaultValue_50(); + ChipLogProgress(chipTool, " ***** Test Step 50 : Write attribute NULLABLE_INT8U with a value\n"); + err = TestWriteAttributeNullableInt8uWithAValue_50(); break; case 51: - ChipLogProgress(chipTool, " ***** Test Step 51 : Read attribute NULLABLE_OCTET_STRING Default Value\n"); - err = TestReadAttributeNullableOctetStringDefaultValue_51(); + ChipLogProgress(chipTool, " ***** Test Step 51 : Read attribute NULLABLE_INT8U with a value\n"); + err = TestReadAttributeNullableInt8uWithAValue_51(); break; case 52: - ChipLogProgress(chipTool, " ***** Test Step 52 : Write attribute NULLABLE_OCTET_STRING\n"); - err = TestWriteAttributeNullableOctetString_52(); + ChipLogProgress(chipTool, " ***** Test Step 52 : Write attribute NULLABLE_INT8U without a value\n"); + err = TestWriteAttributeNullableInt8uWithoutAValue_52(); break; case 53: - ChipLogProgress(chipTool, " ***** Test Step 53 : Read attribute NULLABLE_OCTET_STRING\n"); - err = TestReadAttributeNullableOctetString_53(); + ChipLogProgress(chipTool, " ***** Test Step 53 : Read attribute NULLABLE_INT8U with a value\n"); + err = TestReadAttributeNullableInt8uWithAValue_53(); break; case 54: - ChipLogProgress(chipTool, " ***** Test Step 54 : Write attribute NULLABLE_OCTET_STRING\n"); - err = TestWriteAttributeNullableOctetString_54(); + ChipLogProgress(chipTool, " ***** Test Step 54 : Write attribute NULLABLE_INT8U back to Default Value\n"); + err = TestWriteAttributeNullableInt8uBackToDefaultValue_54(); break; case 55: - ChipLogProgress(chipTool, " ***** Test Step 55 : Read attribute NULLABLE_OCTET_STRING\n"); - err = TestReadAttributeNullableOctetString_55(); + ChipLogProgress(chipTool, " ***** Test Step 55 : Read attribute NULLABLE_OCTET_STRING Default Value\n"); + err = TestReadAttributeNullableOctetStringDefaultValue_55(); break; case 56: - ChipLogProgress(chipTool, " ***** Test Step 56 : Write attribute NULLABLE_OCTET_STRING back to Default Value\n"); - err = TestWriteAttributeNullableOctetStringBackToDefaultValue_56(); + ChipLogProgress(chipTool, " ***** Test Step 56 : Write attribute NULLABLE_OCTET_STRING\n"); + err = TestWriteAttributeNullableOctetString_56(); + break; + case 57: + ChipLogProgress(chipTool, " ***** Test Step 57 : Read attribute NULLABLE_OCTET_STRING\n"); + err = TestReadAttributeNullableOctetString_57(); + break; + case 58: + ChipLogProgress(chipTool, " ***** Test Step 58 : Write attribute NULLABLE_OCTET_STRING\n"); + err = TestWriteAttributeNullableOctetString_58(); + break; + case 59: + ChipLogProgress(chipTool, " ***** Test Step 59 : Read attribute NULLABLE_OCTET_STRING\n"); + err = TestReadAttributeNullableOctetString_59(); + break; + case 60: + ChipLogProgress(chipTool, " ***** Test Step 60 : Write attribute NULLABLE_OCTET_STRING back to Default Value\n"); + err = TestWriteAttributeNullableOctetStringBackToDefaultValue_60(); break; } @@ -119647,6 +119663,18 @@ class TestConstraints : public TestCommandBridge { case 56: VerifyOrReturn(CheckValue("status", chip::to_underlying(status.mStatus), 0)); break; + case 57: + VerifyOrReturn(CheckValue("status", chip::to_underlying(status.mStatus), 0)); + break; + case 58: + VerifyOrReturn(CheckValue("status", chip::to_underlying(status.mStatus), 0)); + break; + case 59: + VerifyOrReturn(CheckValue("status", chip::to_underlying(status.mStatus), 0)); + break; + case 60: + VerifyOrReturn(CheckValue("status", chip::to_underlying(status.mStatus), 0)); + break; } // Go on to the next test. @@ -119660,7 +119688,7 @@ class TestConstraints : public TestCommandBridge { private: std::atomic_uint16_t mTestIndex; - const uint16_t mTestCount = 57; + const uint16_t mTestCount = 61; chip::Optional mNodeId; chip::Optional mCluster; @@ -120601,7 +120629,97 @@ class TestConstraints : public TestCommandBridge { return CHIP_NO_ERROR; } - CHIP_ERROR TestReadAttributeNullableInt8uDefaultValue_45() + CHIP_ERROR TestWriteAttributeNullableCharStringValue_45() + { + + MTRBaseDevice * device = GetDevice("alpha"); + __auto_type * cluster = [[MTRBaseClusterUnitTesting alloc] initWithDevice:device endpointID:@(1) queue:mCallbackQueue]; + VerifyOrReturnError(cluster != nil, CHIP_ERROR_INCORRECT_STATE); + + id nullableCharStringArgument; + nullableCharStringArgument = nil; + [cluster writeAttributeNullableCharStringWithValue:nullableCharStringArgument + completion:^(NSError * _Nullable err) { + NSLog(@"Write attribute NULLABLE_CHAR_STRING Value Error: %@", err); + + VerifyOrReturn(CheckValue("status", err ? err.code : 0, 0)); + + NextTest(); + }]; + + return CHIP_NO_ERROR; + } + + CHIP_ERROR TestReadAttributeNullableCharStringValueMinLengthConstraints_46() + { + + MTRBaseDevice * device = GetDevice("alpha"); + __auto_type * cluster = [[MTRBaseClusterUnitTesting alloc] initWithDevice:device endpointID:@(1) queue:mCallbackQueue]; + VerifyOrReturnError(cluster != nil, CHIP_ERROR_INCORRECT_STATE); + + [cluster readAttributeNullableCharStringWithCompletion:^(NSString * _Nullable value, NSError * _Nullable err) { + NSLog(@"Read attribute NULLABLE_CHAR_STRING Value MinLength Constraints Error: %@", err); + + VerifyOrReturn(CheckValue("status", err ? err.code : 0, 0)); + + if (value != nil) { + + VerifyOrReturn(CheckConstraintMinLength("nullableCharString", value, 5)); + } + + NextTest(); + }]; + + return CHIP_NO_ERROR; + } + + CHIP_ERROR TestReadAttributeNullableCharStringValueMaxLengthConstraints_47() + { + + MTRBaseDevice * device = GetDevice("alpha"); + __auto_type * cluster = [[MTRBaseClusterUnitTesting alloc] initWithDevice:device endpointID:@(1) queue:mCallbackQueue]; + VerifyOrReturnError(cluster != nil, CHIP_ERROR_INCORRECT_STATE); + + [cluster readAttributeNullableCharStringWithCompletion:^(NSString * _Nullable value, NSError * _Nullable err) { + NSLog(@"Read attribute NULLABLE_CHAR_STRING Value MaxLength Constraints Error: %@", err); + + VerifyOrReturn(CheckValue("status", err ? err.code : 0, 0)); + + if (value != nil) { + + VerifyOrReturn(CheckConstraintMaxLength("nullableCharString", value, 20)); + } + + NextTest(); + }]; + + return CHIP_NO_ERROR; + } + + CHIP_ERROR TestWriteAttributeNullableCharStringValueBackToDefaultValue_48() + { + + MTRBaseDevice * device = GetDevice("alpha"); + __auto_type * cluster = [[MTRBaseClusterUnitTesting alloc] initWithDevice:device endpointID:@(1) queue:mCallbackQueue]; + VerifyOrReturnError(cluster != nil, CHIP_ERROR_INCORRECT_STATE); + + id nullableCharStringArgument; + nullableCharStringArgument = @""; + [cluster + writeAttributeNullableCharStringWithValue:nullableCharStringArgument + completion:^(NSError * _Nullable err) { + NSLog(@"Write attribute NULLABLE_CHAR_STRING Value Back to Default Value Error: %@", + err); + + VerifyOrReturn(CheckValue("status", err ? err.code : 0, 0)); + + NextTest(); + }]; + + return CHIP_NO_ERROR; + } + + CHIP_ERROR TestReadAttributeNullableInt8uDefaultValue_49() { MTRBaseDevice * device = GetDevice("alpha"); @@ -120625,7 +120743,7 @@ class TestConstraints : public TestCommandBridge { return CHIP_NO_ERROR; } - CHIP_ERROR TestWriteAttributeNullableInt8uWithAValue_46() + CHIP_ERROR TestWriteAttributeNullableInt8uWithAValue_50() { MTRBaseDevice * device = GetDevice("alpha"); @@ -120646,7 +120764,7 @@ class TestConstraints : public TestCommandBridge { return CHIP_NO_ERROR; } - CHIP_ERROR TestReadAttributeNullableInt8uWithAValue_47() + CHIP_ERROR TestReadAttributeNullableInt8uWithAValue_51() { MTRBaseDevice * device = GetDevice("alpha"); @@ -120667,7 +120785,7 @@ class TestConstraints : public TestCommandBridge { return CHIP_NO_ERROR; } - CHIP_ERROR TestWriteAttributeNullableInt8uWithoutAValue_48() + CHIP_ERROR TestWriteAttributeNullableInt8uWithoutAValue_52() { MTRBaseDevice * device = GetDevice("alpha"); @@ -120688,7 +120806,7 @@ class TestConstraints : public TestCommandBridge { return CHIP_NO_ERROR; } - CHIP_ERROR TestReadAttributeNullableInt8uWithAValue_49() + CHIP_ERROR TestReadAttributeNullableInt8uWithAValue_53() { MTRBaseDevice * device = GetDevice("alpha"); @@ -120709,7 +120827,7 @@ class TestConstraints : public TestCommandBridge { return CHIP_NO_ERROR; } - CHIP_ERROR TestWriteAttributeNullableInt8uBackToDefaultValue_50() + CHIP_ERROR TestWriteAttributeNullableInt8uBackToDefaultValue_54() { MTRBaseDevice * device = GetDevice("alpha"); @@ -120730,7 +120848,7 @@ class TestConstraints : public TestCommandBridge { return CHIP_NO_ERROR; } - CHIP_ERROR TestReadAttributeNullableOctetStringDefaultValue_51() + CHIP_ERROR TestReadAttributeNullableOctetStringDefaultValue_55() { MTRBaseDevice * device = GetDevice("alpha"); @@ -120755,7 +120873,7 @@ class TestConstraints : public TestCommandBridge { return CHIP_NO_ERROR; } - CHIP_ERROR TestWriteAttributeNullableOctetString_52() + CHIP_ERROR TestWriteAttributeNullableOctetString_56() { MTRBaseDevice * device = GetDevice("alpha"); @@ -120776,7 +120894,7 @@ class TestConstraints : public TestCommandBridge { return CHIP_NO_ERROR; } - CHIP_ERROR TestReadAttributeNullableOctetString_53() + CHIP_ERROR TestReadAttributeNullableOctetString_57() { MTRBaseDevice * device = GetDevice("alpha"); @@ -120797,7 +120915,7 @@ class TestConstraints : public TestCommandBridge { return CHIP_NO_ERROR; } - CHIP_ERROR TestWriteAttributeNullableOctetString_54() + CHIP_ERROR TestWriteAttributeNullableOctetString_58() { MTRBaseDevice * device = GetDevice("alpha"); @@ -120818,7 +120936,7 @@ class TestConstraints : public TestCommandBridge { return CHIP_NO_ERROR; } - CHIP_ERROR TestReadAttributeNullableOctetString_55() + CHIP_ERROR TestReadAttributeNullableOctetString_59() { MTRBaseDevice * device = GetDevice("alpha"); @@ -120839,7 +120957,7 @@ class TestConstraints : public TestCommandBridge { return CHIP_NO_ERROR; } - CHIP_ERROR TestWriteAttributeNullableOctetStringBackToDefaultValue_56() + CHIP_ERROR TestWriteAttributeNullableOctetStringBackToDefaultValue_60() { MTRBaseDevice * device = GetDevice("alpha");