class AclManagerTest(GdBaseTestClass):
    def setup_class(self):
        super().setup_class(dut_module='HCI_INTERFACES', cert_module='HCI')

    # todo: move into GdBaseTestClass, based on modules inited
    def setup_test(self):
        super().setup_test()
        self.cert_hci = PyHci(self.cert, acl_streaming=True)
        self.dut_acl_manager = PyAclManager(self.dut)

    def teardown_test(self):
        self.cert_hci.close()
        self.dut_acl_manager.close()
        super().teardown_test()

    def test_dut_connects(self):
        self.cert_hci.enable_inquiry_and_page_scan()
        cert_address = self.cert_hci.read_own_address()

        with self.dut_acl_manager.initiate_connection(cert_address) as dut_acl:
            cert_acl = self.cert_hci.accept_connection()
            cert_acl.send_first(
                b'\x26\x00\x07\x00This is just SomeAclData from the Cert')

            dut_acl.wait_for_connection_complete()

            dut_acl.send(
                b'\x29\x00\x07\x00This is just SomeMoreAclData from the DUT')

            assertThat(cert_acl).emits(
                lambda packet: b'SomeMoreAclData' in packet.data)
            assertThat(dut_acl).emits(
                lambda packet: b'SomeAclData' in packet.payload)

    def test_cert_connects(self):
        dut_address = self.dut.hci_controller.GetMacAddressSimple()
        self.dut.neighbor.EnablePageScan(
            neighbor_facade.EnableMsg(enabled=True))

        self.dut_acl_manager.listen_for_incoming_connections()
        self.cert_hci.initiate_connection(dut_address)

        dut_acl = self.dut_acl_manager.accept_connection()

        cert_acl = self.cert_hci.complete_connection()

        dut_acl.send(
            b'\x29\x00\x07\x00This is just SomeMoreAclData from the DUT')

        cert_acl.send_first(
            b'\x26\x00\x07\x00This is just SomeAclData from the Cert')

        assertThat(cert_acl).emits(
            lambda packet: b'SomeMoreAclData' in packet.data)
        assertThat(dut_acl).emits(
            lambda packet: b'SomeAclData' in packet.payload)

    def test_recombination_l2cap_packet(self):
        self.cert_hci.enable_inquiry_and_page_scan()
        cert_address = self.cert_hci.read_own_address()

        with self.dut_acl_manager.initiate_connection(cert_address) as dut_acl:
            cert_acl = self.cert_hci.accept_connection()
            cert_acl.send_first(b'\x06\x00\x07\x00Hello')
            cert_acl.send_continuing(b'!')
            cert_acl.send_first(b'\xe8\x03\x07\x00' + b'Hello' * 200)

            dut_acl.wait_for_connection_complete()

            assertThat(dut_acl).emits(
                lambda packet: b'Hello!' in packet.payload,
                lambda packet: b'Hello' * 200 in packet.payload).inOrder()
class LeAdvertisingManagerTest(GdBaseTestClass):
    def setup_class(self):
        super().setup_class(dut_module='HCI_INTERFACES', cert_module='HCI')

    def setup_test(self):
        super().setup_test()
        self.cert_hci = PyHci(self.cert, acl_streaming=True)

    def teardown_test(self):
        self.cert_hci.close()
        super().teardown_test()

    def test_le_ad_scan_dut_advertises(self):
        self.cert_hci.register_for_le_events(
            hci_packets.SubeventCode.ADVERTISING_REPORT,
            hci_packets.SubeventCode.EXTENDED_ADVERTISING_REPORT)

        # CERT Scans
        self.cert_hci.send_command(
            hci_packets.LeSetRandomAddressBuilder('0C:05:04:03:02:01'))
        scan_parameters = hci_packets.PhyScanParameters()
        scan_parameters.le_scan_type = hci_packets.LeScanType.ACTIVE
        scan_parameters.le_scan_interval = 40
        scan_parameters.le_scan_window = 20
        self.cert_hci.send_command(
            hci_packets.LeSetExtendedScanParametersBuilder(
                hci_packets.OwnAddressType.RANDOM_DEVICE_ADDRESS,
                hci_packets.LeScanningFilterPolicy.ACCEPT_ALL, 1,
                [scan_parameters]))
        self.cert_hci.send_command(
            hci_packets.LeSetExtendedScanEnableBuilder(
                hci_packets.Enable.ENABLED,
                hci_packets.FilterDuplicates.DISABLED, 0, 0))

        # DUT Advertises
        gap_name = hci_packets.GapData()
        gap_name.data_type = hci_packets.GapDataType.COMPLETE_LOCAL_NAME
        gap_name.data = list(bytes(b'Im_The_DUT'))
        gap_data = le_advertising_facade.GapDataMsg(
            data=bytes(gap_name.Serialize()))
        config = le_advertising_facade.AdvertisingConfig(
            advertisement=[gap_data],
            interval_min=512,
            interval_max=768,
            advertising_type=le_advertising_facade.AdvertisingEventType.
            ADV_IND,
            own_address_type=common.USE_RANDOM_DEVICE_ADDRESS,
            channel_map=7,
            filter_policy=le_advertising_facade.AdvertisingFilterPolicy.
            ALL_DEVICES)
        request = le_advertising_facade.CreateAdvertiserRequest(config=config)

        create_response = self.dut.hci_le_advertising_manager.CreateAdvertiser(
            request)

        assertThat(self.cert_hci.get_le_event_stream()).emits(
            lambda packet: b'Im_The_DUT' in packet.payload)

        remove_request = le_advertising_facade.RemoveAdvertiserRequest(
            advertiser_id=create_response.advertiser_id)
        self.dut.hci_le_advertising_manager.RemoveAdvertiser(remove_request)
        self.cert_hci.send_command(
            hci_packets.LeSetScanEnableBuilder(hci_packets.Enable.DISABLED,
                                               hci_packets.Enable.DISABLED))
class NeighborTest(GdBaseTestClass):
    def setup_class(self):
        super().setup_class(dut_module='HCI_INTERFACES', cert_module='HCI')

    def setup_test(self):
        super().setup_test()
        self.cert_hci = PyHci(self.cert, acl_streaming=True)
        self.cert_hci.send_command_with_complete(
            hci_packets.WriteScanEnableBuilder(
                hci_packets.ScanEnable.INQUIRY_AND_PAGE_SCAN))
        self.cert_name = b'Im_A_Cert'
        self.cert_address = self.cert_hci.read_own_address()
        self.cert_name += b'@' + self.cert_address.encode('utf8')
        self.dut_neighbor = PyNeighbor(self.dut)

    def teardown_test(self):
        self.cert_hci.close()
        super().teardown_test()

    def _set_name(self):
        padded_name = self.cert_name
        while len(padded_name) < 248:
            padded_name = padded_name + b'\0'
        self.cert_hci.send_command_with_complete(
            hci_packets.WriteLocalNameBuilder(padded_name))

        assertThat(self.cert_hci.get_event_stream()).emits(
            HciMatchers.CommandComplete(OpCode.WRITE_LOCAL_NAME))

    def test_inquiry_from_dut(self):
        inquiry_msg = neighbor_facade.InquiryMsg(
            inquiry_mode=neighbor_facade.DiscoverabilityMode.GENERAL,
            result_mode=neighbor_facade.ResultMode.STANDARD,
            length_1_28s=3,
            max_results=0)
        session = self.dut_neighbor.set_inquiry_mode(inquiry_msg)
        self.cert_hci.send_command_with_complete(
            hci_packets.WriteScanEnableBuilder(
                hci_packets.ScanEnable.INQUIRY_AND_PAGE_SCAN))
        assertThat(session).emits(NeighborMatchers.InquiryResult(
            self.cert_address),
                                  timeout=timedelta(seconds=10))

    def test_inquiry_rssi_from_dut(self):
        inquiry_msg = neighbor_facade.InquiryMsg(
            inquiry_mode=neighbor_facade.DiscoverabilityMode.GENERAL,
            result_mode=neighbor_facade.ResultMode.RSSI,
            length_1_28s=6,
            max_results=0)
        session = self.dut_neighbor.set_inquiry_mode(inquiry_msg)
        self.cert_hci.send_command_with_complete(
            hci_packets.WriteScanEnableBuilder(
                hci_packets.ScanEnable.INQUIRY_AND_PAGE_SCAN))
        assertThat(session).emits(NeighborMatchers.InquiryResultwithRssi(
            self.cert_address),
                                  timeout=timedelta(seconds=10))

    def test_inquiry_extended_from_dut(self):
        self._set_name()
        gap_name = hci_packets.GapData()
        gap_name.data_type = hci_packets.GapDataType.COMPLETE_LOCAL_NAME
        gap_name.data = list(bytes(self.cert_name))
        gap_data = list([gap_name])

        self.cert_hci.send_command_with_complete(
            hci_packets.WriteExtendedInquiryResponseBuilder(
                hci_packets.FecRequired.NOT_REQUIRED, gap_data))
        inquiry_msg = neighbor_facade.InquiryMsg(
            inquiry_mode=neighbor_facade.DiscoverabilityMode.GENERAL,
            result_mode=neighbor_facade.ResultMode.EXTENDED,
            length_1_28s=8,
            max_results=0)
        session = self.dut_neighbor.set_inquiry_mode(inquiry_msg)
        self.cert_hci.send_command_with_complete(
            hci_packets.WriteScanEnableBuilder(
                hci_packets.ScanEnable.INQUIRY_AND_PAGE_SCAN))
        assertThat(session).emits(NeighborMatchers.ExtendedInquiryResult(
            self.cert_address),
                                  timeout=timedelta(seconds=10))

    def test_remote_name(self):
        self._set_name()
        session = self.dut_neighbor.get_remote_name(self.cert_address)
        session.verify_name(self.cert_name)
