diff --git a/tests/scripts/thread-cert/Cert_5_8_04_SecurityPolicyTLV.py b/tests/scripts/thread-cert/Cert_5_8_04_SecurityPolicyTLV.py new file mode 100755 index 000000000..16842e7e1 --- /dev/null +++ b/tests/scripts/thread-cert/Cert_5_8_04_SecurityPolicyTLV.py @@ -0,0 +1,409 @@ +#!/usr/bin/env python3 +# +# Copyright (c) 2020, The OpenThread Authors. +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# 1. Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# 2. Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# 3. Neither the name of the copyright holder nor the +# names of its contributors may be used to endorse or promote products +# derived from this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE +# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +# POSSIBILITY OF SUCH DAMAGE. +# + +import unittest + +from mesh_cop import TlvType +import thread_cert +from pktverify.consts import MLE_DATA_RESPONSE, MGMT_ACTIVE_SET_URI, MGMT_ACTIVE_GET_URI, LEADER_ALOC, NM_COMMISSIONER_SESSION_ID_TLV, NM_ACTIVE_TIMESTAMP_TLV, NM_SECURITY_POLICY_TLV, NM_NETWORK_MASTER_KEY_TLV, MLE_DISCOVERY_RESPONSE +from pktverify.packet_verifier import PacketVerifier +from pktverify.layer_fields import nullField +from pktverify.bytes import Bytes + +LEADER = 1 +COMMISSIONER_1 = 2 +COMMISSIONER_2 = 3 +THREAD_NODE = 4 + +# Test Purpose and Description: +# ----------------------------- +# The purpose of this test case is to verify network behavior when Security +# Policy TLV “O”,”N”,”R”,”B” bits are disabled. “C” bit is not tested as it +# requires an External Commissioner which is currently not part of Thread +# Certification. +# +# Notes: Due to the packet parsing compatiable issue for supporting Thread 1.2 +# and 1.1, the security policy values can be fetched only in the unknown +# field. +# +# Test Topology: +# ------------- +# Leader ---- Commissioner_2 +# Thread_Node | +# Commissioner_1 +# +# Notes: Commissioner_2 is introduced in Step 10 and powoff +# Thread_Node sends scan beacon +# +# DUT Types: +# ---------- +# Leader + + +class Cert_5_8_04_SecurityPolicyTLV(thread_cert.TestCase): + SUPPORT_NCP = False + USE_MESSAGE_FACTORY = False + + TOPOLOGY = { + LEADER: { + 'name': 'LEADER', + 'active_dataset': { + 'timestamp': 1, + 'channel': 19, + 'master_key': '00112233445566778899aabbccddeeff', + 'security_policy': [3600, 'onrcb'] + }, + 'mode': 'rdn', + 'router_selection_jitter': 1 + }, + COMMISSIONER_1: { + 'name': 'COMMISSIONER_1', + 'active_dataset': { + 'timestamp': 1, + 'channel': 19, + 'master_key': '00112233445566778899aabbccddeeff', + 'security_policy': [3600, 'onrcb'] + }, + 'mode': 'rdn', + 'router_selection_jitter': 1, + 'allowlist': [LEADER] + }, + COMMISSIONER_2: { + 'name': 'COMMISSIONER_2', + 'router_selection_jitter': 1, + 'mode': 'rdn', + 'allowlist': [LEADER] + }, + THREAD_NODE: { + 'name': 'THREAD_NODE', + 'active_dataset': { + 'timestamp': 1, + 'channel': 19, + 'master_key': '00112233445566778899aabbccddeeff', + 'security_policy': [3600, 'onrcb'] + }, + 'mode': 'rdn', + 'router_selection_jitter': 1 + }, + } + + def test(self): + self.nodes[LEADER].start() + self.simulator.go(5) + self.assertEqual(self.nodes[LEADER].get_state(), 'leader') + + self.nodes[COMMISSIONER_1].start() + self.simulator.go(5) + self.assertEqual(self.nodes[COMMISSIONER_1].get_state(), 'router') + + self.nodes[COMMISSIONER_1].commissioner_start() + self.simulator.go(5) + self.nodes[COMMISSIONER_1].commissioner_add_joiner('*', 'PSKD01') + + self.collect_rlocs() + leader_rloc = self.nodes[LEADER].get_rloc() + + # Step 2 + self.nodes[COMMISSIONER_1].send_mgmt_active_get() + self.simulator.go(5) + + # Step 5 + # Disabling O-Bit security_policy = [3600, 0b01111000] + self.nodes[COMMISSIONER_1].send_mgmt_active_set( + active_timestamp=15, + binary='0c030e1078', + ) + self.simulator.go(5) + + # Step 7 + # Get MasterKey + self.nodes[COMMISSIONER_1].send_mgmt_active_get(leader_rloc, [TlvType.NETWORK_MASTER_KEY]) + self.simulator.go(5) + + # Step 9 + # Disabling N-Bit security_policy = [3600, 0b10111000] + + self.nodes[COMMISSIONER_1].send_mgmt_active_set( + active_timestamp=20, + binary='0c030e10b8', + ) + self.simulator.go(5) + + # Step 10 + # Add Native Commissioner + self.nodes[COMMISSIONER_2].interface_up() + self.nodes[COMMISSIONER_2].joiner_start('10DKSP') + self.simulator.go(5) + self.nodes[COMMISSIONER_2].reset() + + # Step 13 + # Disabling B-Bit security_policy = [3600, 0b11110000] + self.nodes[COMMISSIONER_1].send_mgmt_active_set( + active_timestamp=25, + binary='0c030e10f0', + ) + self.simulator.go(5) + + # Step 15 + # send beacons + self.nodes[THREAD_NODE].start() + self.simulator.go(2) + self.nodes[THREAD_NODE].scan(result=0) + self.simulator.go(20) + + # Step 17 + # Disabling R-Bit security_policy = [3600, 0b11011000] + self.nodes[COMMISSIONER_1].send_mgmt_active_set( + active_timestamp=30, + binary='0c030e10d8', + ) + self.simulator.go(5) + + def verify(self, pv): + pkts = pv.pkts + pv.summary.show() + + LEADER = pv.vars['LEADER'] + LEADER_RLOC = pv.vars['LEADER_RLOC'] + COMMISSIONER_1 = pv.vars['COMMISSIONER_1'] + COMMISSIONER_1_RLOC = pv.vars['COMMISSIONER_1_RLOC'] + COMMISSIONER_2 = pv.vars['COMMISSIONER_2'] + + # Step 1: Ensure the topology is formed correctly + pv.verify_attached('COMMISSIONER_1', 'LEADER') + + # Step 2: Commissioner_1 sends MGMT_ACTIVE_GET.req to Leader + # CoAP Request URI + # coap://[]:MM/c/ag + # CoAP Payload + # + pkts.filter_wpan_src64(COMMISSIONER_1).\ + filter_ipv6_2dsts(LEADER_RLOC, LEADER_ALOC).\ + filter_coap_request(MGMT_ACTIVE_GET_URI).\ + filter(lambda p: p.thread_meshcop.tlv.type is nullField).\ + must_next() + + # Step 3: Leader MUST send MGMT_ACTIVE_GET.rsp to the Commissioner_1 + # CoAP Response Code + # 2.04 Changed + # CoAP Payload + # Security Policy TLV + # Bits “O”,”N”,”R”,”C”,”B” should be set to 1 + pkts.filter_wpan_src64(LEADER).\ + filter_ipv6_dst(COMMISSIONER_1_RLOC).\ + filter_coap_ack(MGMT_ACTIVE_GET_URI).\ + filter(lambda p: p.thread_meshcop.tlv.unknown == '0e10f8').\ + must_next() + + # Step 5: Commissioner_1 sends MGMT_ACTIVE_SET.req to Leader + # CoAP Request URI + # coap://[]:MM/c/as + # CoAP Payload + # Commissioner Session ID TLV + # Active Timestamp TLV > stored value in step 4 + # Security Policy TLV with “O” bit disabled + pkts.filter_wpan_src64(COMMISSIONER_1). \ + filter_ipv6_2dsts(LEADER_RLOC, LEADER_ALOC). \ + filter_coap_request(MGMT_ACTIVE_SET_URI). \ + filter(lambda p: { + NM_COMMISSIONER_SESSION_ID_TLV, + NM_ACTIVE_TIMESTAMP_TLV, + NM_SECURITY_POLICY_TLV + } == set(p.thread_meshcop.tlv.type) and\ + p.thread_meshcop.tlv.active_tstamp == 15 and\ + p.thread_meshcop.tlv.unknown == '0e1078').\ + must_next() + + # Step 6: Leader MUST send MGMT_ACTIVE_SET.rsp to the Commissioner_1 + # CoAP Response Code + # 2.04 Changed + # CoAP Payload + # State TLV (value = Accept (0x01)) + pkts.filter_wpan_src64(LEADER).\ + filter_ipv6_dst(COMMISSIONER_1_RLOC).\ + filter_coap_ack(MGMT_ACTIVE_SET_URI).\ + filter(lambda p: p.thread_meshcop.tlv.state == 1).\ + must_next() + + # Step 7: Commissioner_1 sends MGMT_ACTIVE_GET.req to Leader + # CoAP Request URI + # coap://[]:MM/c/ag + # CoAP Payload + # Network Master Key TLV + pkts.filter_wpan_src64(COMMISSIONER_1).\ + filter_ipv6_2dsts(LEADER_RLOC, LEADER_ALOC).\ + filter_coap_request(MGMT_ACTIVE_GET_URI).\ + filter(lambda p: NM_NETWORK_MASTER_KEY_TLV in p.thread_meshcop.tlv.type).\ + must_next() + + # Step 8: Leader MUST send MGMT_ACTIVE_GET.rsp to the Commissioner_1 + # CoAP Response Code + # 2.04 Changed + # CoAP Payload + # Network Master Key TLV MUST NOT be included + pkts.filter_wpan_src64(LEADER).\ + filter_ipv6_dst(COMMISSIONER_1_RLOC).\ + filter_coap_ack(MGMT_ACTIVE_GET_URI).\ + filter(lambda p: p.thread_meshcop.tlv.type is nullField).\ + must_next() + + # Step 9: Commissioner_1 sends MGMT_ACTIVE_SET.req to Leader + # CoAP Request URI + # coap://[]:MM/c/as + # CoAP Payload + # Commissioner Session ID TLV + # Active Timestamp TLV > stored value in step 5 + # Security Policy TLV with “N” bit disabled + pkts.filter_wpan_src64(COMMISSIONER_1). \ + filter_ipv6_2dsts(LEADER_RLOC, LEADER_ALOC). \ + filter_coap_request(MGMT_ACTIVE_SET_URI). \ + filter(lambda p: { + NM_COMMISSIONER_SESSION_ID_TLV, + NM_ACTIVE_TIMESTAMP_TLV, + NM_SECURITY_POLICY_TLV + } == set(p.thread_meshcop.tlv.type) and\ + p.thread_meshcop.tlv.active_tstamp == 20 and\ + p.thread_meshcop.tlv.unknown == '0e10b8').\ + must_next() + + # Step 10: Leader MUST send MGMT_ACTIVE_SET.rsp to the Commissioner_1 + # CoAP Response Code + # 2.04 Changed + # CoAP Payload + # State TLV (value = Accept (0x01)) + pkts.filter_wpan_src64(LEADER).\ + filter_ipv6_dst(COMMISSIONER_1_RLOC).\ + filter_coap_ack(MGMT_ACTIVE_SET_URI).\ + filter(lambda p: p.thread_meshcop.tlv.state == 1).\ + must_next() + + # Step 12: Leader MUST send a Discovery Response with Native Commissioning + # bit set to “Not Allowed” + pkts.filter_wpan_src64(LEADER).\ + filter_mle_cmd(MLE_DISCOVERY_RESPONSE).\ + filter(lambda p: p.thread_meshcop.tlv.discovery_rsp_n == 0).\ + must_next() + + # Step 13: Commissioner_1 sends MGMT_ACTIVE_SET.req to Leader + # CoAP Request URI + # coap://[]:MM/c/as + # CoAP Payload + # Commissioner Session ID TLV + # Active Timestamp TLV > stored value in step 9 + # Security Policy TLV with “B” bit disabled + pkts.filter_wpan_src64(COMMISSIONER_1). \ + filter_ipv6_2dsts(LEADER_RLOC, LEADER_ALOC). \ + filter_coap_request(MGMT_ACTIVE_SET_URI). \ + filter(lambda p: { + NM_COMMISSIONER_SESSION_ID_TLV, + NM_ACTIVE_TIMESTAMP_TLV, + NM_SECURITY_POLICY_TLV + } == set(p.thread_meshcop.tlv.type) and\ + p.thread_meshcop.tlv.active_tstamp == 25 and\ + p.thread_meshcop.tlv.unknown == '0e10f0').\ + must_next() + + # Step 14: Leader MUST send MGMT_ACTIVE_SET.rsp to the Commissioner_1 + # CoAP Response Code + # 2.04 Changed + # CoAP Payload + # State TLV (value = Accept (0x01)) + pkts.filter_wpan_src64(LEADER).\ + filter_ipv6_dst(COMMISSIONER_1_RLOC).\ + filter_coap_ack(MGMT_ACTIVE_SET_URI).\ + filter(lambda p: p.thread_meshcop.tlv.state == 1).\ + must_next() + + # Step 16: The DUT MUST send beacon response frames.The beacon payload MUST + # either be empty OR the payload format MUST be different from the + # Thread Beacon payload The Protocol ID and Version field values + # MUST be different from the values specified for the Thread beacon + # (Protocol ID= 3, Version = 2) + pkts.filter_wpan_src64(LEADER).\ + filter_wpan_beacon().\ + filter(lambda p: + (p.thread_bcn.protocol is nullField or\ + p.thread_bcn.protocol != 3) and\ + (p.thread_bcn.version is nullField or\ + p.thread_bcn.version != 2) + ).\ + must_next() + + # Step 17: Commissioner_1 sends MGMT_ACTIVE_SET.req to Leader + # CoAP Request URI + # coap://[]:MM/c/as + # CoAP Payload + # Commissioner Session ID TLV + # Active Timestamp TLV > stored value in step 9 + # Security Policy TLV with “R” bit disabled + pkts.filter_wpan_src64(COMMISSIONER_1). \ + filter_ipv6_2dsts(LEADER_RLOC, LEADER_ALOC). \ + filter_coap_request(MGMT_ACTIVE_SET_URI). \ + filter(lambda p: { + NM_COMMISSIONER_SESSION_ID_TLV, + NM_ACTIVE_TIMESTAMP_TLV, + NM_SECURITY_POLICY_TLV + } == set(p.thread_meshcop.tlv.type) and\ + p.thread_meshcop.tlv.active_tstamp == 30 and\ + p.thread_meshcop.tlv.unknown == '0e10d8').\ + must_next() + + # Step 18: Leader MUST send MGMT_ACTIVE_SET.rsp to the Commissioner_1 + # CoAP Response Code + # 2.04 Changed + # CoAP Payload + # State TLV (value = Accept (0x01)) + # Leader MUST multicast MLE Data Response to the Link-Local All Nodes + # multicast address (FF02::1) with active timestamp value as set in + # Step 17. + pkts.filter_wpan_src64(LEADER).\ + filter_ipv6_dst(COMMISSIONER_1_RLOC).\ + filter_coap_ack(MGMT_ACTIVE_SET_URI).\ + filter(lambda p: p.thread_meshcop.tlv.state == 1).\ + must_next() + pkts.filter_wpan_src64(LEADER).\ + filter_LLANMA().\ + filter_mle_cmd(MLE_DATA_RESPONSE).\ + filter(lambda p: p.mle.tlv.active_tstamp == 30).\ + must_next() + + # Step 20: The DUT MUST send a unicast MLE Data Response to Commissioner_1. + # The Active Operational Set MUST contain a Security Policy TLV with + # R bit set to 0. + pkts.filter_wpan_src64(LEADER).\ + filter_wpan_dst64(COMMISSIONER_1). \ + filter_mle_cmd(MLE_DATA_RESPONSE).\ + filter(lambda p: + p.mle.tlv.active_tstamp == 30 and\ + p.thread_meshcop.tlv.unknown == '0e10d8').\ + must_next() + + +if __name__ == '__main__': + unittest.main() diff --git a/tests/scripts/thread-cert/Makefile.am b/tests/scripts/thread-cert/Makefile.am index 03e3fda84..5aaf1a58a 100644 --- a/tests/scripts/thread-cert/Makefile.am +++ b/tests/scripts/thread-cert/Makefile.am @@ -80,6 +80,7 @@ EXTRA_DIST = \ Cert_5_7_03_CoapDiagCommands.py \ Cert_5_8_02_KeyIncrement.py \ Cert_5_8_03_KeyIncrementRollOver.py \ + Cert_5_8_04_SecurityPolicyTLV.py \ Cert_6_1_01_RouterAttach.py \ Cert_6_1_02_REEDAttach.py \ Cert_6_1_03_RouterAttachConnectivity.py \ @@ -264,6 +265,7 @@ check_SCRIPTS = \ Cert_5_7_03_CoapDiagCommands.py \ Cert_5_8_02_KeyIncrement.py \ Cert_5_8_03_KeyIncrementRollOver.py \ + Cert_5_8_04_SecurityPolicyTLV.py \ Cert_6_1_01_RouterAttach.py \ Cert_6_1_02_REEDAttach.py \ Cert_6_1_03_RouterAttachConnectivity.py \ diff --git a/tests/scripts/thread-cert/node.py b/tests/scripts/thread-cert/node.py index 87581028d..3f3fc7c5c 100755 --- a/tests/scripts/thread-cert/node.py +++ b/tests/scripts/thread-cert/node.py @@ -1333,10 +1333,12 @@ class NodeImpl: self._expect('Conflict:', timeout=timeout) - def scan(self): + def scan(self, result=1): self.send_command('scan') - return self._expect_results(r'\|\s(\S+)\s+\|\s(\S+)\s+\|\s([0-9a-fA-F]{4})\s\|\s([0-9a-fA-F]{16})\s\|\s(\d+)') + if result == 1: + return self._expect_results( + r'\|\s(\S+)\s+\|\s(\S+)\s+\|\s([0-9a-fA-F]{4})\s\|\s([0-9a-fA-F]{16})\s\|\s(\d+)') def ping(self, ipaddr, num_responses=1, size=None, timeout=5): cmd = 'ping %s' % ipaddr @@ -1387,6 +1389,7 @@ class NodeImpl: channel=None, channel_mask=None, master_key=None, + security_policy=[], ): self.send_command('dataset clear') self._expect('Done') @@ -1415,6 +1418,14 @@ class NodeImpl: self.send_command(cmd) self._expect('Done') + if security_policy and len(security_policy) == 2: + cmd = 'dataset securitypolicy %s %s' % ( + str(security_policy[0]), + security_policy[1], + ) + self.send_command(cmd) + self._expect('Done') + # Set the meshlocal prefix in config.py self.send_command('dataset meshlocalprefix %s' % config.MESH_LOCAL_PREFIX.split('/')[0]) self._expect('Done') diff --git a/tests/scripts/thread-cert/pktverify/consts.py b/tests/scripts/thread-cert/pktverify/consts.py index ccf319982..177e62646 100644 --- a/tests/scripts/thread-cert/pktverify/consts.py +++ b/tests/scripts/thread-cert/pktverify/consts.py @@ -293,6 +293,7 @@ REAL_LAYER_NAMES = { 'thread_address', 'thread_diagnostic', 'thread_nm', + 'thread_bcn', 'ssdp', 'dns', 'igmp', @@ -338,6 +339,7 @@ MAC_FRAME_VERSION_2006 = 1 MAC_FRAME_VERSION_2015 = 2 # 802.15.4 Frame Type +MAC_FRAME_TYPE_BEACON = 0x0 MAC_FRAME_TYPE_DATA = 0x1 MAC_FRAME_TYPE_ACK = 0x2 MAC_FRAME_TYPE_MAC_CMD = 0x3 diff --git a/tests/scripts/thread-cert/pktverify/layer_fields.py b/tests/scripts/thread-cert/pktverify/layer_fields.py index 93e1145c2..983f955b9 100644 --- a/tests/scripts/thread-cert/pktverify/layer_fields.py +++ b/tests/scripts/thread-cert/pktverify/layer_fields.py @@ -536,6 +536,12 @@ _LAYER_FIELDS = { 'dtls.record.content_type': _list(_auto), 'dtls.alert_message.desc': _auto, + # thread beacon + 'thread_bcn.protocol': _auto, + 'thread_bcn.version': _auto, + 'thread_bcn.network_name': _str, + 'thread_bcn.epid': _ext_addr, + # thread_address 'thread_address.tlv.len': _list(_auto), 'thread_address.tlv.type': _list(_auto), @@ -576,6 +582,7 @@ _LAYER_FIELDS = { 'thread_meshcop.tlv.chan_mask_mask': _bytes, 'thread_meshcop.tlv.discovery_req_ver': _auto, 'thread_meshcop.tlv.discovery_rsp_ver': _auto, + 'thread_meshcop.tlv.discovery_rsp_n': _auto, 'thread_meshcop.tlv.energy_list': _list(_auto), 'thread_meshcop.tlv.pan_id': _list(_auto), 'thread_meshcop.tlv.xpan_id': _bytes, @@ -734,6 +741,8 @@ def _get_candidate_layers(packet, layer_name): candidate_layer_names = ['wpan', 'mle'] elif layer_name == 'ip': candidate_layer_names = ['ip', 'ipv6'] + elif layer_name == 'thread_bcn': + candidate_layer_names = ['thread_bcn'] else: candidate_layer_names = [layer_name] diff --git a/tests/scripts/thread-cert/pktverify/packet_filter.py b/tests/scripts/thread-cert/pktverify/packet_filter.py index 586f8f0b2..8ad6dcf43 100644 --- a/tests/scripts/thread-cert/pktverify/packet_filter.py +++ b/tests/scripts/thread-cert/pktverify/packet_filter.py @@ -445,6 +445,15 @@ class PacketFilter(object): """ return self.filter(lambda p: p.wpan.frame_type == consts.MAC_FRAME_TYPE_ACK, **kwargs) + def filter_wpan_beacon(self, **kwargs): + """ + Create a new PacketFilter for filter WPAN beacon. + + :param kwargs: Extra arguments for `filter`. + :return: The new PacketFilter to filter WPAN packets. + """ + return self.filter(lambda p: p.wpan.frame_type == consts.MAC_FRAME_TYPE_BEACON, **kwargs) + def filter_wpan_data(self, **kwargs): """ Create a new PacketFilter for filter WPAN data packets. diff --git a/tests/scripts/thread-cert/pktverify/utils.py b/tests/scripts/thread-cert/pktverify/utils.py index 6d95a5e77..111dbbdb0 100644 --- a/tests/scripts/thread-cert/pktverify/utils.py +++ b/tests/scripts/thread-cert/pktverify/utils.py @@ -71,6 +71,7 @@ def make_filter_func(func: Union[str, Callable], **vars) -> Callable: 'thread_nm': p.thread_nm, 'thread_nwd': p.thread_nwd, 'thread_address': p.thread_address, + 'thread_bcn': p.thread_bcn, 'null': nullField, }) else: diff --git a/tests/scripts/thread-cert/thread_cert.py b/tests/scripts/thread-cert/thread_cert.py index b20801602..ed2393de8 100644 --- a/tests/scripts/thread-cert/thread_cert.py +++ b/tests/scripts/thread-cert/thread_cert.py @@ -188,7 +188,8 @@ class TestCase(NcpSupportMixin, unittest.TestCase): panid=params['active_dataset'].get('panid'), channel=params['active_dataset'].get('channel'), channel_mask=params['active_dataset'].get('channel_mask'), - master_key=params['active_dataset'].get('master_key')) + master_key=params['active_dataset'].get('master_key'), + security_policy=params['active_dataset'].get('security_policy')) if 'pending_dataset' in params: self.nodes[i].set_pending_dataset(params['pending_dataset']['pendingtimestamp'],