From c87c98c56c10694b7a5254d17c30611dd899aa6b Mon Sep 17 00:00:00 2001 From: cecille Date: Tue, 7 Nov 2023 09:34:47 -0500 Subject: [PATCH] check --- src/python_testing/TC_OPCREDS_3_1.py | 424 ++++++++++++++------------- 1 file changed, 226 insertions(+), 198 deletions(-) diff --git a/src/python_testing/TC_OPCREDS_3_1.py b/src/python_testing/TC_OPCREDS_3_1.py index 6ec215b2f0e08e..1d9324e4a7ed3f 100644 --- a/src/python_testing/TC_OPCREDS_3_1.py +++ b/src/python_testing/TC_OPCREDS_3_1.py @@ -16,9 +16,11 @@ # import logging +import random from cryptography import x509 +from chip import ChipDeviceCtrl import chip.clusters as Clusters import chip.discovery as Discovery from chip.exceptions import ChipStackError @@ -26,8 +28,9 @@ from matter_testing_support import MatterBaseTest, async_test_body, default_matter_test_main, type_matches from mobly import asserts + class TC_OPCREDS_3_1(MatterBaseTest): - def FindAndEstablishPase(self, dev_ctrl: ChipDeviceCtrl = None, discriminator: int, setupPinCode: int, nodeid:int): + def FindAndEstablishPase(self, discriminator: int, setupPinCode: int, nodeid: int, dev_ctrl: ChipDeviceCtrl = None, ): if dev_ctrl == None: dev_ctrl = self.default_controller @@ -38,7 +41,7 @@ def FindAndEstablishPase(self, dev_ctrl: ChipDeviceCtrl = None, discriminator: i for a in device.addresses: try: dev_ctrl.EstablishPASESessionIP(ipaddr=a, setupPinCode=setupPinCode, - nodeid=nodeid, port=device.port) + nodeid=nodeid, port=device.port) break except ChipStackError: continue @@ -54,17 +57,18 @@ async def test_TC_OPCREDS_3_1(self): # Maximize cert chains so we can use this below TH1_CA_real = self.certificate_authority_manager.NewCertificateAuthority(maximizeCertChains=True) TH1_fabric_admin_real = TH1_CA_real.NewFabricAdmin(vendorId=0xFFF1, fabricId=2) - TH1 = TH1_fabric_admin_real.NewController(nodeId=dev_ctrl.nodeId) + TH1 = TH1_fabric_admin_real.NewController(nodeId=self.default_controller.nodeId) - commissioned_fabric_count = self.read_single_attribute_check_success( + commissioned_fabric_count = await self.read_single_attribute_check_success( cluster=opcreds, attribute=opcreds.Attributes.CommissionedFabrics) - supported_fabric_count = self.read_single_attribute_check_success( + supported_fabric_count = await self.read_single_attribute_check_success( cluster=opcreds, attribute=opcreds.Attributes.SupportedFabrics) # Make sure we have space - #TODO: Add step here to just remove extra fabrics if required. - asserts.assert_less(commissionined_fabric_count, supported_fabric_found, "Device fabric table is full - please remove one fabric and retry") + # TODO: Add step here to just remove extra fabrics if required. + asserts.assert_less(commissioned_fabric_count, supported_fabric_count, + "Device fabric table is full - please remove one fabric and retry") self.print_step(1, "TH0 opens a commissioning window on the DUT") # TODO: abstract this in the base layer? Do we do this a lot? @@ -77,20 +81,19 @@ async def test_TC_OPCREDS_3_1(self): asserts.assert_true(False, 'Failed to open commissioning window') self.print_step("1a", "TH1 opens a PASE connection to the DUT") - # TODO: same - do we do this a lot? newNodeId = self.dut_node_id + 1 - self.FindAndEstablishPase(TH=TH1, discriminator=discriminator, setupPinCode=params.setupPinCode, nodeid=newNodeId) + self.FindAndEstablishPase(dev_ctrl=TH1, discriminator=discriminator, setupPinCode=params.setupPinCode, nodeid=newNodeId) self.print_step("2", "TH1 sends ArmFailSafe command to the DUT with the ExpiryLengthSeconds field set to 900") - await self.send_single_cmd(dev_ctrl=TH2, nodeid=nodeid, cmd=Clusters.GeneralCommissioning.Commands.ArmFailSafe(900)) + await self.send_single_cmd(dev_ctrl=TH1, node_id=newNodeId, cmd=Clusters.GeneralCommissioning.Commands.ArmFailSafe(900)) self.print_step(8, "TH1 Sends CSRRequest command with a random 32-byte nonce and saves the response as`csrResponse") nonce = random.randbytes(32) - csrResponse = await self.send_single_cmd(dev_ctrl=TH1, nodeid=newNodeId, cmd=opcreds.Commands.CSRRequest(CSRNonce=nonce, isForUpdateNOC=False)) + csrResponse = await self.send_single_cmd(dev_ctrl=TH1, node_id=newNodeId, cmd=opcreds.Commands.CSRRequest(CSRNonce=nonce, isForUpdateNOC=False)) self.print_step(10, "TH1 obtains or generates the NOC, the Root CA Certificate and ICAC using csrResponse and selects an IPK. The certificates shall have their subjects padded with additional data such that they are each the maximum certificate size of 400 bytes when encoded in the MatterCertificateEncoding.") # Our CA is set up to maximize cert chains already - #Extract the RCAC public key and save as `Root_Public_Key_TH1` + # Extract the RCAC public key and save as `Root_Public_Key_TH1` TH1_certs_real = TH1.IssueNOCChain(csrResponse, newNodeId) if (TH1_certs_real.rcacBytes is None or TH1_certs_real.icacBytes is None or @@ -98,10 +101,13 @@ async def test_TC_OPCREDS_3_1(self): # Expiring the failsafe timer in an attempt to clean up. await TH1.SendCommand(newNodeId, 0, Clusters.GeneralCommissioning.Commands.ArmFailSafe(0)) asserts.assert_fail("Unable to generate NOC chain for DUT - this is a script failure, please report this as a bug") - root_cert_temp = load_der_x509_certificate(TH1_certs_read.rcacBytes) - root_public_key_th1 = hex_from_bytes(root_cert_temp.public_key().public_bytes(encoding=Encoding.X962, format=PublicFormat.UncompressedPoint)) + # TODO: This is actually easier because we just need to parse the TLV + root_cert_temp = x509.load_der_x509_certificate(TH1_certs_real.rcacBytes) + root_public_key_th1 = hex_from_bytes(root_cert_temp.public_key().public_bytes( + encoding=Encoding.X962, format=PublicFormat.UncompressedPoint)) - self.print_step(11, "TH1 obtains or generates Root Certificate with a different Root CA ID and the corresponding ICAC, NOC and IPK using csrResponse") + self.print_step( + 11, "TH1 obtains or generates Root Certificate with a different Root CA ID and the corresponding ICAC, NOC and IPK using csrResponse") TH1_CA_fake = self.certificate_authority_manager.NewCertificateAuthority() TH1_fabric_admin_fake = TH1_CA_fake.NewFabricAdmin(vendorId=0xFFF1, fabricId=2) TH1_fake = TH1_fabric_admin_fake.NewController(nodeId=dev_ctrl.nodeId) @@ -113,33 +119,39 @@ async def test_TC_OPCREDS_3_1(self): await TH1.SendCommand(newNodeId, 0, Clusters.GeneralCommissioning.Commands.ArmFailSafe(0)) asserts.assert_fail("Unable to generate NOC chain for DUT - this is a script failure, please report this as a bug") - self.print_step(12, "TH1 generates an INVALID Root Certificate where the signature does not match the public key and saves it as `Root_CA_Malformed`") + self.print_step( + 12, "TH1 generates an INVALID Root Certificate where the signature does not match the public key and saves it as `Root_CA_Malformed`") TH1_root_CA_malformed = copy.deepcopy(root_cert_temp) TH1_root_CA_malformed.signature[0] = TH1_root_CA_malformed.signature[0] + 1 + # TH1_root_CA_malformed_der = TH1_root_CA_malformed.public_bytes(encoding) + self.print_step( + 13, "TH1 sends AddTrustedRootCertificate command to DUT to install `Root_CA_Malformed` and verifies INVALID_COMMAND is returned") - self.print_step(13, "TH1 sends AddTrustedRootCertificate command to DUT to install `Root_CA_Malformed` and verifies INVALID_COMMAND is returned") - - self.print_step(14, "TH1 sends AddTrustedRootCertificate command to DUT with RootCACertificate set to `Root_CA_Certificate_TH1`, verify SUCCESS") + self.print_step( + 14, "TH1 sends AddTrustedRootCertificate command to DUT with RootCACertificate set to `Root_CA_Certificate_TH1`, verify SUCCESS") - self.print_step(15, "TH1 sends AddTrustedRootCertificate command to DUT again with the RootCACertificate field set to `Root_CA_Certificate_TH1`, verify SUCCESS") + self.print_step( + 15, "TH1 sends AddTrustedRootCertificate command to DUT again with the RootCACertificate field set to `Root_CA_Certificate_TH1`, verify SUCCESS") - self.print_step(16, "TH1 sends AddTrustedRootCertificate command to DUT again with the RootCACertificate field set to `Root_CA_Certificate_TH1_2`, verify CONSTRAINT_ERROR") + self.print_step( + 16, "TH1 sends AddTrustedRootCertificate command to DUT again with the RootCACertificate field set to `Root_CA_Certificate_TH1_2`, verify CONSTRAINT_ERROR") self.print_step(17, "TH1 reads the TrustedRootCertificates list from DUT and saves as `TrustedRootsList`, Verify that there is only one instance of Root CA Certificate in the list and that its content matches `Root_CA_Certificate_TH1`") # TODO: Verify that it contains the first, and does not contain the second - self.print_step(18, "TH1 appends `Root_CA_Certificate_TH1_2` to `TrustedRootsList` and writes the TrustedRootCertificates attribute with that value, Verify UNSUPPORTED_WRITE") + self.print_step( + 18, "TH1 appends `Root_CA_Certificate_TH1_2` to `TrustedRootsList` and writes the TrustedRootCertificates attribute with that value, Verify UNSUPPORTED_WRITE") self.print_step(19, "TH1 reads the TrustedRootCertificates list from DUT | Verify that there is only one instance of Root CA Certificate in the list and that its content matches `Root_CA_Certificate_TH1`") # TODO: verify that it matches `TrustedRootList` self.print_step(20, "TH1 sends the AddNOC Command to DUT for the certs generated with the second trusted root cert") - #Node_Operational_Certificate_TH1_2` - #ICACValue as `Intermediate_Certificate_TH1_2` - #IpkValue as `IPK_TH1_2` - #CaseAdminSubject as the NodeID of TH1 - #AdminVendorId as the Vendor ID of TH1 a|* Verify that DUT responds with NOCResponse command with status code InvalidNOC + # Node_Operational_Certificate_TH1_2` + # ICACValue as `Intermediate_Certificate_TH1_2` + # IpkValue as `IPK_TH1_2` + # CaseAdminSubject as the NodeID of TH1 + # AdminVendorId as the Vendor ID of TH1 a|* Verify that DUT responds with NOCResponse command with status code InvalidNOC self.print_step(21, "TH1 sends the AddNOC Command to DUT with an invalid node ID") # NOCValue as `Node_Operational_Certificate_TH1` @@ -168,204 +180,220 @@ async def test_TC_OPCREDS_3_1(self): # CaseAdminSubject as the NodeID of TH1 # AdminVendorId as the Vendor ID of TH1 | Verify that DUT responds with status code CONSTRAINT_ERROR - self.print_step(25, "TH1 reads the NOCs attribute from DUT using a non-fabric-filtered read and saves the list as `NOCList`) + self.print_step(25, "TH1 reads the NOCs attribute from DUT using a non-fabric-filtered read and saves the list as `NOCList`") # TODO: Vhange this step to verify that the valid NOC is there and the invalid NOC is not - self.print_step(26, "TH1 appends a second list item to 'NOCList' and writes that value to the NOCs attribute. Verify UNSUPPORTED_WRITE") - - self.print_step(27, "TH1 reads the NOCs attribute from DUT using a non-fabric-filtered read. Verify the added NOC from the previous step is not part of the list") - #TODO: chance this in the test plan - -|[[fabric-label-command,28]]28 |11.17.6.5 |OPCREDS.S.C09.Rsp(UpdateFabricLabel)|TH1 sends UpdateFabricLabel command with 'Label 1' as Label field to DUT a|* Verify that the DUT responds with the NOCResponse Command with status OK - -|29 |11.17.6.2 | | TH1 reads the Fabrics Attribute from DUT using a non-fabric-filtered read and gets the FabricDescriptorStruct for which the FabricIndex field equals `FabricIndex_TH1`| - -|[[fabric-table,30]]30 | | | a|* Read the other fields from FabricDescriptorStruct -1. RootPublicKey -2. VendorID -3. FabricID -4. NodeID -5. Label -* Verify that the size of RootPublicKey is exactly 65 bytes -* Verify that the RootPublicKey matches `Root_Public_Key_TH1` -* Verify that the NodeID is the same as the matter-node-id field in the NOC sent with AddNOC Command -* Verify that the VendorID is the same as the AdminVendorID sent with AddNOC Command -* Verify that the FabricID is the same as the matter-fabric-id field in the NOC sent with AddNOC Command -* Verify that the Label field has value "Label 1" - -|31 a|* 11.9.7.2 -* 11.9.7.3 a|* CGEN.S.C00.Rsp(ArmFailSafe) -* CGEN.S.C01.Tx(ArmFailSafeResponse) | TH1 sends ArmFailSafe command to the DUT with ExpiryLengthSeconds field set to 0 | - -|32 | | | TH1 reconnects to the DUT over PASE | - -|[[failsafe-expiry-root-certs,33]]33 | 11.17.6.5| OPCREDS.S.A0004(TrustedRootCertificates)| TH1 reads the TrustedRootCertificates list from DUT | Verify that list is empty - -|[[failsafe-expiry-nocs,34]]34 | 11.17.6.1 | OPCREDS.S.A0000(NOCs)| TH1 reads the NOCs attribute from DUT using a non-fabric-filtered read| Verify that the list is empty - -|[[failsafe-expiry-fabrics,35]]35 | 11.17.6.2 | OPCREDS.A.A0001(Fabrics) | TH1 reads the Fabrics attribute from the DUT using a non-fabric-filtered read | Verify that the list is empty - -|36| 5.5 | | TH1 fully commissions DUT onto the fabric, using 'Root_CA_Certificate_TH1' and the AddNOC parameters specified in step [[noc-ok]]. This will update the value of `FabricIndex_TH1` so that it references the fabric the DUT was just commissioned onto | Verify that TH1 successfully completes commissioning, including establishing a CASE session on the operational network and issuing a CommissioningComplete command. - -|[[trusted-root-cert-table-ok,37]]37 | 11.17.6.5| OPCREDS.S.A0004(TrustedRootCertificates)| TH1 reads the TrustedRootCertificates list from DUT | Verify that there is only one instance of Root CA Certificate in the list and that its content matches `Root_CA_Certificate_TH1` - -|[[noc-table-ok,38]]38 | 11.17.6.1 | OPCREDS.S.A0000(NOCs)| TH1 reads the NOCs attribute from DUT using a non-fabric-filtered read | Verify that the list contains one entry with NOC field `Node_Operational_Certificate_TH1` and ICAC field `Intermediate_Certificate_TH1` - -|39 |11.17.6.5 |OPCREDS.S.C09.Rsp(UpdateFabricLabel)|TH1 sends UpdateFabricLabel command with 'Label 1' as Label field to DUT a|* Verify that the DUT responds with the NOCResponse Command with status OK - -|[[fabrics-table-ok,40]]40 |11.17.6.2 | OPCREDS.S.A0001(Fabrics)| TH1 reads the Fabrics Attribute from DUT using a non-fabric-filtered read and gets the FabricDescriptorStruct for which the FabricIndex field equals `FabricIndex_TH1`| - -|41 | | | a|* Read the other fields from FabricDescriptorStruct -1. RootPublicKey -2. VendorID -3. FabricID -4. NodeID -5. Label -* Verify that the size of RootPublicKey is exactly 65 bytes -* Verify that the RootPublicKey matches `Root_Public_Key_TH1` -* Verify that the NodeID is the same as the matter-node-id field in the NOC sent with AddNOC Command -* Verify that the VendorID is the same as the AdminVendorID sent with AddNOC Command -* Verify that the FabricID is the same as the matter-fabric-id field in the NOC sent with AddNOC Command -* Verify that the Label field has value "Label 1" - -|[[acl-ok,42]]42 a|* 11.17.7.8 -* 9.10.5 |OPCREDS.S.C06.Rsp(AddNOC) | TH1 reads the ACL attribute from the Access Control cluster a| * Verify that the returned list includes an entry with: -* Fabric index of `FabricIndex_TH1` -* Administer privilege (5) -* CASE AuthMode (2) -* Includes the NodeID of TH1 in the list of subjects - -|[[ipk-ok,43]]43 a|* 11.17.7.8 -* 11.2.9.2 | OPCREDS.S.C06.Rsp(AddNOC) | TH1 issues a KeySetRead command to the DUT for GroupKeySetID 0 | Verify that an entry is read-back successfully. - -|44 | 11.18.8.1 | | TH1 sends an OpenCommissioningWindow command to the Administrator Commissioning cluster | - -|45| 6.4| a|* TH2 begins the process of commissioning the DUT. After receiving the CSRResponse TH2 obtains or generates a NOC, the Root CA Certificate, ICAC and IPK. The certificates shall have their subjects padded with additional data such that they are each the maximum certificate size of 400 bytes when encoded in the MatterCertificateEncoding. -* Save RCAC as `Root_CA_Certificate_TH2` -* Save ICAC as `Intermediate_Certificate_TH2` -* Save NOC as `Node_Operational_Certificate_TH2` -* Save IPK as `IPK_TH2` -* Extract the RCAC public key and save as `Root_Public_Key_TH2` | - -|[[add-noc-cat,46]]46| 5.5 | a|* TH2 completes the commissioning process using `Root_CA_Certificate_TH2` when performing the AddTrustedRootCertificate command and sending AddNOC with the following parameters: -* NOCValue as `Node_Operational_Certificate_TH2` -* ICACValue as `Intermediate_Certificate_TH2` -* IpkValue as `IPK_TH2` -* CaseAdminSubject as `CAT_TH2` -* AdminVendorId as the Vendor ID of TH2 | Verify that TH2 successfully completes commissioning, including establishing a CASE session on the operational network and issuing a CommissioningComplete command - -|[[multiple-trusted-root-certs,47]]47 |11.17.6.5| OPCREDS.S.A0004(TrustedRootCertificates)|TH2 reads the TrustedRootCertificates list from DUT |Verify that the list length is two and it contains `Root_CA_Certificate_TH1` and `Root_CA_Certificate_TH2` - -|[[multiple-nocs,48]]48 | 11.17.6.1 | OPCREDS.S.A0000(NOCs)| TH2 reads the NOCs attribute from DUT using a non-fabric-filtered read a|* Verify that the list contains two entries -* Verify that one entry has NOC field `Node_Operational_Certificate_TH2` and ICAC field `Intermediate_Certificate_TH2` - -|49 |11.17.6.5 |OPCREDS.S.C09.Rsp(UpdateFabricLabel)|TH2 sends UpdateFabricLabel command with 'Label 2' as Label field to DUT a|* Verify that the DUT responds with the NOCResponse Command with status OK - -|[[label-conflict,50]]50 |11.17.7.11 |OPCREDS.S.C09.Rsp(UpdateFabricLabel)|TH2 sends UpdateFabricLabel command with 'Label 1' as Label field to DUT a|* Verify that the DUT responds with the NOCResponse Command with status LabelConflict - - -|[[multiple-fabric-table,51]]51 |11.17.6.2 | OPCREDS.S.A0001(Fabrics)| Read the Fabrics List from DUT using a non-fabric-filtered read a|* Verify that there are two entries -* Verify that one entry has Label field 'Label 1' -* Verify that the other entry has label field 'Label 2' -* Verify that the list item with Label 'Label 1' has RootPublicKey field `Root_Public_Key_TH1`, NodeId field matches matter-node-id in `Node_Operational_Certificate_TH1`, FabricID field matches matter-fabric-id field in `Node_Operational_Certificate_TH1` and VendorID is the vendor ID of TH1 -* Verify that the list item with Label 'Label 2' has RootPublicKey field `Root_Public_Key_TH2`, NodeId field matches matter-node-id in `Node_Operational_Certificate_TH2`, FabricID field matches matter-fabric-id field in `Node_Operational_Certificate_TH2` and VendorID is the vendor ID of TH2 - -|52 a|* 11.9.7.2 -* 11.9.7.3 a|* CGEN.S.C00.Rsp(ArmFailSafe) -* CGEN.S.C01.Tx(ArmFailSafeResponse) | TH1 sends ArmFailSafe command to the DUT with the ExpiryLengthSeconds field set to 900| Verify that the DUT sends ArmFailSafeResponse Command to TH1 with field ErrorCode as 'OK'(0) + self.print_step( + 26, "TH1 appends a second list item to 'NOCList' and writes that value to the NOCs attribute. Verify UNSUPPORTED_WRITE") + + self.print_step( + 27, "TH1 reads the NOCs attribute from DUT using a non-fabric-filtered read. Verify the added NOC from the previous step is not part of the list") + # TODO: chance this in the test plan + + self.print_step( + 28, "TH1 sends UpdateFabricLabel command with 'Label 1' as Label field to DUT a|* Verify that the DUT responds with the NOCResponse Command with status OK") + + self.print_step(29, "TH1 reads the Fabrics Attribute from DUT using a non-fabric-filtered read and gets the FabricDescriptorStruct for which the FabricIndex field equals `FabricIndex_TH1`") + + self.print_step(30, "Read the other fields from FabricDescriptorStruct") + # 1. RootPublicKey + # 2. VendorID + # 3. FabricID + # 4. NodeID + # 5. Label + # Verify that the size of RootPublicKey is exactly 65 bytes + # Verify that the RootPublicKey matches `Root_Public_Key_TH1` + # Verify that the NodeID is the same as the matter-node-id field in the NOC sent with AddNOC Command + # Verify that the VendorID is the same as the AdminVendorID sent with AddNOC Command + # Verify that the FabricID is the same as the matter-fabric-id field in the NOC sent with AddNOC Command + # Verify that the Label field has value "Label 1" + + self.print_step(31, "TH1 sends ArmFailSafe command to the DUT with ExpiryLengthSeconds field set to 0") + + self.print_step(32, "TH1 reconnects to the DUT over PASE") + + self.print_step(33, "TH1 reads the TrustedRootCertificates list from DUT | Verify that list is empty") + # TODO: change this so that it's just that the list matches the original + + self.print_step(34, "TH1 reads the NOCs attribute from DUT using a non-fabric-filtered read| Verify that the list is empty") + # TODO: change this so it's just that the list matches the original + + self.print_step(35, "TH1 reads the Fabrics attribute from the DUT using a non-fabric-filtered read | Verify that the list is empty") + # TODO: change this so it's just that the list matches the original + + self.print_step( + 36, "TH1 fully commissions DUT onto the fabric, using 'Root_CA_Certificate_TH1' and the AddNOC parameters specified in step [[noc-ok]]. This will update the value of `FabricIndex_TH1` so that it references the fabric the DUT was just commissioned onto | Verify that TH1 successfully completes commissioning, including establishing a CASE session on the operational network and issuing a CommissioningComplete command.") + # TODO: change to just using a valid certificate + + self.print_step(37, "TH1 reads the TrustedRootCertificates list from DUT | Verify that there is only one instance of Root CA Certificate in the list and that its content matches `Root_CA_Certificate_TH1`") + # TODO: change to original number + 1 + + self.print_step(38, "TH1 reads the NOCs attribute from DUT using a non-fabric-filtered read | Verify that the list contains one entry with NOC field `Node_Operational_Certificate_TH1` and ICAC field `Intermediate_Certificate_TH1`") + # TODO: change to original number + 1 + + self.print_step(39, "TH1 sends UpdateFabricLabel command with 'Label 1' as Label field to DUT ") + + self.print_step(40, "TH1 reads the Fabrics Attribute from DUT using a non-fabric-filtered read and gets the FabricDescriptorStruct for which the FabricIndex field equals `FabricIndex_TH1`") + + self.print_step(41, "Read the other fields from FabricDescriptorStruct and verify") + # 1. RootPublicKey + # 2. VendorID + # 3. FabricID + # 4. NodeID + # 5. Label + # Verify that the size of RootPublicKey is exactly 65 bytes + # Verify that the RootPublicKey matches `Root_Public_Key_TH1` + # Verify that the NodeID is the same as the matter-node-id field in the NOC sent with AddNOC Command + # Verify that the VendorID is the same as the AdminVendorID sent with AddNOC Command + # Verify that the FabricID is the same as the matter-fabric-id field in the NOC sent with AddNOC Command + # Verify that the Label field has value "Label 1" + + self.print_step(42, "TH1 reads the ACL attribute from the Access Control cluster") + # a| * Verify that the returned list includes an entry with: + # Fabric index of `FabricIndex_TH1` + # Administer privilege (5) + # CASE AuthMode (2) + # Includes the NodeID of TH1 in the list of subjects + + self.print_step( + 43, "TH1 issues a KeySetRead command to the DUT for GroupKeySetID 0 | Verify that an entry is read-back successfully.") + + self.print_step(44, "TH1 sends an OpenCommissioningWindow command to the Administrator Commissioning cluster") + + self.print_step(45, "TH2 begins the process of commissioning the DUT. After receiving the CSRResponse TH2 obtains or generates a NOC, the Root CA Certificate, ICAC and IPK. The certificates shall have their subjects padded with additional data such that they are each the maximum certificate size of 400 bytes when encoded in the MatterCertificateEncoding.") + # Save RCAC as `Root_CA_Certificate_TH2` + # Save ICAC as `Intermediate_Certificate_TH2` + # Save NOC as `Node_Operational_Certificate_TH2` + # Save IPK as `IPK_TH2` + # Extract the RCAC public key and save as `Root_Public_Key_TH2` | + + self.print_step(46, "TH2 completes the commissioning process using `Root_CA_Certificate_TH2` when performing the AddTrustedRootCertificate command and sending AddNOC with the following parameters:") + # NOCValue as `Node_Operational_Certificate_TH2` + # ICACValue as `Intermediate_Certificate_TH2` + # IpkValue as `IPK_TH2` + # CaseAdminSubject as `CAT_TH2` + # AdminVendorId as the Vendor ID of TH2 | Verify that TH2 successfully completes commissioning, including establishing a CASE session on the operational network and issuing a CommissioningComplete command + + self.print_step( + 47, "TH2 reads the TrustedRootCertificates list from DUT |Verify that the list length is two and it contains `Root_CA_Certificate_TH1` and `Root_CA_Certificate_TH2`") + + self.print_step( + 48, "TH2 reads the NOCs attribute from DUT using a non-fabric-filtered read a|* Verify that the list contains two entries") + # TODO: original number + 2 + # Verify that one entry has NOC field `Node_Operational_Certificate_TH2` and ICAC field `Intermediate_Certificate_TH2` + + self.print_step( + 49, "TH2 sends UpdateFabricLabel command with 'Label 2' as Label field to DUT a|* Verify that the DUT responds with the NOCResponse Command with status OK") + + self.print_step( + 50, "TH2 sends UpdateFabricLabel command with 'Label 1' as Label field to DUT a|* Verify that the DUT responds with the NOCResponse Command with status LabelConflict") + + self.print_step(51, "Read the Fabrics List from DUT using a non-fabric-filtered read a|* Verify that there are two entries") + # TODO: original number + 2 + # Verify that one entry has Label field 'Label 1' + # Verify that the other entry has label field 'Label 2' + # Verify that the list item with Label 'Label 1' has RootPublicKey field `Root_Public_Key_TH1`, NodeId field matches matter-node-id in `Node_Operational_Certificate_TH1`, FabricID field matches matter-fabric-id field in `Node_Operational_Certificate_TH1` and VendorID is the vendor ID of TH1 + # Verify that the list item with Label 'Label 2' has RootPublicKey field `Root_Public_Key_TH2`, NodeId field matches matter-node-id in `Node_Operational_Certificate_TH2`, FabricID field matches matter-fabric-id field in `Node_Operational_Certificate_TH2` and VendorID is the vendor ID of TH2 + + self.print_step(52, "TH1 sends ArmFailSafe command to the DUT with the ExpiryLengthSeconds field set to 900| Verify that the DUT sends ArmFailSafeResponse Command to TH1 with field ErrorCode as 'OK'(0)") + + self.print_step(53, "TH1 sends AddTrustedRootCertificate command to DUT with RootCACertificate set to `Root_CA_Certificate_TH1_2` |Verify that AddTrustedRootCertificate Command succeeds by sending the status code as SUCCESS") + + self.print_step(54, "TH1 sends the AddNOC Command to DUT with the following fields:") + # NOCValue as `Node_Operational_Certificate_TH1_2` + # ICACValue as `Intermediate_Certificate_TH1_2` + # IpkValue as `IPK_TH1_2` + # CaseAdminSubject as the NodeID of TH1 + # AdminVendorId as the Vendor ID of TH1 | Verify that DUT responds with status code MissingCsr -|53 |11.17.7.13 |OPCREDS.S.C0b.Rsp(AddTrustedRootCertificate) |TH1 sends AddTrustedRootCertificate command to DUT with RootCACertificate set to `Root_CA_Certificate_TH1_2` |Verify that AddTrustedRootCertificate Command succeeds by sending the status code as SUCCESS + self.print_step( + 55, "TH1 Sends CSRRequest command with a random 32-byte nonce a|* Verify that the DUT responds with the CSRResponse Command") + # TODO: skip these validations - we've done this -|[[missing-csr,54]]54 |5.5,11.17.7.10 |OPCREDS.S.C06.Rsp(AddNOC) a|* TH1 sends the AddNOC Command to DUT with the following fields: -* NOCValue as `Node_Operational_Certificate_TH1_2` -* ICACValue as `Intermediate_Certificate_TH1_2` -* IpkValue as `IPK_TH1_2` -* CaseAdminSubject as the NodeID of TH1 -* AdminVendorId as the Vendor ID of TH1 | Verify that DUT responds with status code MissingCsr + self.print_step(56, "TH1 sends the AddNOC Command to DUT with the following fields:") + # NOCValue as `Node_Operational_Certificate_TH1_2` + # ICACValue as `Intermediate_Certificate_TH1_2` + # IpkValue as `IPK_TH1_2` + # CaseAdminSubject as the NodeID of TH1 + # AdminVendorId as the Vendor ID of TH1 | Verify that DUT responds with status code InvalidPublicKey -|[[csr-step, 55]]55 | 11.17.7.5| OPCREDS.S.C04.Rsp(CSRRequest) | TH1 Sends CSRRequest command with a random 32-byte nonce a|* Verify that the DUT responds with the CSRResponse Command -* Verify that the NOCSRElements field is present and of type octstr -* Verify that the AttestationSignature field is present, is an octstr type and has a maximum length of 64 + self.print_step(57, "TH1 obtains or generates a NOC and ICAC using the CSR elements from step <> with a different NodeID, but the same Root CA Certificate and fabric ID as step <>. Save as `Node_Operational_Certificates_TH1_fabric_conflict` and `Intermediate_Certificate_TH1_fabric_conflict`|") -|[[invalid-public-key,56]]56 |5.5,11.17.7.10 |OPCREDS.S.C06.Rsp(AddNOC) a|* TH1 sends the AddNOC Command to DUT with the following fields: -* NOCValue as `Node_Operational_Certificate_TH1_2` -* ICACValue as `Intermediate_Certificate_TH1_2` -* IpkValue as `IPK_TH1_2` -* CaseAdminSubject as the NodeID of TH1 -* AdminVendorId as the Vendor ID of TH1 | Verify that DUT responds with status code InvalidPublicKey + self.print_step(58, "TH1 sends the AddNOC Command to DUT with the following fields:") + # NOCValue as `Node_Operational_Certificate_TH1_fabric_conflict` + # ICACValue as `Intermediate_Certificate_TH1_fabric_conflict` + # CaseAdminSubject as the NodeID of TH1 + # AdminVendorId as the Vendor ID of TH1 | Verify that DUT responds with status code FabricConflict -|57| 6.4 | |TH1 obtains or generates a NOC and ICAC using the CSR elements from step <> with a different NodeID, but the same Root CA Certificate and fabric ID as step <>. Save as `Node_Operational_Certificates_TH1_fabric_conflict` and `Intermediate_Certificate_TH1_fabric_conflict`| + self.print_step(59, "TH1 sends ArmFailSafe command to the DUT with ExpiryLengthSeconds set to 0| Verify that the DUT sends ArmFailSafeResponse Command to TH1 with field ErrorCode as 'OK'(0)") -|[[fabric-conflict,58]]58 |11.17.7.10 |OPCREDS.S.C06.Rsp(AddNOC) a|* TH1 sends the AddNOC Command to DUT with the following fields: -* NOCValue as `Node_Operational_Certificate_TH1_fabric_conflict` -* ICACValue as `Intermediate_Certificate_TH1_fabric_conflict` -* CaseAdminSubject as the NodeID of TH1 -* AdminVendorId as the Vendor ID of TH1 | Verify that DUT responds with status code FabricConflict + self.print_step( + 60, "TH1 reads the TrustedRootCertificates list from DUT | Verify that list contains a single entry matching `Root_CA_Certificate_TH1`") -|59 a|* 11.9.7.2 -* 11.9.7.3 a|* CGEN.S.C00.Rsp(ArmFailSafe) -* CGEN.S.C01.Tx(ArmFailSafeResponse) | TH1 sends ArmFailSafe command to the DUT with ExpiryLengthSeconds set to 0| Verify that the DUT sends ArmFailSafeResponse Command to TH1 with field ErrorCode as 'OK'(0) + self.print_step(61, "TH1 sends ArmFailSafe command to the DUT with the ExpiryLengthSeconds field set to 900| Verify that the DUT sends ArmFailSafeResponse Command to TH1 with field ErrorCode as 'OK'(0)") -|60 | 11.17.6.5| OPCREDS.S.A0004(TrustedRootCertificates)| TH1 reads the TrustedRootCertificates list from DUT | Verify that list contains a single entry matching `Root_CA_Certificate_TH1` + self.print_step( + 62, "TH1 Sends CSRRequest command with a random 32-byte nonce and the IsForUpdateNOC field set to true a|* Verify that the DUT responds with the CSRResponse Command") + # TODO: skip these checks - already done elsewhere -|61 a|* 11.9.7.2 -* 11.9.7.3 a|* CGEN.S.C00.Rsp(ArmFailSafe) -* CGEN.S.C01.Tx(ArmFailSafeResponse) | TH1 sends ArmFailSafe command to the DUT with the ExpiryLengthSeconds field set to 900| Verify that the DUT sends ArmFailSafeResponse Command to TH1 with field ErrorCode as 'OK'(0) + self.print_step(63, "TH1 obtains or generates a NOC, Root CA Certificate, ICAC using the CSR elements from the previous step") + # Save RCAC as `Root_CA_Certificate_TH1_3` + # Save ICAC as `Intermediate_Certificate_TH1_3` + # Save NOC as `Node_Operational_Certificate_TH1_3` | -|[[csr-step-update, 62]]62 | 11.17.7.5| OPCREDS.S.C04.Rsp(CSRRequest) | TH1 Sends CSRRequest command with a random 32-byte nonce and the IsForUpdateNOC field set to true a|* Verify that the DUT responds with the CSRResponse Command -* Verify that the NOCSRElements field is present and of type octstr -* Verify that the AttestationSignature field is present, is an octstr type and has a maximum length of 64 + self.print_step(64, "TH1 sends AddTrustedRootCertificate command to DUT with RootCACertificate set to `Root_CA_Certificate_TH1_3` |Verify that AddTrustedRootCertificate Command succeeds by sending the status code as SUCCESS") -| 63 | | a|* TH1 obtains or generates a NOC, Root CA Certificate, ICAC using the CSR elements from the previous step -* Save RCAC as `Root_CA_Certificate_TH1_3` -* Save ICAC as `Intermediate_Certificate_TH1_3` -* Save NOC as `Node_Operational_Certificate_TH1_3` | + self.print_step(65, "TH1 sends the AddNOC Command to DUT with the following fields:") + # NOCValue as `Node_Operational_Certificate_TH1_3` + # ICACValue as `Intermediate_Certificate_TH1_3` + # CaseAdminSubject as the NodeID of TH1 + # AdminVendorId as the Vendor ID of TH1 | Verify that DUT responds with status code CONSTRAINT_ERROR -|64 |11.17.7.13 |OPCREDS.S.C0b.Rsp(AddTrustedRootCertificate) |TH1 sends AddTrustedRootCertificate command to DUT with RootCACertificate set to `Root_CA_Certificate_TH1_3` |Verify that AddTrustedRootCertificate Command succeeds by sending the status code as SUCCESS + self.print_step(66, "TH1 sends ArmFailSafe command to the DUT with ExpiryLengthSeconds set to 0| Verify that the DUT sends ArmFailSafeResponse Command to TH1 with field ErrorCode as 'OK'(0)") -|[[add-noc-for-update-csr,65]]65 |11.17.7.10 |OPCREDS.S.C06.Rsp(AddNOC) a|* TH1 sends the AddNOC Command to DUT with the following fields: -* NOCValue as `Node_Operational_Certificate_TH1_3` -* ICACValue as `Intermediate_Certificate_TH1_3` -* CaseAdminSubject as the NodeID of TH1 -* AdminVendorId as the Vendor ID of TH1 | Verify that DUT responds with status code CONSTRAINT_ERROR + self.print_step(67, "TH1 sends ArmFailSafe command to the DUT with the ExpiryLengthSeconds field set to 900| Verify that the DUT sends ArmFailSafeResponse Command to TH1 with field ErrorCode as 'OK'(0)") -|66 a|* 11.9.7.2 -* 11.9.7.3 a|* CGEN.S.C00.Rsp(ArmFailSafe) -* CGEN.S.C01.Tx(ArmFailSafeResponse) | TH1 sends ArmFailSafe command to the DUT with ExpiryLengthSeconds set to 0| Verify that the DUT sends ArmFailSafeResponse Command to TH1 with field ErrorCode as 'OK'(0) + self.print_step(68, "TH2 sends RemoveFabric command with Fabric Index as FabricIndexTH2 + 5 (Invalid Fabric Index) to DUT | Verify that DUT sends NOCResponse Command with StatusCode of InvalidFabricIndex") -|67 a|* 11.9.7.2 -* 11.9.7.3 a|* CGEN.S.C00.Rsp(ArmFailSafe) -* CGEN.S.C01.Tx(ArmFailSafeResponse) | TH1 sends ArmFailSafe command to the DUT with the ExpiryLengthSeconds field set to 900| Verify that the DUT sends ArmFailSafeResponse Command to TH1 with field ErrorCode as 'OK'(0) + self.print_step(69, "TH2 reads the Fabrics List from DUT using a non-fabric-filtered read a| Verify that there are two entries") + # TODO: original + 2 -|[[remove-invalid-fabric,68]]68|11.17.7.12 |OPCREDS.S.C0a.Rsp(RemoveFabric)| TH2 sends RemoveFabric command with Fabric Index as FabricIndexTH2 + 5 (Invalid Fabric Index) to DUT | Verify that DUT sends NOCResponse Command with StatusCode of InvalidFabricIndex + self.print_step( + 70, "TH2 sends RemoveFabric command with Fabric Index as FabricIndex_TH1 (Valid Fabric Index) to DUT | Verify that DUT sends NOCResponse Command with StatusCode of OK") -|69 |11.17.6.2 | OPCREDS.S.A0001(Fabrics)| TH2 reads the Fabrics List from DUT using a non-fabric-filtered read a| Verify that there are two entries + self.print_step( + 71, "TH2 reads the Fabrics List from DUT using a non-fabric-filtered read a|* Verify that there is a single entry with the following fields:") + # TODO: original + 1 + # Label is "Label 2" + # RootPublicKey field `Root_Public_Key_TH2` + # NodeId field matches matter-node-id in `Node_Operational_Certificate_TH2` + # FabricID field matches matter-fabric-id field in `Node_Operational_Certificate_TH2` + # VendorID is the vendor ID of TH2 -|70 | 11.17.7.12 |OPCREDS.S.C0a.Rsp(RemoveFabric)|TH2 sends RemoveFabric command with Fabric Index as FabricIndex_TH1 (Valid Fabric Index) to DUT | Verify that DUT sends NOCResponse Command with StatusCode of OK + self.print_step( + 72, "TH2 sends a CommissioningComplete command to the DUT | Verify that the DUT responds with a CommissioningCompleteResponse with the ErrorCode as 'OK'(0)") + # TODO: remove all steps below? This is covered in TC-RR-1.1 -|[[remove-fabric-ok,71]]71 |11.17.6.2 | OPCREDS.S.A0001(Fabrics)| TH2 reads the Fabrics List from DUT using a non-fabric-filtered read a|* Verify that there is a single entry with the following fields: -* Label is "Label 2" -* RootPublicKey field `Root_Public_Key_TH2` -* NodeId field matches matter-node-id in `Node_Operational_Certificate_TH2` -* FabricID field matches matter-fabric-id field in `Node_Operational_Certificate_TH2` -* VendorID is the vendor ID of TH2 + self.print_step(73, "TH2 sends an OpenCommissioningWindow command to the Administrator Commissioning cluster") -|72| 11.9.7.6 | | TH2 sends a CommissioningComplete command to the DUT | Verify that the DUT responds with a CommissioningCompleteResponse with the ErrorCode as 'OK'(0) + self.print_step( + 74, "TH1 fully commissions the DUT using subject-padded, 400 byte certificates | Verify that the commissioning completes successfully") + # |[[fill-fabric-table,75]]75| | | Repeat steps <> and <> to fill the fabric table using the remaining test harnesses (TH3 through TH `NumSupportedFabrics`). Each test harness should commission the DUT using subject-padded, 400-byte certificates | Verify that each commissioning completes successfully -|[[open-commissioning-window,73]]73 | 11.18.8.1 | | TH2 sends an OpenCommissioningWindow command to the Administrator Commissioning cluster | + # |76| 11.17.6.4| OPCREDS.S.A0003(CommissionedFabrics)| TH1 reads CommissionedFabrics attribute | Verify that attribute value matches `NumSupportedFabrics` -|[[commission-with-big-certs,74]]74 | 5.5 | | TH1 fully commissions the DUT using subject-padded, 400 byte certificates | Verify that the commissioning completes successfully -|[[fill-fabric-table,75]]75| | | Repeat steps <> and <> to fill the fabric table using the remaining test harnesses (TH3 through TH `NumSupportedFabrics`). Each test harness should commission the DUT using subject-padded, 400-byte certificates | Verify that each commissioning completes successfully + # |77 | | | Repeat steps <> and <> with TH `NumSupportedFabrics` + 1 | Verify that commissioning fails -|76| 11.17.6.4| OPCREDS.S.A0003(CommissionedFabrics)| TH1 reads CommissionedFabrics attribute | Verify that attribute value matches `NumSupportedFabrics` + # |78 | 9.10.5.5 | | TH1 reads the SubjectsPerAccessControlEntry attribute from the Access Control Cluster and saves the value as `maxSubjects` | -|77 | | | Repeat steps <> and <> with TH `NumSupportedFabrics` + 1 | Verify that commissioning fails + # |79 | 9.10.5.6 | | TH1 reads the TargetsPerAccessControlEntry attribute from the Access Control Cluster and saves the value as `maxTargets` | + # |80 | 9.10.5.7 | | TH1 reads the AccessControlEntriesPerFabric attribute from the Access Control Cluster and saves the value as `maxEntries` | -|78 | 9.10.5.5 | | TH1 reads the SubjectsPerAccessControlEntry attribute from the Access Control Cluster and saves the value as `maxSubjects` | + # |[[add-acls,81]]81 | | | TH1 creates a valid list of AccessControlEntryStructs with `maxEntries` entries. Each AccessControlEntryStruct specifies `maxSubjects` subjects and `maxTargets` targets. TH1 writes this list to the AccessControl cluster ACL attribute | Verify that the DUT returns SUCCESS -|79 | 9.10.5.6 | | TH1 reads the TargetsPerAccessControlEntry attribute from the Access Control Cluster and saves the value as `maxTargets` | -|80 | 9.10.5.7 | | TH1 reads the AccessControlEntriesPerFabric attribute from the Access Control Cluster and saves the value as `maxEntries` | + # | 82 | | |Repeat step <> for TH2 through TH `NumSupportedFabrics` to fill the ACL table | -|[[add-acls,81]]81 | | | TH1 creates a valid list of AccessControlEntryStructs with `maxEntries` entries. Each AccessControlEntryStruct specifies `maxSubjects` subjects and `maxTargets` targets. TH1 writes this list to the AccessControl cluster ACL attribute | Verify that the DUT returns SUCCESS -| 82 | | |Repeat step <> for TH2 through TH `NumSupportedFabrics` to fill the ACL table | +# TODO: remove all the extra stuff we did +if __name__ == "__main__": + default_matter_test_main()