class DirectHciTest(GdBaseTestClass):
    def setup_class(self):
        super().setup_class(dut_module='HCI', cert_module='HAL')

    def setup_test(self):
        super().setup_test()
        self.dut_hci = PyHci(self.dut, acl_streaming=True)
        self.cert_hal = PyHal(self.cert)
        self.cert_hal.send_hci_command(ResetBuilder())

    def teardown_test(self):
        self.dut_hci.close()
        self.cert_hal.close()
        super().teardown_test()

    def enqueue_acl_data(self, handle, pb_flag, b_flag, data):
        acl = AclBuilder(handle, pb_flag, b_flag, RawBuilder(data))
        self.dut.hci.SendAcl(common.Data(payload=bytes(acl.Serialize())))

    def test_local_hci_cmd_and_event(self):
        # Loopback mode responds with ACL and SCO connection complete
        self.dut_hci.register_for_events(EventCode.LOOPBACK_COMMAND)
        self.dut_hci.send_command(
            WriteLoopbackModeBuilder(LoopbackMode.ENABLE_LOCAL))

        self.dut_hci.send_command(ReadLocalNameBuilder())
        assertThat(self.dut_hci.get_event_stream()).emits(
            HciMatchers.LoopbackOf(ReadLocalNameBuilder()))

    def test_inquiry_from_dut(self):
        self.dut_hci.register_for_events(EventCode.INQUIRY_RESULT)

        self.cert_hal.enable_inquiry_and_page_scan()
        lap = Lap()
        lap.lap = 0x33
        self.dut_hci.send_command(InquiryBuilder(lap, 0x30, 0xff))
        assertThat(self.dut_hci.get_event_stream()).emits(
            HciMatchers.EventWithCode(EventCode.INQUIRY_RESULT))

    def test_le_ad_scan_cert_advertises(self):
        self.dut_hci.register_for_le_events(
            SubeventCode.EXTENDED_ADVERTISING_REPORT,
            SubeventCode.ADVERTISING_REPORT)

        # DUT Scans
        self.dut_hci.send_command(
            LeSetRandomAddressBuilder('0D:05:04:03:02:01'))
        phy_scan_params = PhyScanParameters()
        phy_scan_params.le_scan_interval = 6553
        phy_scan_params.le_scan_window = 6553
        phy_scan_params.le_scan_type = LeScanType.ACTIVE

        self.dut_hci.send_command(
            LeSetExtendedScanParametersBuilder(
                OwnAddressType.RANDOM_DEVICE_ADDRESS,
                LeScanningFilterPolicy.ACCEPT_ALL, 1, [phy_scan_params]))
        self.dut_hci.send_command(
            LeSetExtendedScanEnableBuilder(Enable.ENABLED,
                                           FilterDuplicates.DISABLED, 0, 0))

        # CERT Advertises
        advertising_handle = 0
        self.cert_hal.send_hci_command(
            LeSetExtendedAdvertisingLegacyParametersBuilder(
                advertising_handle,
                LegacyAdvertisingProperties.ADV_IND,
                512,
                768,
                7,
                OwnAddressType.RANDOM_DEVICE_ADDRESS,
                PeerAddressType.PUBLIC_DEVICE_OR_IDENTITY_ADDRESS,
                'A6:A5:A4:A3:A2:A1',
                AdvertisingFilterPolicy.ALL_DEVICES,
                0xF7,
                1,  # SID
                Enable.DISABLED  # Scan request notification
            ))

        self.cert_hal.send_hci_command(
            LeSetExtendedAdvertisingRandomAddressBuilder(
                advertising_handle, '0C:05:04:03:02:01'))
        gap_name = GapData()
        gap_name.data_type = GapDataType.COMPLETE_LOCAL_NAME
        gap_name.data = list(bytes(b'Im_A_Cert'))

        self.cert_hal.send_hci_command(
            LeSetExtendedAdvertisingDataBuilder(
                advertising_handle, Operation.COMPLETE_ADVERTISEMENT,
                FragmentPreference.CONTROLLER_SHOULD_NOT, [gap_name]))

        gap_short_name = GapData()
        gap_short_name.data_type = GapDataType.SHORTENED_LOCAL_NAME
        gap_short_name.data = list(bytes(b'Im_A_C'))

        self.cert_hal.send_hci_command(
            LeSetExtendedAdvertisingScanResponseBuilder(
                advertising_handle, Operation.COMPLETE_ADVERTISEMENT,
                FragmentPreference.CONTROLLER_SHOULD_NOT, [gap_short_name]))

        enabled_set = EnabledSet()
        enabled_set.advertising_handle = 0
        enabled_set.duration = 0
        enabled_set.max_extended_advertising_events = 0
        self.cert_hal.send_hci_command(
            LeSetExtendedAdvertisingEnableBuilder(Enable.ENABLED,
                                                  [enabled_set]))

        assertThat(self.dut_hci.get_le_event_stream()).emits(
            lambda packet: b'Im_A_Cert' in packet.payload)

        self.cert_hal.send_hci_command(
            LeSetExtendedAdvertisingEnableBuilder(Enable.DISABLED,
                                                  [enabled_set]))
        self.dut_hci.send_command(
            LeSetExtendedScanEnableBuilder(Enable.DISABLED,
                                           FilterDuplicates.DISABLED, 0, 0))

    def _verify_le_connection_complete(self):
        cert_conn_complete_capture = HalCaptures.LeConnectionCompleteCapture()
        assertThat(self.cert_hal.get_hci_event_stream()).emits(
            cert_conn_complete_capture)
        cert_handle = cert_conn_complete_capture.get().GetConnectionHandle()

        dut_conn_complete_capture = HciCaptures.LeConnectionCompleteCapture()
        assertThat(self.dut_hci.get_le_event_stream()).emits(
            dut_conn_complete_capture)
        dut_handle = dut_conn_complete_capture.get().GetConnectionHandle()

        return (dut_handle, cert_handle)

    @staticmethod
    def _create_phy_scan_params():
        phy_scan_params = LeCreateConnPhyScanParameters()
        phy_scan_params.scan_interval = 0x60
        phy_scan_params.scan_window = 0x30
        phy_scan_params.conn_interval_min = 0x18
        phy_scan_params.conn_interval_max = 0x28
        phy_scan_params.conn_latency = 0
        phy_scan_params.supervision_timeout = 0x1f4
        phy_scan_params.min_ce_length = 0
        phy_scan_params.max_ce_length = 0
        return phy_scan_params

    def test_le_connection_dut_advertises(self):
        self.dut_hci.register_for_le_events(
            SubeventCode.CONNECTION_COMPLETE,
            SubeventCode.ADVERTISING_SET_TERMINATED,
            SubeventCode.ENHANCED_CONNECTION_COMPLETE,
            SubeventCode.READ_REMOTE_FEATURES_COMPLETE)
        # Cert Connects
        self.cert_hal.send_hci_command(
            LeSetRandomAddressBuilder('0C:05:04:03:02:01'))
        phy_scan_params = DirectHciTest._create_phy_scan_params()
        self.cert_hal.send_hci_command(
            LeExtendedCreateConnectionBuilder(
                InitiatorFilterPolicy.USE_PEER_ADDRESS,
                OwnAddressType.RANDOM_DEVICE_ADDRESS,
                AddressType.RANDOM_DEVICE_ADDRESS, '0D:05:04:03:02:01', 1,
                [phy_scan_params]))

        advertisement = self.dut_hci.create_advertisement(
            0, '0D:05:04:03:02:01')
        advertisement.set_data(b'Im_The_DUT')
        advertisement.set_scan_response(b'Im_The_D')
        advertisement.start()

        (dut_handle, cert_handle) = self._verify_le_connection_complete()

        self.dut_hci.send_command(LeReadRemoteFeaturesBuilder(dut_handle))
        assertThat(self.dut_hci.get_le_event_stream()).emits(
            lambda packet: packet.payload[0] == int(
                EventCode.LE_META_EVENT) and packet.payload[2] == int(
                    SubeventCode.READ_REMOTE_FEATURES_COMPLETE))

        # Send ACL Data
        self.enqueue_acl_data(
            dut_handle, PacketBoundaryFlag.FIRST_NON_AUTOMATICALLY_FLUSHABLE,
            BroadcastFlag.POINT_TO_POINT, bytes(b'Just SomeAclData'))
        self.cert_hal.send_acl_first(cert_handle,
                                     bytes(b'Just SomeMoreAclData'))

        assertThat(
            self.cert_hal.get_acl_stream()).emits(lambda packet: logging.debug(
                packet.payload) or b'SomeAclData' in packet.payload)
        assertThat(self.dut_hci.get_raw_acl_stream()).emits(
            lambda packet: logging.debug(
                packet.payload) or b'SomeMoreAclData' in packet.payload)

    def test_le_connect_list_connection_cert_advertises(self):
        self.dut_hci.register_for_le_events(
            SubeventCode.CONNECTION_COMPLETE,
            SubeventCode.ENHANCED_CONNECTION_COMPLETE)
        # DUT Connects
        self.dut_hci.send_command(
            LeSetRandomAddressBuilder('0D:05:04:03:02:01'))
        self.dut_hci.send_command(
            LeAddDeviceToConnectListBuilder(ConnectListAddressType.RANDOM,
                                            '0C:05:04:03:02:01'))
        phy_scan_params = DirectHciTest._create_phy_scan_params()
        self.dut_hci.send_command(
            LeExtendedCreateConnectionBuilder(
                InitiatorFilterPolicy.USE_CONNECT_LIST,
                OwnAddressType.RANDOM_DEVICE_ADDRESS,
                AddressType.RANDOM_DEVICE_ADDRESS, 'BA:D5:A4:A3:A2:A1', 1,
                [phy_scan_params]))

        advertisement = self.cert_hal.create_advertisement(
            1,
            '0C:05:04:03:02:01',
            min_interval=512,
            max_interval=768,
            peer_address='A6:A5:A4:A3:A2:A1',
            tx_power=0x7f,
            sid=0)
        advertisement.set_data(b'Im_A_Cert')
        advertisement.start()

        # LeConnectionComplete
        self._verify_le_connection_complete()

    def test_connection_dut_connects(self):
        self.dut_hci.send_command(WritePageTimeoutBuilder(0x4000))

        self.cert_hal.enable_inquiry_and_page_scan()
        address = self.cert_hal.read_own_address()

        self.dut_hci.initiate_connection(address)
        cert_acl = self.cert_hal.accept_connection()
        dut_acl = self.dut_hci.complete_connection()

        # Send ACL Data
        dut_acl.send_first(b'Just SomeAclData')
        cert_acl.send_first(b'Just SomeMoreAclData')

        assertThat(self.cert_hal.get_acl_stream()).emits(
            lambda packet: b'SomeAclData' in packet.payload)
        assertThat(self.dut_hci.get_raw_acl_stream()).emits(
            lambda packet: b'SomeMoreAclData' in packet.payload)

    def test_connection_cert_connects(self):
        self.cert_hal.send_hci_command(WritePageTimeoutBuilder(0x4000))

        self.dut_hci.enable_inquiry_and_page_scan()
        address = self.dut_hci.read_own_address()

        self.cert_hal.initiate_connection(address)
        dut_acl = self.dut_hci.accept_connection()
        cert_acl = self.cert_hal.complete_connection()

        # Send ACL Data
        dut_acl.send_first(b'This is just SomeAclData')
        cert_acl.send_first(b'This is just SomeMoreAclData')

        assertThat(self.cert_hal.get_acl_stream()).emits(
            lambda packet: b'SomeAclData' in packet.payload)
        assertThat(self.dut_hci.get_raw_acl_stream()).emits(
            lambda packet: b'SomeMoreAclData' in packet.payload)
Beispiel #5
0
class DirectHciTest(GdBaseTestClass):
    def setup_class(self):
        super().setup_class(dut_module='HCI', cert_module='HAL')

    def setup_test(self):
        super().setup_test()
        self.dut_hci = PyHci(self.dut, acl_streaming=True)
        self.cert_hal = PyHal(self.cert)
        self.cert_hal.send_hci_command(hci_packets.ResetBuilder().Serialize())

    def teardown_test(self):
        self.dut_hci.close()
        self.cert_hal.close()
        super().teardown_test()

    def send_hal_hci_command(self, command):
        self.cert_hal.send_hci_command(bytes(command.Serialize()))

    def enqueue_acl_data(self, handle, pb_flag, b_flag, acl):
        acl_msg = hci_facade.AclMsg(handle=int(handle),
                                    packet_boundary_flag=int(pb_flag),
                                    broadcast_flag=int(b_flag),
                                    data=acl)
        self.dut.hci.SendAclData(acl_msg)

    def send_hal_acl_data(self, handle, pb_flag, b_flag, acl):
        lower = handle & 0xff
        upper = (handle >> 8) & 0xf
        upper = upper | int(pb_flag) & 0x3
        upper = upper | ((int(b_flag) & 0x3) << 2)
        lower_length = len(acl) & 0xff
        upper_length = (len(acl) & 0xff00) >> 8
        concatenated = bytes([lower, upper, lower_length, upper_length] +
                             list(acl))
        self.cert_hal.send_acl(concatenated)

    def test_local_hci_cmd_and_event(self):
        # Loopback mode responds with ACL and SCO connection complete
        self.dut_hci.register_for_events(
            hci_packets.EventCode.LOOPBACK_COMMAND)

        self.dut_hci.send_command_with_complete(
            hci_packets.WriteLoopbackModeBuilder(
                hci_packets.LoopbackMode.ENABLE_LOCAL))

        cmd2loop = hci_packets.ReadLocalNameBuilder()
        self.dut_hci.send_command_with_complete(cmd2loop)

        looped_bytes = bytes(cmd2loop.Serialize())
        assertThat(self.dut_hci.get_event_stream()).emits(
            lambda packet: looped_bytes in packet.event)

    def test_inquiry_from_dut(self):
        self.dut_hci.register_for_events(hci_packets.EventCode.INQUIRY_RESULT)

        self.send_hal_hci_command(
            hci_packets.WriteScanEnableBuilder(
                hci_packets.ScanEnable.INQUIRY_AND_PAGE_SCAN))
        lap = hci_packets.Lap()
        lap.lap = 0x33
        self.dut_hci.send_command_with_status(
            hci_packets.InquiryBuilder(lap, 0x30, 0xff))
        assertThat(self.dut_hci.get_event_stream()).emits(
            HciMatchers.EventWithCode(hci_packets.EventCode.INQUIRY_RESULT))

    def test_le_ad_scan_cert_advertises(self):
        self.dut_hci.register_for_le_events(
            hci_packets.SubeventCode.EXTENDED_ADVERTISING_REPORT)
        self.dut_hci.register_for_le_events(
            hci_packets.SubeventCode.ADVERTISING_REPORT)

        # DUT Scans
        self.dut_hci.send_command_with_complete(
            hci_packets.LeSetRandomAddressBuilder('0D:05:04:03:02:01'))
        phy_scan_params = hci_packets.PhyScanParameters()
        phy_scan_params.le_scan_interval = 6553
        phy_scan_params.le_scan_window = 6553
        phy_scan_params.le_scan_type = hci_packets.LeScanType.ACTIVE

        self.dut_hci.send_command_with_complete(
            hci_packets.LeSetExtendedScanParametersBuilder(
                hci_packets.AddressType.RANDOM_DEVICE_ADDRESS,
                hci_packets.LeSetScanningFilterPolicy.ACCEPT_ALL, 1,
                [phy_scan_params]))
        self.dut_hci.send_command_with_complete(
            hci_packets.LeSetExtendedScanEnableBuilder(
                hci_packets.Enable.ENABLED,
                hci_packets.FilterDuplicates.DISABLED, 0, 0))

        # CERT Advertises
        advertising_handle = 0
        self.send_hal_hci_command(
            hci_packets.LeSetExtendedAdvertisingLegacyParametersBuilder(
                advertising_handle,
                hci_packets.LegacyAdvertisingProperties.ADV_IND,
                512,
                768,
                7,
                hci_packets.OwnAddressType.RANDOM_DEVICE_ADDRESS,
                hci_packets.PeerAddressType.PUBLIC_DEVICE_OR_IDENTITY_ADDRESS,
                'A6:A5:A4:A3:A2:A1',
                hci_packets.AdvertisingFilterPolicy.ALL_DEVICES,
                0xF7,
                1,  # SID
                hci_packets.Enable.DISABLED  # Scan request notification
            ))

        self.send_hal_hci_command(
            hci_packets.LeSetExtendedAdvertisingRandomAddressBuilder(
                advertising_handle, '0C:05:04:03:02:01'))
        gap_name = hci_packets.GapData()
        gap_name.data_type = hci_packets.GapDataType.COMPLETE_LOCAL_NAME
        gap_name.data = list(bytes(b'Im_A_Cert!'))  # TODO: Fix and remove !

        self.send_hal_hci_command(
            hci_packets.LeSetExtendedAdvertisingDataBuilder(
                advertising_handle,
                hci_packets.Operation.COMPLETE_ADVERTISEMENT,
                hci_packets.FragmentPreference.CONTROLLER_SHOULD_NOT,
                [gap_name]))

        gap_short_name = hci_packets.GapData()
        gap_short_name.data_type = hci_packets.GapDataType.SHORTENED_LOCAL_NAME
        gap_short_name.data = list(bytes(b'Im_A_C'))

        self.send_hal_hci_command(
            hci_packets.LeSetExtendedAdvertisingScanResponseBuilder(
                advertising_handle,
                hci_packets.Operation.COMPLETE_ADVERTISEMENT,
                hci_packets.FragmentPreference.CONTROLLER_SHOULD_NOT,
                [gap_short_name]))

        enabled_set = hci_packets.EnabledSet()
        enabled_set.advertising_handle = 0
        enabled_set.duration = 0
        enabled_set.max_extended_advertising_events = 0
        self.send_hal_hci_command(
            hci_packets.LeSetExtendedAdvertisingEnableBuilder(
                hci_packets.Enable.ENABLED, [enabled_set]))

        assertThat(self.dut_hci.get_le_event_stream()).emits(
            lambda packet: b'Im_A_Cert' in packet.event)

        self.send_hal_hci_command(
            hci_packets.LeSetExtendedAdvertisingEnableBuilder(
                hci_packets.Enable.DISABLED, [enabled_set]))
        self.dut_hci.send_command_with_complete(
            hci_packets.LeSetExtendedScanEnableBuilder(
                hci_packets.Enable.DISABLED,
                hci_packets.FilterDuplicates.DISABLED, 0, 0))

    def _verify_le_connection_complete(self):
        cert_conn_complete_capture = HalCaptures.LeConnectionCompleteCapture()
        assertThat(self.cert_hal.get_hci_event_stream()).emits(
            cert_conn_complete_capture)
        cert_handle = cert_conn_complete_capture.get().GetConnectionHandle()

        dut_conn_complete_capture = HciCaptures.LeConnectionCompleteCapture()
        assertThat(self.dut_hci.get_le_event_stream()).emits(
            dut_conn_complete_capture)
        dut_handle = dut_conn_complete_capture.get().GetConnectionHandle()

        return (dut_handle, cert_handle)

    @staticmethod
    def _create_phy_scan_params():
        phy_scan_params = hci_packets.LeCreateConnPhyScanParameters()
        phy_scan_params.scan_interval = 0x60
        phy_scan_params.scan_window = 0x30
        phy_scan_params.conn_interval_min = 0x18
        phy_scan_params.conn_interval_max = 0x28
        phy_scan_params.conn_latency = 0
        phy_scan_params.supervision_timeout = 0x1f4
        phy_scan_params.min_ce_length = 0
        phy_scan_params.max_ce_length = 0
        return phy_scan_params

    def test_le_connection_dut_advertises(self):
        self.dut_hci.register_for_le_events(
            hci_packets.SubeventCode.CONNECTION_COMPLETE)
        # Cert Connects
        self.send_hal_hci_command(
            hci_packets.LeSetRandomAddressBuilder('0C:05:04:03:02:01'))
        phy_scan_params = DirectHciTest._create_phy_scan_params()
        self.send_hal_hci_command(
            hci_packets.LeExtendedCreateConnectionBuilder(
                hci_packets.InitiatorFilterPolicy.USE_PEER_ADDRESS,
                hci_packets.OwnAddressType.RANDOM_DEVICE_ADDRESS,
                hci_packets.AddressType.RANDOM_DEVICE_ADDRESS,
                '0D:05:04:03:02:01', 1, [phy_scan_params]))

        # DUT Advertises
        advertising_handle = 0
        self.dut_hci.send_command_with_complete(
            hci_packets.LeSetExtendedAdvertisingLegacyParametersBuilder(
                advertising_handle,
                hci_packets.LegacyAdvertisingProperties.ADV_IND,
                400,
                450,
                7,
                hci_packets.OwnAddressType.RANDOM_DEVICE_ADDRESS,
                hci_packets.PeerAddressType.PUBLIC_DEVICE_OR_IDENTITY_ADDRESS,
                '00:00:00:00:00:00',
                hci_packets.AdvertisingFilterPolicy.ALL_DEVICES,
                0xF8,
                1,  #SID
                hci_packets.Enable.DISABLED  # Scan request notification
            ))

        self.dut_hci.send_command_with_complete(
            hci_packets.LeSetExtendedAdvertisingRandomAddressBuilder(
                advertising_handle, '0D:05:04:03:02:01'))

        gap_name = hci_packets.GapData()
        gap_name.data_type = hci_packets.GapDataType.COMPLETE_LOCAL_NAME
        gap_name.data = list(bytes(b'Im_The_DUT!'))  # TODO: Fix and remove !

        self.dut_hci.send_command_with_complete(
            hci_packets.LeSetExtendedAdvertisingDataBuilder(
                advertising_handle,
                hci_packets.Operation.COMPLETE_ADVERTISEMENT,
                hci_packets.FragmentPreference.CONTROLLER_SHOULD_NOT,
                [gap_name]))

        gap_short_name = hci_packets.GapData()
        gap_short_name.data_type = hci_packets.GapDataType.SHORTENED_LOCAL_NAME
        gap_short_name.data = list(bytes(b'Im_The_D'))

        self.dut_hci.send_command_with_complete(
            hci_packets.LeSetExtendedAdvertisingScanResponseBuilder(
                advertising_handle,
                hci_packets.Operation.COMPLETE_ADVERTISEMENT,
                hci_packets.FragmentPreference.CONTROLLER_SHOULD_NOT,
                [gap_short_name]))

        enabled_set = hci_packets.EnabledSet()
        enabled_set.advertising_handle = advertising_handle
        enabled_set.duration = 0
        enabled_set.max_extended_advertising_events = 0
        self.dut_hci.send_command_with_complete(
            hci_packets.LeSetExtendedAdvertisingEnableBuilder(
                hci_packets.Enable.ENABLED, [enabled_set]))

        # Check for success of Enable
        assertThat(self.dut_hci.get_event_stream()).emits(
            HciMatchers.CommandComplete(
                hci_packets.OpCode.LE_SET_EXTENDED_ADVERTISING_ENABLE))

        (dut_handle, cert_handle) = self._verify_le_connection_complete()

        # Send ACL Data
        self.enqueue_acl_data(
            dut_handle,
            hci_packets.PacketBoundaryFlag.FIRST_NON_AUTOMATICALLY_FLUSHABLE,
            hci_packets.BroadcastFlag.POINT_TO_POINT,
            bytes(b'Just SomeAclData'))
        self.send_hal_acl_data(
            cert_handle,
            hci_packets.PacketBoundaryFlag.FIRST_NON_AUTOMATICALLY_FLUSHABLE,
            hci_packets.BroadcastFlag.POINT_TO_POINT,
            bytes(b'Just SomeMoreAclData'))

        assertThat(
            self.cert_hal.get_acl_stream()).emits(lambda packet: logging.debug(
                packet.payload) or b'SomeAclData' in packet.payload)
        assertThat(self.dut_hci.get_raw_acl_stream()).emits(
            lambda packet: logging.debug(
                packet.data) or b'SomeMoreAclData' in packet.data)

    def test_le_white_list_connection_cert_advertises(self):
        self.dut_hci.register_for_le_events(
            hci_packets.SubeventCode.CONNECTION_COMPLETE)
        # DUT Connects
        self.dut_hci.send_command_with_complete(
            hci_packets.LeSetRandomAddressBuilder('0D:05:04:03:02:01'))
        self.dut_hci.send_command_with_complete(
            hci_packets.LeAddDeviceToWhiteListBuilder(
                hci_packets.WhiteListAddressType.RANDOM, '0C:05:04:03:02:01'))
        phy_scan_params = DirectHciTest._create_phy_scan_params()
        self.dut_hci.send_command_with_status(
            hci_packets.LeExtendedCreateConnectionBuilder(
                hci_packets.InitiatorFilterPolicy.USE_WHITE_LIST,
                hci_packets.OwnAddressType.RANDOM_DEVICE_ADDRESS,
                hci_packets.AddressType.RANDOM_DEVICE_ADDRESS,
                'BA:D5:A4:A3:A2:A1', 1, [phy_scan_params]))

        # CERT Advertises
        advertising_handle = 1
        self.send_hal_hci_command(
            hci_packets.LeSetExtendedAdvertisingLegacyParametersBuilder(
                advertising_handle,
                hci_packets.LegacyAdvertisingProperties.ADV_IND,
                512,
                768,
                7,
                hci_packets.OwnAddressType.RANDOM_DEVICE_ADDRESS,
                hci_packets.PeerAddressType.PUBLIC_DEVICE_OR_IDENTITY_ADDRESS,
                'A6:A5:A4:A3:A2:A1',
                hci_packets.AdvertisingFilterPolicy.ALL_DEVICES,
                0x7F,
                0,  # SID
                hci_packets.Enable.DISABLED  # Scan request notification
            ))

        self.send_hal_hci_command(
            hci_packets.LeSetExtendedAdvertisingRandomAddressBuilder(
                advertising_handle, '0C:05:04:03:02:01'))

        gap_name = hci_packets.GapData()
        gap_name.data_type = hci_packets.GapDataType.COMPLETE_LOCAL_NAME
        gap_name.data = list(bytes(b'Im_A_Cert!'))  # TODO: Fix and remove !

        self.send_hal_hci_command(
            hci_packets.LeSetExtendedAdvertisingDataBuilder(
                advertising_handle,
                hci_packets.Operation.COMPLETE_ADVERTISEMENT,
                hci_packets.FragmentPreference.CONTROLLER_SHOULD_NOT,
                [gap_name]))
        enabled_set = hci_packets.EnabledSet()
        enabled_set.advertising_handle = 1
        enabled_set.duration = 0
        enabled_set.max_extended_advertising_events = 0
        self.send_hal_hci_command(
            hci_packets.LeSetExtendedAdvertisingEnableBuilder(
                hci_packets.Enable.ENABLED, [enabled_set]))

        # LeConnectionComplete
        self._verify_le_connection_complete()

    def _verify_connection_complete(self):
        cert_connection_complete_capture = HalCaptures.ConnectionCompleteCapture(
        )
        assertThat(self.cert_hal.get_hci_event_stream()).emits(
            cert_connection_complete_capture)
        cert_handle = cert_connection_complete_capture.get(
        ).GetConnectionHandle()

        dut_connection_complete_capture = HciCaptures.ConnectionCompleteCapture(
        )
        assertThat(self.dut_hci.get_event_stream()).emits(
            dut_connection_complete_capture)
        dut_handle = dut_connection_complete_capture.get().GetConnectionHandle(
        )

        return (dut_handle, cert_handle)

    def test_connection_dut_connects(self):
        self.dut_hci.send_command_with_complete(
            hci_packets.WritePageTimeoutBuilder(0x4000))

        # CERT Enables scans and gets its address
        self.send_hal_hci_command(hci_packets.ReadBdAddrBuilder())

        cert_read_bd_addr_capture = HalCaptures.ReadBdAddrCompleteCapture()
        assertThat(self.cert_hal.get_hci_event_stream()).emits(
            cert_read_bd_addr_capture)
        address = cert_read_bd_addr_capture.get().GetBdAddr()

        self.send_hal_hci_command(
            hci_packets.WriteScanEnableBuilder(
                hci_packets.ScanEnable.INQUIRY_AND_PAGE_SCAN))

        # DUT Connects
        self.dut_hci.send_command_with_status(
            hci_packets.CreateConnectionBuilder(
                address,
                0xcc18,  # Packet Type
                hci_packets.PageScanRepetitionMode.R0,
                0,
                hci_packets.ClockOffsetValid.INVALID,
                hci_packets.CreateConnectionRoleSwitch.ALLOW_ROLE_SWITCH))

        # Cert Accepts
        connect_request_capture = HalCaptures.ConnectionRequestCapture()
        assertThat(self.cert_hal.get_hci_event_stream()).emits(
            connect_request_capture, timeout=timedelta(seconds=20))
        connection_request = connect_request_capture.get()
        self.send_hal_hci_command(
            hci_packets.AcceptConnectionRequestBuilder(
                connection_request.GetBdAddr(),
                hci_packets.AcceptConnectionRequestRole.REMAIN_SLAVE))

        (dut_handle, cert_handle) = self._verify_connection_complete()

        # Send ACL Data
        self.enqueue_acl_data(
            dut_handle,
            hci_packets.PacketBoundaryFlag.FIRST_NON_AUTOMATICALLY_FLUSHABLE,
            hci_packets.BroadcastFlag.POINT_TO_POINT,
            bytes(b'Just SomeAclData'))
        self.send_hal_acl_data(
            cert_handle,
            hci_packets.PacketBoundaryFlag.FIRST_NON_AUTOMATICALLY_FLUSHABLE,
            hci_packets.BroadcastFlag.POINT_TO_POINT,
            bytes(b'Just SomeMoreAclData'))

        assertThat(self.cert_hal.get_acl_stream()).emits(
            lambda packet: b'SomeAclData' in packet.payload)
        assertThat(self.dut_hci.get_raw_acl_stream()).emits(
            lambda packet: b'SomeMoreAclData' in packet.data)

    def test_connection_cert_connects(self):
        self.send_hal_hci_command(hci_packets.WritePageTimeoutBuilder(0x4000))

        # DUT Enables scans and gets its address
        self.dut_hci.send_command_with_complete(
            hci_packets.WriteScanEnableBuilder(
                hci_packets.ScanEnable.INQUIRY_AND_PAGE_SCAN))
        self.dut_hci.send_command_with_complete(
            hci_packets.ReadBdAddrBuilder())

        read_bd_addr_capture = HciCaptures.ReadBdAddrCompleteCapture()
        assertThat(self.dut_hci.get_event_stream()).emits(read_bd_addr_capture)
        address = read_bd_addr_capture.get().GetBdAddr()

        # Cert Connects
        self.send_hal_hci_command(
            hci_packets.CreateConnectionBuilder(
                address,
                0xcc18,  # Packet Type
                hci_packets.PageScanRepetitionMode.R0,
                0,
                hci_packets.ClockOffsetValid.INVALID,
                hci_packets.CreateConnectionRoleSwitch.ALLOW_ROLE_SWITCH))

        # DUT Accepts
        connection_request_capture = HciCaptures.ConnectionRequestCapture()
        assertThat(self.dut_hci.get_event_stream()).emits(
            connection_request_capture, timeout=timedelta(seconds=20))
        connection_request = connection_request_capture.get()
        self.dut_hci.send_command_with_status(
            hci_packets.AcceptConnectionRequestBuilder(
                connection_request.GetBdAddr(),
                hci_packets.AcceptConnectionRequestRole.REMAIN_SLAVE))

        (dut_handle, cert_handle) = self._verify_connection_complete()

        # Send ACL Data
        self.enqueue_acl_data(
            dut_handle,
            hci_packets.PacketBoundaryFlag.FIRST_NON_AUTOMATICALLY_FLUSHABLE,
            hci_packets.BroadcastFlag.POINT_TO_POINT,
            bytes(b'This is just SomeAclData'))
        self.send_hal_acl_data(
            cert_handle,
            hci_packets.PacketBoundaryFlag.FIRST_NON_AUTOMATICALLY_FLUSHABLE,
            hci_packets.BroadcastFlag.POINT_TO_POINT,
            bytes(b'This is just SomeMoreAclData'))

        assertThat(self.cert_hal.get_acl_stream()).emits(
            lambda packet: b'SomeAclData' in packet.payload)
        assertThat(self.dut_hci.get_raw_acl_stream()).emits(
            lambda packet: b'SomeMoreAclData' in packet.data)
Beispiel #6
0
class AclManagerTest(GdBaseTestClass):
    def setup_class(self):
        super().setup_class(dut_module='HCI_INTERFACES', cert_module='HCI')

    # todo: move into GdBaseTestClass, based on modules inited
    def setup_test(self):
        super().setup_test()
        self.cert_hci = PyHci(self.cert, acl_streaming=True)
        self.dut_acl_manager = PyAclManager(self.dut)

    def teardown_test(self):
        self.cert_hci.close()
        super().teardown_test()

    def test_dut_connects(self):
        self.cert_hci.enable_inquiry_and_page_scan()
        cert_address = self.cert_hci.read_own_address()

        self.dut_acl_manager.initiate_connection(cert_address)
        cert_acl = self.cert_hci.accept_connection()
        with self.dut_acl_manager.complete_outgoing_connection() as dut_acl:
            cert_acl.send_first(
                b'\x26\x00\x07\x00This is just SomeAclData from the Cert')
            dut_acl.send(
                b'\x29\x00\x07\x00This is just SomeMoreAclData from the DUT')

            assertThat(cert_acl).emits(
                lambda packet: b'SomeMoreAclData' in packet.payload)
            assertThat(dut_acl).emits(
                lambda packet: b'SomeAclData' in packet.payload)

    def test_cert_connects(self):
        dut_address = self.dut.hci_controller.GetMacAddressSimple()
        self.dut.neighbor.EnablePageScan(
            neighbor_facade.EnableMsg(enabled=True))

        self.dut_acl_manager.listen_for_an_incoming_connection()
        self.cert_hci.initiate_connection(dut_address)
        with self.dut_acl_manager.complete_incoming_connection() as dut_acl:
            cert_acl = self.cert_hci.complete_connection()

            dut_acl.send(
                b'\x29\x00\x07\x00This is just SomeMoreAclData from the DUT')

            cert_acl.send_first(
                b'\x26\x00\x07\x00This is just SomeAclData from the Cert')

            assertThat(cert_acl).emits(
                lambda packet: b'SomeMoreAclData' in packet.payload)
            assertThat(dut_acl).emits(
                lambda packet: b'SomeAclData' in packet.payload)

    def test_reject_broadcast(self):
        dut_address = self.dut.hci_controller.GetMacAddressSimple()
        self.dut.neighbor.EnablePageScan(
            neighbor_facade.EnableMsg(enabled=True))

        self.dut_acl_manager.listen_for_an_incoming_connection()
        self.cert_hci.initiate_connection(dut_address)
        with self.dut_acl_manager.complete_incoming_connection() as dut_acl:
            cert_acl = self.cert_hci.complete_connection()

            cert_acl.send(
                hci_packets.PacketBoundaryFlag.FIRST_AUTOMATICALLY_FLUSHABLE,
                hci_packets.BroadcastFlag.ACTIVE_PERIPHERAL_BROADCAST,
                b'\x26\x00\x07\x00This is a Broadcast from the Cert')
            assertThat(dut_acl).emitsNone()

            cert_acl.send(
                hci_packets.PacketBoundaryFlag.FIRST_AUTOMATICALLY_FLUSHABLE,
                hci_packets.BroadcastFlag.POINT_TO_POINT,
                b'\x26\x00\x07\x00This is just SomeAclData from the Cert')
            assertThat(dut_acl).emits(
                lambda packet: b'SomeAclData' in packet.payload)

    def test_cert_connects_disconnects(self):
        dut_address = self.dut.hci_controller.GetMacAddressSimple()
        self.dut.neighbor.EnablePageScan(
            neighbor_facade.EnableMsg(enabled=True))

        self.dut_acl_manager.listen_for_an_incoming_connection()
        self.cert_hci.initiate_connection(dut_address)
        with self.dut_acl_manager.complete_incoming_connection() as dut_acl:
            cert_acl = self.cert_hci.complete_connection()

            dut_acl.send(
                b'\x29\x00\x07\x00This is just SomeMoreAclData from the DUT')

            cert_acl.send_first(
                b'\x26\x00\x07\x00This is just SomeAclData from the Cert')

            assertThat(cert_acl).emits(
                lambda packet: b'SomeMoreAclData' in packet.payload)
            assertThat(dut_acl).emits(
                lambda packet: b'SomeAclData' in packet.payload)

            dut_acl.disconnect(
                hci_packets.DisconnectReason.REMOTE_USER_TERMINATED_CONNECTION)
            dut_acl.wait_for_disconnection_complete()

    def test_recombination_l2cap_packet(self):
        self.cert_hci.enable_inquiry_and_page_scan()
        cert_address = self.cert_hci.read_own_address()

        self.dut_acl_manager.initiate_connection(cert_address)
        cert_acl = self.cert_hci.accept_connection()
        with self.dut_acl_manager.complete_outgoing_connection() as dut_acl:
            cert_acl.send_first(b'\x06\x00\x07\x00Hello')
            cert_acl.send_continuing(b'!')
            cert_acl.send_first(b'\xe8\x03\x07\x00' + b'Hello' * 200)

            assertThat(dut_acl).emits(
                lambda packet: b'Hello!' in packet.payload,
                lambda packet: b'Hello' * 200 in packet.payload).inOrder()
Beispiel #7
0
class LeSecurityTest(GdBaseTestClass):
    """
        Collection of tests that each sample results from
        different (unique) combinations of io capabilities, authentication requirements, and oob data.
    """
    def setup_class(self):
        super().setup_class(dut_module='SECURITY', cert_module='SECURITY')

    def setup_test(self):
        super().setup_test()

        self.dut_security = PyLeSecurity(self.dut)
        self.cert_security = PyLeSecurity(self.cert)
        self.dut_hci = PyHci(self.dut)

        self.dut_address = common.BluetoothAddressWithType(
            address=common.BluetoothAddress(
                address=bytes(b'DD:05:04:03:02:01')),
            type=common.RANDOM_DEVICE_ADDRESS)
        privacy_policy = le_initiator_address_facade.PrivacyPolicy(
            address_policy=le_initiator_address_facade.AddressPolicy.
            USE_STATIC_ADDRESS,
            address_with_type=self.dut_address)
        self.dut.security.SetLeInitiatorAddressPolicy(privacy_policy)
        self.cert_address = common.BluetoothAddressWithType(
            address=common.BluetoothAddress(
                address=bytes(b'C5:11:FF:AA:33:22')),
            type=common.RANDOM_DEVICE_ADDRESS)
        cert_privacy_policy = le_initiator_address_facade.PrivacyPolicy(
            address_policy=le_initiator_address_facade.AddressPolicy.
            USE_STATIC_ADDRESS,
            address_with_type=self.cert_address)
        self.cert.security.SetLeInitiatorAddressPolicy(cert_privacy_policy)

    def teardown_test(self):
        self.dut_hci.close()
        self.dut_security.close()
        self.cert_security.close()
        super().teardown_test()

    def _prepare_cert_for_connection(self):
        # DUT Advertises
        gap_name = hci_packets.GapData()
        gap_name.data_type = hci_packets.GapDataType.COMPLETE_LOCAL_NAME
        gap_name.data = list(bytes(b'Im_The_CERT'))
        gap_data = le_advertising_facade.GapDataMsg(
            data=bytes(gap_name.Serialize()))
        config = le_advertising_facade.AdvertisingConfig(
            advertisement=[gap_data],
            interval_min=512,
            interval_max=768,
            event_type=le_advertising_facade.AdvertisingEventType.ADV_IND,
            address_type=common.RANDOM_DEVICE_ADDRESS,
            channel_map=7,
            filter_policy=le_advertising_facade.AdvertisingFilterPolicy.
            ALL_DEVICES)
        request = le_advertising_facade.CreateAdvertiserRequest(config=config)
        create_response = self.cert.hci_le_advertising_manager.CreateAdvertiser(
            request)

    def _prepare_dut_for_connection(self):
        # DUT Advertises
        gap_name = hci_packets.GapData()
        gap_name.data_type = hci_packets.GapDataType.COMPLETE_LOCAL_NAME
        gap_name.data = list(bytes(b'Im_The_DUT'))
        gap_data = le_advertising_facade.GapDataMsg(
            data=bytes(gap_name.Serialize()))
        config = le_advertising_facade.AdvertisingConfig(
            advertisement=[gap_data],
            interval_min=512,
            interval_max=768,
            event_type=le_advertising_facade.AdvertisingEventType.ADV_IND,
            address_type=common.RANDOM_DEVICE_ADDRESS,
            channel_map=7,
            filter_policy=le_advertising_facade.AdvertisingFilterPolicy.
            ALL_DEVICES)
        request = le_advertising_facade.CreateAdvertiserRequest(config=config)
        create_response = self.dut.hci_le_advertising_manager.CreateAdvertiser(
            request)

    @metadata(pts_test_id="SM/MAS/PROT/BV-01-C",
              pts_test_name="SMP Time Out – IUT Initiator")
    def test_le_smp_timeout_iut_initiator(self):
        """
            Verify that the IUT handles the lack of pairing response after 30 seconds when acting as initiator.
        """
        self._prepare_cert_for_connection()
        self.dut.security.CreateBondLe(self.cert_address)
        assertThat(self.dut_security.get_bond_stream()).emits(
            SecurityMatchers.BondMsg(BondMsgType.DEVICE_BOND_FAILED),
            timeout=timedelta(seconds=35))

    @metadata(pts_test_id="SM/SLA/PROT/BV-02-C",
              pts_test_name="SMP Time Out – IUT Responder")
    def test_le_smp_timeout_iut_responder(self):
        """
            Verify that the IUT handles the lack of pairing response after 30 seconds when acting as initiator.
        """
        self.cert.security.SetLeIoCapability(KEYBOARD_ONLY)
        self.dut.security.SetLeIoCapability(DISPLAY_ONLY)

        self._prepare_dut_for_connection()

        # 1. Lower Tester transmits Pairing Request.
        self.cert.security.CreateBondLe(self.dut_address)

        assertThat(self.dut_security.get_ui_stream()).emits(
            SecurityMatchers.UiMsg(UiMsgType.DISPLAY_PAIRING_PROMPT),
            timeout=timedelta(seconds=35))

        # 2. IUT responds with Pairing Response.
        self.dut.security.SendUiCallback(
            UiCallbackMsg(message_type=UiCallbackType.PAIRING_PROMPT,
                          boolean=True,
                          unique_id=1,
                          address=self.cert_address))

        # 3. In phase 2, Lower Tester does not issue the expected Pairing Confirm.

        # Here the cert receives DISPLAY_PASSKEY_ENTRY. By not replying to it we make sure Pairing Confirm is never sent
        assertThat(self.cert_security.get_ui_stream()).emits(
            SecurityMatchers.UiMsg(UiMsgType.DISPLAY_PASSKEY_ENTRY),
            timeout=timedelta(seconds=5))

        # 4. IUT times out 30 seconds after issued Pairing Response and reports the failure to the Upper Tester.
        assertThat(self.dut_security.get_bond_stream()).emits(
            SecurityMatchers.BondMsg(BondMsgType.DEVICE_BOND_FAILED),
            timeout=timedelta(seconds=35))

        # 5. After additionally (at least) 10 seconds the Lower Tester issues the expected Pairing Confirm.
        # 6. The IUT closes the connection before receiving the delayed response or does not respond to it when it is received.
        #TODO:
        #assertThat(self.dut_hci.get_event_stream()).emits(HciMatchers.Disconnect())

    @metadata(pts_test_id="SM/MAS/JW/BV-01-C",
              pts_test_name="Just Works IUT Initiator – Success")
    def test_just_works_iut_initiator(self):
        """
            Verify that the IUT performs the Just Works pairing procedure correctly as master, initiator when both sides do not require MITM protection.
        """
        self._prepare_cert_for_connection()

        self.dut.security.SetLeIoCapability(KEYBOARD_ONLY)
        self.dut.security.SetLeOobDataPresent(OOB_NOT_PRESENT)
        self.dut_security.SetLeAuthRequirements()

        self.cert.security.SetLeIoCapability(DISPLAY_ONLY)
        self.cert.security.SetLeOobDataPresent(OOB_NOT_PRESENT)
        self.cert_security.SetLeAuthRequirements()

        # 1. IUT transmits Pairing Request command with:
        # a. IO capability set to any IO capability
        # b. OOB data flag set to 0x00 (OOB Authentication data not present)
        # c. AuthReq Bonding Flags set to ‘00’ and the MITM flag set to ‘0’ and all the reserved bits are set to ‘0’
        self.dut.security.CreateBondLe(self.cert_address)

        assertThat(self.cert_security.get_ui_stream()).emits(
            SecurityMatchers.UiMsg(UiMsgType.DISPLAY_PAIRING_PROMPT))

        # 2. Lower Tester responds with a Pairing Response command, with:
        # a. IO capability set to “KeyboardDisplay”
        # b. OOB data flag set to 0x00 (OOB Authentication data not present)
        # c. AuthReq Bonding Flags set to ‘00’, and the MITM flag set to ‘0’ and all the reserved bits are set to ‘0’
        self.cert.security.SendUiCallback(
            UiCallbackMsg(message_type=UiCallbackType.PAIRING_PROMPT,
                          boolean=True,
                          unique_id=1,
                          address=self.dut_address))

        # 3. IUT and Lower Tester perform phase 2 of the just works pairing procedure and establish an encrypted link with the key generated in phase 2.
        assertThat(self.dut_security.get_bond_stream()).emits(
            SecurityMatchers.BondMsg(BondMsgType.DEVICE_BONDED))

    @metadata(pts_test_id="SM/SLA/JW/BV-02-C",
              pts_test_name="Just Works IUT Responder – Success")
    def test_just_works_iut_responder(self):
        """
            Verify that the IUT is able to perform the Just Works pairing procedure correctly when acting as slave, responder.
        """
        self._prepare_dut_for_connection()

        self.dut.security.SetLeIoCapability(KEYBOARD_ONLY)
        self.dut.security.SetLeOobDataPresent(OOB_NOT_PRESENT)
        self.dut_security.SetLeAuthRequirements()

        self.cert.security.SetLeIoCapability(NO_INPUT_NO_OUTPUT)
        self.cert.security.SetLeOobDataPresent(OOB_NOT_PRESENT)
        self.cert_security.SetLeAuthRequirements()

        # 1. Lower Tester transmits Pairing Request command with:
        # a. IO capability set to “NoInputNoOutput”
        # b. OOB data flag set to 0x00 (OOB Authentication data not present)
        # c. MITM flag set to ‘0’ and all reserved bits are set to ‘0’
        self.cert.security.CreateBondLe(self.dut_address)

        assertThat(self.dut_security.get_ui_stream()).emits(
            SecurityMatchers.UiMsg(UiMsgType.DISPLAY_PAIRING_PROMPT))

        # 2. IUT responds with a Pairing Response command, with:
        # a. IO capability set to any IO capability
        # b. OOB data flag set to 0x00 (OOB Authentication data not present)
        self.dut.security.SendUiCallback(
            UiCallbackMsg(message_type=UiCallbackType.PAIRING_PROMPT,
                          boolean=True,
                          unique_id=1,
                          address=self.cert_address))

        # IUT and Lower Tester perform phase 2 of the just works pairing and establish an encrypted link with the generated STK.
        assertThat(self.dut_security.get_bond_stream()).emits(
            SecurityMatchers.BondMsg(BondMsgType.DEVICE_BONDED))

    @metadata(pts_test_id="SM/SLA/JW/BI-03-C",
              pts_test_name=
              "Just Works IUT Responder – Handle AuthReq flag RFU correctly")
    def test_just_works_iut_responder_auth_req_rfu(self):
        """
            Verify that the IUT is able to perform the Just Works pairing procedure when receiving additional bits set in the AuthReq flag. Reserved For Future Use bits are correctly handled when acting as slave, responder.
        """
        self._prepare_dut_for_connection()

        self.dut.security.SetLeIoCapability(KEYBOARD_DISPLAY)
        self.dut.security.SetLeOobDataPresent(OOB_NOT_PRESENT)
        self.dut_security.SetLeAuthRequirements()

        self.cert.security.SetLeIoCapability(NO_INPUT_NO_OUTPUT)
        self.cert.security.SetLeOobDataPresent(OOB_NOT_PRESENT)
        self.cert_security.SetLeAuthRequirements(mitm=1,
                                                 secure_connections=1,
                                                 reserved_bits=2)

        # 1. Lower Tester transmits Pairing Request command with:
        # a. IO Capability set to ”NoInputNoOutput”
        # b. OOB data flag set to 0x00 (OOB Authentication data not present)
        # c. MITM set to ‘0’ and all reserved bits are set to ‘1’
        self.cert.security.CreateBondLe(self.dut_address)

        assertThat(self.dut_security.get_ui_stream()).emits(
            SecurityMatchers.UiMsg(UiMsgType.DISPLAY_PAIRING_PROMPT))

        # 2. IUT responds with a Pairing Response command, with:
        # a. IO capability set to any IO capability
        # b. OOB data flag set to 0x00 (OOB Authentication data not present)
        # c. All reserved bits are set to ‘0’
        self.dut.security.SendUiCallback(
            UiCallbackMsg(message_type=UiCallbackType.PAIRING_PROMPT,
                          boolean=True,
                          unique_id=1,
                          address=self.cert_address))

        # 3. IUT and Lower Tester perform phase 2 of the just works pairing and establish an encrypted link with the generated STK.
        assertThat(self.dut_security.get_bond_stream()).emits(
            SecurityMatchers.BondMsg(BondMsgType.DEVICE_BONDED))

    @metadata(pts_test_id="SM/MAS/JW/BI-04-C",
              pts_test_name=
              "Just Works IUT Initiator – Handle AuthReq flag RFU correctly")
    def test_just_works_iut_initiator_auth_req_rfu(self):
        """
            Verify that the IUT is able to perform the Just Works pairing procedure when receiving additional bits set in the AuthReq flag. Reserved For Future Use bits are correctly handled when acting as master, initiator.
        """
        self._prepare_cert_for_connection()

        self.dut.security.SetLeIoCapability(KEYBOARD_DISPLAY)
        self.dut.security.SetLeOobDataPresent(OOB_NOT_PRESENT)
        self.dut_security.SetLeAuthRequirements()

        self.cert.security.SetLeIoCapability(NO_INPUT_NO_OUTPUT)
        self.cert.security.SetLeOobDataPresent(OOB_NOT_PRESENT)
        self.cert_security.SetLeAuthRequirements(mitm=1,
                                                 secure_connections=1,
                                                 reserved_bits=3)

        # 1. IUT transmits a Pairing Request command with:
        # a. IO Capability set to any IO Capability
        # b. OOB data flag set to 0x00 (OOB Authentication data not present)
        # c. All reserved bits are set to ‘0’. For the purposes of this test the Secure Connections bit and the Keypress bits in the AuthReq bonding flag set by the IUT are ignored by the Lower Tester.
        self.dut.security.CreateBondLe(self.cert_address)

        assertThat(self.cert_security.get_ui_stream()).emits(
            SecurityMatchers.UiMsg(UiMsgType.DISPLAY_PAIRING_PROMPT))

        # 2. Lower Tester responds with a Pairing Response command, with:
        # a. IO Capability set to “NoInputNoOutput”
        # b. OOB data flag set to 0x00 (OOB Authentication data not present)
        # c. AuthReq bonding flag set to the value indicated in the IXIT [7] for ‘Bonding Flags’ and the MITM flag set to ‘0’ and all reserved bits are set to ‘1’. The SC and Keypress bits in the AuthReq bonding flag are set to 0 by the Lower Tester for this test.
        self.cert.security.SendUiCallback(
            UiCallbackMsg(message_type=UiCallbackType.PAIRING_PROMPT,
                          boolean=True,
                          unique_id=1,
                          address=self.dut_address))

        # 3. IUT and Lower Tester perform phase 2 of the just works pairing and establish an encrypted link with the generated STK.
        assertThat(self.dut_security.get_bond_stream()).emits(
            SecurityMatchers.BondMsg(BondMsgType.DEVICE_BONDED))

    @metadata(
        pts_test_id="SM/MAS/SCJW/BV-01-C",
        pts_test_name="Just Works, IUT Initiator, Secure Connections – Success"
    )
    def test_just_works_iut_initiator_secure_connections(self):
        """
            Verify that the IUT supporting LE Secure Connections performs the Just Works or Numeric Comparison pairing procedure correctly as initiator.
        """
        self._prepare_cert_for_connection()

        self.dut.security.SetLeIoCapability(KEYBOARD_ONLY)
        self.dut.security.SetLeOobDataPresent(OOB_NOT_PRESENT)
        self.dut_security.SetLeAuthRequirements(secure_connections=1)

        self.cert.security.SetLeIoCapability(DISPLAY_ONLY)
        self.cert.security.SetLeOobDataPresent(OOB_NOT_PRESENT)
        self.cert_security.SetLeAuthRequirements(secure_connections=1)

        # 1. IUT transmits Pairing Request command with:
        # a. IO capability set to any IO capability
        # b. OOB data flag set to 0x00 (OOB Authentication data not present)
        # c. AuthReq Bonding Flags set to ‘00’, the MITM flag set to either ‘0’ for Just Works or '1' for Numeric Comparison, Secure Connections flag set to '1' and all the reserved bits are set to ‘0’
        self.dut.security.CreateBondLe(self.cert_address)

        assertThat(self.cert_security.get_ui_stream()).emits(
            SecurityMatchers.UiMsg(UiMsgType.DISPLAY_PAIRING_PROMPT))

        # 2. Lower Tester responds with a Pairing Response command, with:
        # a. IO capability set to “KeyboardDisplay”
        # b. OOB data flag set to 0x00 (OOB Authentication data not present)
        # c. AuthReq Bonding Flags set to ‘00’, the MITM flag set to ‘0’, Secure Connections flag set to '1' and all the reserved bits are set to ‘0’
        self.cert.security.SendUiCallback(
            UiCallbackMsg(message_type=UiCallbackType.PAIRING_PROMPT,
                          boolean=True,
                          unique_id=1,
                          address=self.dut_address))

        # 3. IUT and Lower Tester perform phase 2 of the Just Works or Numeric Comparison pairing procedure according to the MITM flag and IO capabilities, and establish an encrypted link with the LTK generated in phase 2.
        assertThat(self.dut_security.get_bond_stream()).emits(
            SecurityMatchers.BondMsg(BondMsgType.DEVICE_BONDED))

    @metadata(
        pts_test_id="SM/SLA/SCJW/BV-02-C",
        pts_test_name="Just Works, IUT Responder, Secure Connections – Success"
    )
    def test_just_works_iut_responder_secure_connections(self):
        """
            Verify that the IUT supporting LE Secure Connections is able to perform the Just Works or Numeric Comparison pairing procedure correctly when acting as responder.
        """
        self._prepare_dut_for_connection()

        self.dut.security.SetLeIoCapability(KEYBOARD_ONLY)
        self.dut.security.SetLeOobDataPresent(OOB_NOT_PRESENT)
        self.dut_security.SetLeAuthRequirements(secure_connections=1)

        self.cert.security.SetLeIoCapability(NO_INPUT_NO_OUTPUT)
        self.cert.security.SetLeOobDataPresent(OOB_NOT_PRESENT)
        self.cert_security.SetLeAuthRequirements(secure_connections=1)

        # 1. Lower Tester transmits Pairing Request command with:
        # a. IO capability set to “NoInputNoOutput”
        # b. OOB data flag set to 0x00 (OOB Authentication data not present)
        # c. AuthReq Bonding Flags set to ‘00’, MITM flag set to ‘0’, Secure Connections flag set to '1' and all reserved bits are set to ‘0’
        self.cert.security.CreateBondLe(self.dut_address)

        assertThat(self.dut_security.get_ui_stream()).emits(
            SecurityMatchers.UiMsg(UiMsgType.DISPLAY_PAIRING_PROMPT))

        # 2. IUT responds with a Pairing Response command, with:
        # a. IO capability set to any IO capability
        # b. AuthReq Bonding Flags set to ‘00’, MITM flag set to either ‘0’ for Just Works or '1' for Numeric Comparison, Secure Connections flag set to '1' and all reserved bits are set to ‘0’
        self.dut.security.SendUiCallback(
            UiCallbackMsg(message_type=UiCallbackType.PAIRING_PROMPT,
                          boolean=True,
                          unique_id=1,
                          address=self.cert_address))

        # 3. UT and Lower Tester perform phase 2 of the Just Works or Numeric Comparison pairing procedure according to the MITM flag and IO capabilities, and establish an encrypted link with the LTK generated in phase 2.
        assertThat(self.dut_security.get_bond_stream()).emits(
            SecurityMatchers.BondMsg(BondMsgType.DEVICE_BONDED))

    @metadata(
        pts_test_id="SM/SLA/SCJW/BV-03-C",
        pts_test_name=
        "Just Works, IUT Responder, Secure Connections – Handle AuthReq Flag RFU Correctly"
    )
    def test_just_works_iut_responder_secure_connections_auth_req_rfu(self):
        """
            Verify that the IUT is able to perform the Just Works pairing procedure when receiving additional bits set in the AuthReq flag. Reserved For Future Use bits are correctly handled when acting as slave, responder.
        """
        self._prepare_dut_for_connection()

        self.dut.security.SetLeIoCapability(KEYBOARD_DISPLAY)
        self.dut.security.SetLeOobDataPresent(OOB_NOT_PRESENT)
        self.dut_security.SetLeAuthRequirements(secure_connections=1)

        self.cert.security.SetLeIoCapability(NO_INPUT_NO_OUTPUT)
        self.cert.security.SetLeOobDataPresent(OOB_NOT_PRESENT)
        self.cert_security.SetLeAuthRequirements(mitm=1,
                                                 secure_connections=1,
                                                 reserved_bits=3)

        # 1. Lower Tester transmits Pairing Request command with:
        # a. IO Capability set to ”NoInputNoOutput”
        # b. OOB data flag set to 0x00 (OOB Authentication data not present)
        # c. MITM set to ‘0’ and all reserved bits are set to a random value.
        self.cert.security.CreateBondLe(self.dut_address)

        assertThat(self.dut_security.get_ui_stream()).emits(
            SecurityMatchers.UiMsg(UiMsgType.DISPLAY_PAIRING_PROMPT))

        # 2. IUT responds with a Pairing Response command, with:
        # a. IO capability set to any IO capability
        # b. OOB data flag set to 0x00 (OOB Authentication data not present)
        # c. All reserved bits are set to ‘0’
        self.dut.security.SendUiCallback(
            UiCallbackMsg(message_type=UiCallbackType.PAIRING_PROMPT,
                          boolean=True,
                          unique_id=1,
                          address=self.cert_address))

        # 3. IUT and Lower Tester perform phase 2 of the Just Works pairing and establish an encrypted link with the generated LTK.
        assertThat(self.dut_security.get_bond_stream()).emits(
            SecurityMatchers.BondMsg(BondMsgType.DEVICE_BONDED))

    @metadata(
        pts_test_id="SM/MAS/SCJW/BV-04-C",
        pts_test_name=
        "Just Works, IUT Initiator, Secure Connections – Handle AuthReq Flag RFU Correctly"
    )
    def test_just_works_iut_initiator_secure_connections_auth_req_rfu(self):
        """
            Verify that the IUT is able to perform the Just Works pairing procedure when receiving additional bits set in the AuthReq flag. Reserved For Future Use bits are correctly handled when acting as master, initiator.
        """
        self._prepare_cert_for_connection()

        self.dut.security.SetLeIoCapability(KEYBOARD_DISPLAY)
        self.dut.security.SetLeOobDataPresent(OOB_NOT_PRESENT)
        self.dut_security.SetLeAuthRequirements(secure_connections=1)

        self.cert.security.SetLeIoCapability(NO_INPUT_NO_OUTPUT)
        self.cert.security.SetLeOobDataPresent(OOB_NOT_PRESENT)
        self.cert_security.SetLeAuthRequirements(mitm=1,
                                                 secure_connections=1,
                                                 reserved_bits=3)

        # 1. IUT transmits a Pairing Request command with:
        # a. IO Capability set to any IO Capability
        # b. OOB data flag set to 0x00 (OOB Authentication data not present)
        # c. All reserved bits are set to ‘0’.
        self.dut.security.CreateBondLe(self.cert_address)

        assertThat(self.cert_security.get_ui_stream()).emits(
            SecurityMatchers.UiMsg(UiMsgType.DISPLAY_PAIRING_PROMPT))

        # 2. Lower Tester responds with a Pairing Response command, with:
        # a. IO Capability set to “NoInputNoOutput”
        # b. OOB data flag set to 0x00 (OOB Authentication data not present)
        # c. AuthReq bonding flag set to the value indicated in the IXIT [7] for ‘Bonding Flags’ and the MITM flag set to ‘0’ and all reserved bits are set to a random value.
        self.cert.security.SendUiCallback(
            UiCallbackMsg(message_type=UiCallbackType.PAIRING_PROMPT,
                          boolean=True,
                          unique_id=1,
                          address=self.dut_address))

        # 3. IUT and Lower Tester perform phase 2 of the Just Works pairing and establish an encrypted link with the generated LTK.
        assertThat(self.dut_security.get_bond_stream()).emits(
            SecurityMatchers.BondMsg(BondMsgType.DEVICE_BONDED))

    @metadata(pts_test_id="SM/MAS/SCPK/BV-01-C",
              pts_test_name=
              "Passkey Entry, IUT Initiator, Secure Connections – Success")
    def test_passkey_entry_iut_initiator_secure_connections(self):
        """
            Verify that the IUT supporting LE Secure Connections performs the Passkey Entry pairing procedure correctly as master, initiator.
        """
        self._prepare_cert_for_connection()

        self.dut.security.SetLeIoCapability(DISPLAY_ONLY)
        self.dut.security.SetLeOobDataPresent(OOB_NOT_PRESENT)
        self.dut_security.SetLeAuthRequirements(secure_connections=1)

        self.cert.security.SetLeIoCapability(KEYBOARD_ONLY)
        self.cert.security.SetLeOobDataPresent(OOB_NOT_PRESENT)
        self.cert_security.SetLeAuthRequirements(mitm=1, secure_connections=1)

        # 1. IUT transmits Pairing Request command with:
        # a. IO capability set to “DisplayOnly” or “KeyboardOnly”
        # b. OOB data flag set to 0x00 (OOB Authentication data not present)
        # c. AuthReq bonding flag set to ‘00’, the MITM flag set to ‘0’ and Secure Connections flag set to '1'. Keypress bit is set to '1' if supported
        self.dut.security.CreateBondLe(self.cert_address)

        assertThat(self.cert_security.get_ui_stream()).emits(
            SecurityMatchers.UiMsg(UiMsgType.DISPLAY_PAIRING_PROMPT))

        # 2. Lower Tester responds with a Pairing Response command, with:
        # a. IO capability set to “KeyboardOnly”
        # b. OOB data flag set to 0x00 (OOB Authentication data not present)
        # c. AuthReq bonding flag set to ‘00’, the MITM flag set to ‘1’, Secure Connections flag set to '1' and all reserved bits are set to ‘0’. Keypress bit is set to '1' if supported by the IUT.
        self.cert.security.SendUiCallback(
            UiCallbackMsg(message_type=UiCallbackType.PAIRING_PROMPT,
                          boolean=True,
                          unique_id=1,
                          address=self.dut_address))

        assertThat(self.cert_security.get_ui_stream()).emits(
            SecurityMatchers.UiMsg(UiMsgType.DISPLAY_PASSKEY_ENTRY))

        # 3. During the phase 2 pairing, the IUT displays the 6-digit passkey while the Lower Tester prompts user to enter the 6-digit passkey. If the IUT’s IO capabilities are “KeyboardOnly” the passkey is not displayed and both IUT and Lower Tester enter the same 6-digit passkey. If Keypress bit is set, pairing keypress notifications are sent by the Lower Tester.
        passkey = self.dut_security.wait_for_ui_event_passkey()

        if passkey == 0:
            print("Passkey did not arrive into test")

        # 4. IUT and Lower Tester use the same 6-digit passkey.
        self.cert.security.SendUiCallback(
            UiCallbackMsg(message_type=UiCallbackType.PASSKEY,
                          numeric_value=passkey,
                          unique_id=1,
                          address=self.dut_address))

        # 5. IUT and Lower Tester perform phase 2 of the Passkey Entry pairing procedure and establish an encrypted link with the LTK generated in phase 2.
        assertThat(self.dut_security.get_bond_stream()).emits(
            SecurityMatchers.BondMsg(BondMsgType.DEVICE_BONDED),
            timeout=timedelta(seconds=10))

    @metadata(pts_test_id="SM/SLA/SCPK/BV-02-C",
              pts_test_name=
              "Passkey Entry, IUT Responder, Secure Connections – Success")
    def test_passkey_entry_iut_responder_secure_connections(self):
        """
            Verify that the IUT supporting LE Secure Connections is able to perform the Passkey Entry pairing procedure correctly when acting as slave, responder.
        """
        self._prepare_dut_for_connection()

        self.dut.security.SetLeIoCapability(DISPLAY_ONLY)
        self.dut.security.SetLeOobDataPresent(OOB_NOT_PRESENT)
        self.dut_security.SetLeAuthRequirements(secure_connections=1)

        self.cert.security.SetLeIoCapability(KEYBOARD_DISPLAY)
        self.cert.security.SetLeOobDataPresent(OOB_NOT_PRESENT)
        self.cert_security.SetLeAuthRequirements(mitm=1, secure_connections=1)

        # 1. Lower Tester transmits Pairing Request command with:
        # a. IO capability set to “KeyboardDisplay”
        # b. OOB data flag set to 0x00 (OOB Authentication data not present)
        # c. AuthReq bonding flag set to the value indicated in the IXIT [7] for ‘Bonding Flags’, and the MITM flag set to ‘1’ Secure Connections flag set to '1' and all reserved bits are set to ‘0’
        self.cert.security.CreateBondLe(self.dut_address)

        assertThat(self.dut_security.get_ui_stream()).emits(
            SecurityMatchers.UiMsg(UiMsgType.DISPLAY_PAIRING_PROMPT))

        # 2. IUT responds with a Pairing Response command, with:
        # a. IO capability set to “KeyboardOnly” or “KeyboardDisplay” or “DisplayYesNo” or “DisplayOnly”
        # b. Secure Connections flag set to '1'. Keypress bit is set to '1' if supported by IUT
        self.dut.security.SendUiCallback(
            UiCallbackMsg(message_type=UiCallbackType.PAIRING_PROMPT,
                          boolean=True,
                          unique_id=1,
                          address=self.cert_address))

        # 3. During the phase 2 passkey pairing process, Lower Tester displays the 6-digit passkey while the IUT prompts user to enter the 6-digit passkey. If the IO capabilities of the IUT are “DisplayYesNo” or “DisplayOnly” the IUT displays the 6-digit passkey while the Lower Tester enters the 6-digit passkey. If Keypress bit is set, pairing keypress notifications are send by the IUT
        passkey = self.dut_security.wait_for_ui_event_passkey()

        if passkey == 0:
            print("Passkey did not arrive into test")

        assertThat(self.cert_security.get_ui_stream()).emits(
            SecurityMatchers.UiMsg(UiMsgType.DISPLAY_PASSKEY_ENTRY))

        # 4. IUT and Lower Tester use the same pre-defined 6-digit passkey.
        self.cert.security.SendUiCallback(
            UiCallbackMsg(message_type=UiCallbackType.PASSKEY,
                          numeric_value=passkey,
                          unique_id=1,
                          address=self.dut_address))

        # 5. IUT and Lower Tester perform phase 2 of the LE pairing and establish an encrypted link with the LTK generated in phase 2.
        assertThat(self.dut_security.get_bond_stream()).emits(
            SecurityMatchers.BondMsg(BondMsgType.DEVICE_BONDED),
            timeout=timedelta(seconds=10))

    @metadata(
        pts_test_id="SM/SLA/SCPK/BV-03-C",
        pts_test_name=
        "Passkey Entry, IUT Responder, Secure Connections – Handle AuthReq Flag RFU Correctly"
    )
    def test_passkey_entry_iut_responder_secure_connections_auth_req_rfu(self):
        """
            Verify that the IUT supporting LE Secure Connections is able to perform the Passkey Entry pairing procedure when receiving additional bits set in the AuthReq flag. Reserved For Future Use bits are correctly handled when acting as slave, responder.
        """
        self._prepare_dut_for_connection()

        self.dut.security.SetLeIoCapability(KEYBOARD_ONLY)
        self.dut.security.SetLeOobDataPresent(OOB_NOT_PRESENT)
        self.dut_security.SetLeAuthRequirements(secure_connections=1)

        self.cert.security.SetLeIoCapability(DISPLAY_ONLY)
        self.cert.security.SetLeOobDataPresent(OOB_NOT_PRESENT)
        self.cert_security.SetLeAuthRequirements(mitm=1,
                                                 secure_connections=1,
                                                 reserved_bits=3)

        # 1. Lower Tester transmits Pairing Request command with:
        # a. IO Capability set to ”KeyboardOnly”
        # b. OOB data flag set to 0x00 (OOB Authentication data not present)
        # c. MITM set to ‘1’ and all reserved bits are set to a random value
        self.cert.security.CreateBondLe(self.dut_address)

        assertThat(self.dut_security.get_ui_stream()).emits(
            SecurityMatchers.UiMsg(UiMsgType.DISPLAY_PAIRING_PROMPT))

        # 2. IUT responds with a Pairing Response command, with:
        # a. IO Capability set to “KeyboardOnly” or “DisplayOnly”
        # b. OOB data flag set to 0x00 (OOB Authentication data not present)
        # c. All reserved bits are set to ‘0’
        self.dut.security.SendUiCallback(
            UiCallbackMsg(message_type=UiCallbackType.PAIRING_PROMPT,
                          boolean=True,
                          unique_id=1,
                          address=self.cert_address))

        passkey = self.cert_security.wait_for_ui_event_passkey()

        if passkey == 0:
            print("Passkey did not arrive into test")

        assertThat(self.dut_security.get_ui_stream()).emits(
            SecurityMatchers.UiMsg(UiMsgType.DISPLAY_PASSKEY_ENTRY))

        self.dut.security.SendUiCallback(
            UiCallbackMsg(message_type=UiCallbackType.PASSKEY,
                          numeric_value=passkey,
                          unique_id=1,
                          address=self.cert_address))

        # 3. IUT and Lower Tester perform phase 2 of the Passkey Entry pairing and establish an encrypted link with the generated LTK.
        assertThat(self.dut_security.get_bond_stream()).emits(
            SecurityMatchers.BondMsg(BondMsgType.DEVICE_BONDED),
            timeout=timedelta(seconds=10))

    @metadata(
        pts_test_id="SM/MAS/SCPK/BV-04-C",
        pts_test_name=
        "Passkey Entry, IUT Initiator, Secure Connections – Handle AuthReq Flag RFU Correctly"
    )
    def test_passkey_entry_iut_initiator_secure_connections_auth_req_rfu(self):
        """
            Verify that the IUT supporting LE Secure Connections is able to perform the Passkey Entry pairing procedure when receiving additional bits set in the AuthReq flag. Reserved For Future Use bits are correctly handled when acting as master, initiator.
        """
        self._prepare_cert_for_connection()

        self.dut.security.SetLeIoCapability(KEYBOARD_DISPLAY)
        self.dut.security.SetLeOobDataPresent(OOB_NOT_PRESENT)
        self.dut_security.SetLeAuthRequirements(secure_connections=1)

        self.cert.security.SetLeIoCapability(KEYBOARD_ONLY)
        self.cert.security.SetLeOobDataPresent(OOB_NOT_PRESENT)
        self.cert_security.SetLeAuthRequirements(mitm=1,
                                                 secure_connections=1,
                                                 reserved_bits=3)

        # 1. IUT transmits a Pairing Request command with:
        # a. IO Capability set to “DisplayOnly” or “DisplayYesNo” or “KeyboardOnly” or “KeyboardDisplay”
        # b. OOB data flag set to 0x00 (OOB Authentication data not present)
        # c. All reserved bits are set to ‘0’.
        self.dut.security.CreateBondLe(self.cert_address)

        assertThat(self.cert_security.get_ui_stream()).emits(
            SecurityMatchers.UiMsg(UiMsgType.DISPLAY_PAIRING_PROMPT))

        # 2. Lower Tester responds with a Pairing Response command, with:
        # a. IO Capability set to “KeyboardOnly”
        # b. OOB data flag set to 0x00 (OOB Authentication data not present)
        # c. AuthReq bonding flag set to the value indicated in the IXIT [7] for ‘Bonding Flags’ and the MITM flag set to ‘1’ and all reserved bits are set to a random value.
        self.cert.security.SendUiCallback(
            UiCallbackMsg(message_type=UiCallbackType.PAIRING_PROMPT,
                          boolean=True,
                          unique_id=1,
                          address=self.dut_address))

        assertThat(self.cert_security.get_ui_stream()).emits(
            SecurityMatchers.UiMsg(UiMsgType.DISPLAY_PASSKEY_ENTRY))

        passkey = self.dut_security.wait_for_ui_event_passkey()

        self.cert.security.SendUiCallback(
            UiCallbackMsg(message_type=UiCallbackType.PASSKEY,
                          numeric_value=passkey,
                          unique_id=1,
                          address=self.dut_address))

        # 3.    IUT and Lower Tester perform phase 2 of the Just Works pairing and establish an encrypted link with the generated LTK.
        assertThat(self.dut_security.get_bond_stream()).emits(
            SecurityMatchers.BondMsg(BondMsgType.DEVICE_BONDED),
            timeout=timedelta(seconds=10))

    @metadata(
        pts_test_id="SM/MAS/SCOB/BV-01-C",
        pts_test_name="Out of Band, IUT Initiator, Secure Connections – Success"
    )
    def test_out_of_band_iut_initiator_secure_connections(self):
        """
            Verify that the IUT supporting LE Secure Connections performs the Out-of-Band pairing procedure correctly as master, initiator.
        """

        oob_combinations = [(OOB_NOT_PRESENT, OOB_PRESENT),
                            (OOB_PRESENT, OOB_NOT_PRESENT),
                            (OOB_PRESENT, OOB_PRESENT)]

        for (dut_oob_flag, cert_oob_flag) in oob_combinations:
            print("oob flag combination dut: " + str(dut_oob_flag) +
                  ", cert: " + str(cert_oob_flag))

            self._prepare_cert_for_connection()

            if dut_oob_flag == LeOobDataFlag.PRESENT:
                oobdata = self.cert.security.GetOutOfBandData(
                    empty_proto.Empty())
                self.dut.security.SetOutOfBandData(
                    OobDataMessage(
                        address=self.cert_address,
                        le_sc_confirmation_value=oobdata.
                        le_sc_confirmation_value,
                        le_sc_random_value=oobdata.le_sc_random_value))

            if cert_oob_flag == LeOobDataFlag.PRESENT:
                oobdata = self.dut.security.GetOutOfBandData(
                    empty_proto.Empty())
                self.cert.security.SetOutOfBandData(
                    OobDataMessage(
                        address=self.dut_address,
                        le_sc_confirmation_value=oobdata.
                        le_sc_confirmation_value,
                        le_sc_random_value=oobdata.le_sc_random_value))

            self.dut.security.SetLeIoCapability(KEYBOARD_ONLY)
            self.dut.security.SetLeOobDataPresent(dut_oob_flag)
            self.dut_security.SetLeAuthRequirements(bond=1,
                                                    mitm=1,
                                                    secure_connections=1)

            self.cert.security.SetLeIoCapability(DISPLAY_ONLY)
            self.cert.security.SetLeOobDataPresent(cert_oob_flag)
            self.cert_security.SetLeAuthRequirements(bond=1,
                                                     mitm=1,
                                                     secure_connections=1)

            # 1. IUT transmits a Pairing Request command with OOB data flag set to either 0x00 or 0x01, and Secure Connections flag set to '1'.
            self.dut.security.CreateBondLe(self.cert_address)

            assertThat(self.cert_security.get_ui_stream()).emits(
                SecurityMatchers.UiMsg(UiMsgType.DISPLAY_PAIRING_PROMPT))

            # 2. Lower Tester responds with a Pairing Response command with Secure Connections flag set to '1' and OOB data flag set to either 0x00 or 0x01.
            self.cert.security.SendUiCallback(
                UiCallbackMsg(message_type=UiCallbackType.PAIRING_PROMPT,
                              boolean=True,
                              unique_id=1,
                              address=self.dut_address))

            # 3. IUT uses the 128-bit value generated by the Lower Tester as the confirm value. Similarly, the Lower Tester uses the 128-bit value generated by the IUT as the confirm value.

            # 4. IUT and Lower Tester perform phase 2 of the pairing process and establish an encrypted link with an LTK generated using the OOB data in phase 2.
            assertThat(self.dut_security.get_bond_stream()).emits(
                SecurityMatchers.BondMsg(BondMsgType.DEVICE_BONDED),
                timeout=timedelta(seconds=10))

            assertThat(self.cert_security.get_bond_stream()).emits(
                SecurityMatchers.BondMsg(BondMsgType.DEVICE_BONDED),
                timeout=timedelta(seconds=10))

            self.dut.security.RemoveBond(self.cert_address)
            self.cert.security.RemoveBond(self.dut_address)

            assertThat(self.dut_security.get_bond_stream()).emits(
                SecurityMatchers.BondMsg(BondMsgType.DEVICE_UNBONDED))

            #disconnection should happen after one second timeout, sleep for 2 just to be sure
            #TODO(jpawlowski): wait for disconnection event instead of sleeping.
            time.sleep(2)