class SecurityTest(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='L2CAP')

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

        self.dut.neighbor.EnablePageScan(
            neighbor_facade.EnableMsg(enabled=True))
        self.cert.neighbor.EnablePageScan(
            neighbor_facade.EnableMsg(enabled=True))

        self.dut.name = b'DUT Device'
        self.dut.address = self.dut.hci_controller.GetMacAddress(
            empty_proto.Empty()).address
        self.cert.name = b'Cert Device'
        self.cert.address = self.cert.hci_controller.GetMacAddress(
            empty_proto.Empty()).address

        # TODO(optedoblivion): Make this happen in PySecurity or GdDevice
        self.dut.hci_controller.WriteLocalName(
            controller_facade.NameMsg(name=self.dut.name))
        self.cert.hci_controller.WriteLocalName(
            controller_facade.NameMsg(name=self.cert.name))

        self.dut_security = PySecurity(self.dut)
        self.cert_security = CertSecurity(self.cert)

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

    # SSP Numeric Comparison test cases
    def _run_ssp_numeric_comparison(
            self, initiator, responder, init_ui_response, resp_ui_response,
            expected_init_ui_event, expected_resp_ui_event,
            expected_init_bond_event, expected_resp_bond_event):
        initiator.enable_secure_simple_pairing()
        responder.enable_secure_simple_pairing()
        initiator.create_bond(
            responder.get_address(),
            common.BluetoothAddressTypeEnum.PUBLIC_DEVICE_ADDRESS)
        responder.accept_pairing(initiator.get_address(), resp_ui_response)
        initiator.on_user_input(responder.get_address(), init_ui_response,
                                expected_init_ui_event)
        initiator.wait_for_bond_event(expected_init_bond_event)
        responder.wait_for_bond_event(expected_resp_bond_event)

    def test_setup_teardown(self):
        """
            Make sure our setup and teardown is sane
        """
        pass

###### JustWorks (Numeric Comparison w/ no UI) ######
## Needs dialog as per security a bug unless pairing is temporary

# display_only + display_only is JustWorks no confirmation

    def test_dut_initiated_display_only_display_only(self):
        # Arrange
        self.dut_security.set_io_capabilities(IoCapabilities.DISPLAY_ONLY)
        self.dut_security.set_authentication_requirements(
            AuthenticationRequirements.DEDICATED_BONDING_MITM_PROTECTION)
        self.dut_security.set_oob_data(OobDataPresent.NOT_PRESENT)
        self.cert_security.set_io_capabilities(IoCapabilities.DISPLAY_ONLY)
        self.cert_security.set_authentication_requirements(
            AuthenticationRequirements.DEDICATED_BONDING_MITM_PROTECTION)
        self.cert_security.set_oob_data(OobDataPresent.NOT_PRESENT)

        # Act and Assert
        self._run_ssp_numeric_comparison(
            initiator=self.dut_security,
            responder=self.cert_security,
            init_ui_response=True,
            resp_ui_response=True,
            expected_init_ui_event=None,
            expected_resp_ui_event=None,
            expected_init_bond_event=BondMsgType.DEVICE_BONDED,
            expected_resp_bond_event=None)

    # display_yes_no + display_only is JustWorks no confirmation
    def test_dut_initiated_display_yes_no_display_only(self):
        # Arrange
        self.dut_security.set_io_capabilities(
            IoCapabilities.DISPLAY_YES_NO_IO_CAP)
        self.dut_security.set_authentication_requirements(
            AuthenticationRequirements.DEDICATED_BONDING_MITM_PROTECTION)
        self.dut_security.set_oob_data(OobDataPresent.NOT_PRESENT)
        self.cert_security.set_io_capabilities(IoCapabilities.DISPLAY_ONLY)
        self.cert_security.set_authentication_requirements(
            AuthenticationRequirements.DEDICATED_BONDING_MITM_PROTECTION)
        self.cert_security.set_oob_data(OobDataPresent.NOT_PRESENT)

        # Act and Assert
        self._run_ssp_numeric_comparison(
            initiator=self.dut_security,
            responder=self.cert_security,
            init_ui_response=True,
            resp_ui_response=True,
            expected_init_ui_event=UiMsgType.DISPLAY_YES_NO_WITH_VALUE,
            expected_resp_ui_event=None,
            expected_init_bond_event=BondMsgType.DEVICE_BONDED,
            expected_resp_bond_event=None)

    # keyboard_only + display_only is JustWorks no confirmation
    def test_dut_initiated_keyboard_only_display_only(self):
        # Arrange
        self.dut_security.set_io_capabilities(IoCapabilities.KEYBOARD_ONLY)
        self.dut_security.set_authentication_requirements(
            AuthenticationRequirements.DEDICATED_BONDING_MITM_PROTECTION)
        self.dut_security.set_oob_data(OobDataPresent.NOT_PRESENT)
        self.cert_security.set_io_capabilities(IoCapabilities.DISPLAY_ONLY)
        self.cert_security.set_authentication_requirements(
            AuthenticationRequirements.DEDICATED_BONDING_MITM_PROTECTION)
        self.cert_security.set_oob_data(OobDataPresent.NOT_PRESENT)

        # Act and Assert
        self._run_ssp_numeric_comparison(
            initiator=self.dut_security,
            responder=self.cert_security,
            init_ui_response=True,
            resp_ui_response=True,
            expected_init_ui_event=None,
            expected_resp_ui_event=None,
            expected_init_bond_event=BondMsgType.DEVICE_BONDED,
            expected_resp_bond_event=None)

    # no_input_no_output + display_only is JustWorks no confirmation
    def test_dut_initiated_no_input_no_output_display_only(self):
        # Arrange
        self.dut_security.set_io_capabilities(IoCapabilities.NO_INPUT_NO_OUTPUT)
        self.dut_security.set_authentication_requirements(
            AuthenticationRequirements.DEDICATED_BONDING_MITM_PROTECTION)
        self.dut_security.set_oob_data(OobDataPresent.NOT_PRESENT)
        self.cert_security.set_io_capabilities(IoCapabilities.DISPLAY_ONLY)
        self.cert_security.set_authentication_requirements(
            AuthenticationRequirements.DEDICATED_BONDING_MITM_PROTECTION)
        self.cert_security.set_oob_data(OobDataPresent.NOT_PRESENT)

        # Act and Assert
        self._run_ssp_numeric_comparison(
            initiator=self.dut_security,
            responder=self.cert_security,
            init_ui_response=True,
            resp_ui_response=True,
            expected_init_ui_event=None,
            expected_resp_ui_event=None,
            expected_init_bond_event=BondMsgType.DEVICE_BONDED,
            expected_resp_bond_event=None)

    # display_only + display_yes_no is JustWorks no confirmation
    def test_dut_initiated_display_only_display_yes_no(self):
        # Arrange
        self.dut_security.set_io_capabilities(IoCapabilities.DISPLAY_ONLY)
        self.dut_security.set_authentication_requirements(
            AuthenticationRequirements.DEDICATED_BONDING_MITM_PROTECTION)
        self.dut_security.set_oob_data(OobDataPresent.NOT_PRESENT)
        self.cert_security.set_io_capabilities(
            IoCapabilities.DISPLAY_YES_NO_IO_CAP)
        self.cert_security.set_authentication_requirements(
            AuthenticationRequirements.DEDICATED_BONDING_MITM_PROTECTION)
        self.cert_security.set_oob_data(OobDataPresent.NOT_PRESENT)

        # Act and Assert
        self._run_ssp_numeric_comparison(
            initiator=self.dut_security,
            responder=self.cert_security,
            init_ui_response=True,
            resp_ui_response=True,
            expected_init_ui_event=None,
            expected_resp_ui_event=None,
            expected_init_bond_event=BondMsgType.DEVICE_BONDED,
            expected_resp_bond_event=None)

    # display_yes_no + display_yes_no is JustWorks no confirmation
    def test_dut_initiated_display_yes_no_display_yes_no(self):
        # Arrange
        self.dut_security.set_io_capabilities(
            IoCapabilities.DISPLAY_YES_NO_IO_CAP)
        self.dut_security.set_authentication_requirements(
            AuthenticationRequirements.DEDICATED_BONDING_MITM_PROTECTION)
        self.dut_security.set_oob_data(OobDataPresent.NOT_PRESENT)
        self.cert_security.set_io_capabilities(
            IoCapabilities.DISPLAY_YES_NO_IO_CAP)
        self.cert_security.set_authentication_requirements(
            AuthenticationRequirements.DEDICATED_BONDING_MITM_PROTECTION)
        self.cert_security.set_oob_data(OobDataPresent.NOT_PRESENT)

        # Act and Assert
        self._run_ssp_numeric_comparison(
            initiator=self.dut_security,
            responder=self.cert_security,
            init_ui_response=True,
            resp_ui_response=True,
            expected_init_ui_event=UiMsgType.DISPLAY_YES_NO_WITH_VALUE,
            expected_resp_ui_event=None,
            expected_init_bond_event=BondMsgType.DEVICE_BONDED,
            expected_resp_bond_event=None)

    # keyboard_only + display_yes_no is JustWorks no confirmation
    def test_dut_initiated_keyboard_only_display_yes_no(self):
        # Arrange
        self.dut_security.set_io_capabilities(IoCapabilities.KEYBOARD_ONLY)
        self.dut_security.set_authentication_requirements(
            AuthenticationRequirements.DEDICATED_BONDING_MITM_PROTECTION)
        self.dut_security.set_oob_data(OobDataPresent.NOT_PRESENT)
        self.cert_security.set_io_capabilities(
            IoCapabilities.DISPLAY_YES_NO_IO_CAP)
        self.cert_security.set_authentication_requirements(
            AuthenticationRequirements.DEDICATED_BONDING_MITM_PROTECTION)
        self.cert_security.set_oob_data(OobDataPresent.NOT_PRESENT)

        # Act and Assert
        self._run_ssp_numeric_comparison(
            initiator=self.dut_security,
            responder=self.cert_security,
            init_ui_response=True,
            resp_ui_response=True,
            expected_init_ui_event=None,
            expected_resp_ui_event=None,
            expected_init_bond_event=BondMsgType.DEVICE_BONDED,
            expected_resp_bond_event=None)

    # no_input_no_output + display_yes_no is JustWorks no confirmation
    def test_dut_initiated_no_input_no_output_display_yes_no(self):
        # Arrange
        self.dut_security.set_io_capabilities(IoCapabilities.NO_INPUT_NO_OUTPUT)
        self.dut_security.set_authentication_requirements(
            AuthenticationRequirements.DEDICATED_BONDING_MITM_PROTECTION)
        self.dut_security.set_oob_data(OobDataPresent.NOT_PRESENT)
        self.cert_security.set_io_capabilities(
            IoCapabilities.DISPLAY_YES_NO_IO_CAP)
        self.cert_security.set_authentication_requirements(
            AuthenticationRequirements.DEDICATED_BONDING_MITM_PROTECTION)
        self.cert_security.set_oob_data(OobDataPresent.NOT_PRESENT)

        # Act and Assert
        self._run_ssp_numeric_comparison(
            initiator=self.dut_security,
            responder=self.cert_security,
            init_ui_response=True,
            resp_ui_response=True,
            expected_init_ui_event=None,
            expected_resp_ui_event=None,
            expected_init_bond_event=BondMsgType.DEVICE_BONDED,
            expected_resp_bond_event=None)

    # display_only + keyboard_only is JustWorks no confirmation
    def test_dut_initiated_display_only_keyboard_only(self):
        # Arrange
        self.dut_security.set_io_capabilities(IoCapabilities.DISPLAY_ONLY)
        self.dut_security.set_authentication_requirements(
            AuthenticationRequirements.DEDICATED_BONDING_MITM_PROTECTION)
        self.dut_security.set_oob_data(OobDataPresent.NOT_PRESENT)
        self.cert_security.set_io_capabilities(IoCapabilities.KEYBOARD_ONLY)
        self.cert_security.set_authentication_requirements(
            AuthenticationRequirements.DEDICATED_BONDING_MITM_PROTECTION)
        self.cert_security.set_oob_data(OobDataPresent.NOT_PRESENT)

        # Act and Assert
        self._run_ssp_numeric_comparison(
            initiator=self.dut_security,
            responder=self.cert_security,
            init_ui_response=True,
            resp_ui_response=True,
            expected_init_ui_event=None,
            expected_resp_ui_event=None,
            expected_init_bond_event=BondMsgType.DEVICE_BONDED,
            expected_resp_bond_event=None)

    # display_yes_no + keyboard_only is JustWorks no confirmation
    def test_dut_initiated_display_yes_no_keyboard_only(self):
        # Arrange
        self.dut_security.set_io_capabilities(
            IoCapabilities.DISPLAY_YES_NO_IO_CAP)
        self.dut_security.set_authentication_requirements(
            AuthenticationRequirements.DEDICATED_BONDING_MITM_PROTECTION)
        self.dut_security.set_oob_data(OobDataPresent.NOT_PRESENT)
        self.cert_security.set_io_capabilities(IoCapabilities.KEYBOARD_ONLY)
        self.cert_security.set_authentication_requirements(
            AuthenticationRequirements.DEDICATED_BONDING_MITM_PROTECTION)
        self.cert_security.set_oob_data(OobDataPresent.NOT_PRESENT)

        # Act and Assert
        self._run_ssp_numeric_comparison(
            initiator=self.dut_security,
            responder=self.cert_security,
            init_ui_response=True,
            resp_ui_response=True,
            expected_init_ui_event=UiMsgType.DISPLAY_PASSKEY,
            expected_resp_ui_event=None,
            expected_init_bond_event=BondMsgType.DEVICE_BONDED,
            expected_resp_bond_event=None)

    # keyboard_only + display_yes_no is JustWorks no confirmation
    def test_dut_initiated_keyboard_only_keyboard_only(self):
        # Arrange
        self.dut_security.set_io_capabilities(IoCapabilities.KEYBOARD_ONLY)
        self.dut_security.set_authentication_requirements(
            AuthenticationRequirements.DEDICATED_BONDING_MITM_PROTECTION)
        self.dut_security.set_oob_data(OobDataPresent.NOT_PRESENT)
        self.cert_security.set_io_capabilities(IoCapabilities.KEYBOARD_ONLY)
        self.cert_security.set_authentication_requirements(
            AuthenticationRequirements.DEDICATED_BONDING_MITM_PROTECTION)
        self.cert_security.set_oob_data(OobDataPresent.NOT_PRESENT)

        # Act and Assert
        self._run_ssp_numeric_comparison(
            initiator=self.dut_security,
            responder=self.cert_security,
            init_ui_response=True,
            resp_ui_response=True,
            expected_init_ui_event=None,
            expected_resp_ui_event=None,
            expected_init_bond_event=BondMsgType.DEVICE_BONDED,
            expected_resp_bond_event=None)

    # no_input_no_output + keyboard_only is JustWorks no confirmation
    def test_dut_initiated_no_input_no_output_keyboard_only(self):
        # Arrange
        self.dut_security.set_io_capabilities(IoCapabilities.NO_INPUT_NO_OUTPUT)
        self.dut_security.set_authentication_requirements(
            AuthenticationRequirements.DEDICATED_BONDING_MITM_PROTECTION)
        self.dut_security.set_oob_data(OobDataPresent.NOT_PRESENT)
        self.cert_security.set_io_capabilities(
            IoCapabilities.DISPLAY_YES_NO_IO_CAP)
        self.cert_security.set_authentication_requirements(
            AuthenticationRequirements.DEDICATED_BONDING_MITM_PROTECTION)
        self.cert_security.set_oob_data(OobDataPresent.NOT_PRESENT)

        # Act and Assert
        self._run_ssp_numeric_comparison(
            initiator=self.dut_security,
            responder=self.cert_security,
            init_ui_response=True,
            resp_ui_response=True,
            expected_init_ui_event=None,
            expected_resp_ui_event=None,
            expected_init_bond_event=BondMsgType.DEVICE_BONDED,
            expected_resp_bond_event=None)

    # display_only + no_input_no_output is JustWorks no confirmation
    def test_dut_initiated_display_only_keyboard_only(self):
        # Arrange
        self.dut_security.set_io_capabilities(IoCapabilities.DISPLAY_ONLY)
        self.dut_security.set_authentication_requirements(
            AuthenticationRequirements.DEDICATED_BONDING_MITM_PROTECTION)
        self.dut_security.set_oob_data(OobDataPresent.NOT_PRESENT)
        self.cert_security.set_io_capabilities(
            IoCapabilities.NO_INPUT_NO_OUTPUT)
        self.cert_security.set_authentication_requirements(
            AuthenticationRequirements.DEDICATED_BONDING_MITM_PROTECTION)
        self.cert_security.set_oob_data(OobDataPresent.NOT_PRESENT)

        # Act and Assert
        self._run_ssp_numeric_comparison(
            initiator=self.dut_security,
            responder=self.cert_security,
            init_ui_response=True,
            resp_ui_response=True,
            expected_init_ui_event=None,
            expected_resp_ui_event=None,
            expected_init_bond_event=BondMsgType.DEVICE_BONDED,
            expected_resp_bond_event=None)

    # display_yes_no + keyboard_only is JustWorks no confirmation
    def test_dut_initiated_display_yes_no_no_input_no_output(self):
        # Arrange
        self.dut_security.set_io_capabilities(
            IoCapabilities.DISPLAY_YES_NO_IO_CAP)
        self.dut_security.set_authentication_requirements(
            AuthenticationRequirements.DEDICATED_BONDING_MITM_PROTECTION)
        self.dut_security.set_oob_data(OobDataPresent.NOT_PRESENT)
        self.cert_security.set_io_capabilities(
            IoCapabilities.NO_INPUT_NO_OUTPUT)
        self.cert_security.set_authentication_requirements(
            AuthenticationRequirements.DEDICATED_BONDING_MITM_PROTECTION)
        self.cert_security.set_oob_data(OobDataPresent.NOT_PRESENT)

        # Act and Assert
        self._run_ssp_numeric_comparison(
            initiator=self.dut_security,
            responder=self.cert_security,
            init_ui_response=True,
            resp_ui_response=True,
            expected_init_ui_event=UiMsgType.DISPLAY_YES_NO_WITH_VALUE,
            expected_resp_ui_event=None,
            expected_init_bond_event=BondMsgType.DEVICE_BONDED,
            expected_resp_bond_event=None)

    # keyboard_only + display_yes_no is JustWorks no confirmation
    def test_dut_initiated_keyboard_only_no_input_no_output(self):
        # Arrange
        self.dut_security.set_io_capabilities(IoCapabilities.KEYBOARD_ONLY)
        self.dut_security.set_authentication_requirements(
            AuthenticationRequirements.DEDICATED_BONDING_MITM_PROTECTION)
        self.dut_security.set_oob_data(OobDataPresent.NOT_PRESENT)
        self.cert_security.set_io_capabilities(
            IoCapabilities.NO_INPUT_NO_OUTPUT)
        self.cert_security.set_authentication_requirements(
            AuthenticationRequirements.DEDICATED_BONDING_MITM_PROTECTION)
        self.cert_security.set_oob_data(OobDataPresent.NOT_PRESENT)

        # Act and Assert
        self._run_ssp_numeric_comparison(
            initiator=self.dut_security,
            responder=self.cert_security,
            init_ui_response=True,
            resp_ui_response=True,
            expected_init_ui_event=None,
            expected_resp_ui_event=None,
            expected_init_bond_event=BondMsgType.DEVICE_BONDED,
            expected_resp_bond_event=None)

    # no_input_no_output + keyboard_only is JustWorks no confirmation
    def test_dut_initiated_no_input_no_output_no_input_no_output(self):
        # Arrange
        self.dut_security.set_io_capabilities(IoCapabilities.NO_INPUT_NO_OUTPUT)
        self.dut_security.set_authentication_requirements(
            AuthenticationRequirements.DEDICATED_BONDING_MITM_PROTECTION)
        self.dut_security.set_oob_data(OobDataPresent.NOT_PRESENT)
        self.cert_security.set_io_capabilities(
            IoCapabilities.NO_INPUT_NO_OUTPUT)
        self.cert_security.set_authentication_requirements(
            AuthenticationRequirements.DEDICATED_BONDING_MITM_PROTECTION)
        self.cert_security.set_oob_data(OobDataPresent.NOT_PRESENT)

        # Act and Assert
        self._run_ssp_numeric_comparison(
            initiator=self.dut_security,
            responder=self.cert_security,
            init_ui_response=True,
            resp_ui_response=True,
            expected_init_ui_event=None,
            expected_resp_ui_event=None,
            expected_init_bond_event=BondMsgType.DEVICE_BONDED,
            expected_resp_bond_event=None)
Beispiel #2
0
class SecurityTest(GdBaseTestClass):
    """
        Collection of tests that each sample results from 
        different (unique) combinations of io capabilities, authentication requirements, and oob data.
    """

    _io_capabilities_name_lookup = {
        IoCapabilities.DISPLAY_ONLY:
        "DISPLAY_ONLY",
        IoCapabilities.DISPLAY_YES_NO_IO_CAP:
        "DISPLAY_YES_NO_IO_CAP",
        #IoCapabilities.KEYBOARD_ONLY:"KEYBOARD_ONLY",
        IoCapabilities.NO_INPUT_NO_OUTPUT:
        "NO_INPUT_NO_OUTPUT",
    }

    _auth_reqs_name_lookup = {
        AuthenticationRequirements.NO_BONDING:
        "NO_BONDING",
        AuthenticationRequirements.NO_BONDING_MITM_PROTECTION:
        "NO_BONDING_MITM_PROTECTION",
        AuthenticationRequirements.DEDICATED_BONDING:
        "DEDICATED_BONDING",
        AuthenticationRequirements.DEDICATED_BONDING_MITM_PROTECTION:
        "DEDICATED_BONDING_MITM_PROTECTION",
        AuthenticationRequirements.GENERAL_BONDING:
        "GENERAL_BONDING",
        AuthenticationRequirements.GENERAL_BONDING_MITM_PROTECTION:
        "GENERAL_BONDING_MITM_PROTECTION",
    }

    # Possible IO Capabilities
    io_capabilities = (
        IoCapabilities.DISPLAY_ONLY,
        IoCapabilities.DISPLAY_YES_NO_IO_CAP,
        # TODO(optedoblivion): Uncomment when Passkey Entry is implemented in ClassicPairingHandler
        #IoCapabilities.KEYBOARD_ONLY,
        IoCapabilities.NO_INPUT_NO_OUTPUT)

    # Possible Authentication Requirements
    auth_reqs = (AuthenticationRequirements.NO_BONDING,
                 AuthenticationRequirements.NO_BONDING_MITM_PROTECTION,
                 AuthenticationRequirements.DEDICATED_BONDING,
                 AuthenticationRequirements.DEDICATED_BONDING_MITM_PROTECTION,
                 AuthenticationRequirements.GENERAL_BONDING,
                 AuthenticationRequirements.GENERAL_BONDING_MITM_PROTECTION)

    # Possible Out-of-Band data options
    oob_present = (
        OobDataPresent.NOT_PRESENT,
        # TODO(optedoblivion): Uncomment when OOB is implemented in root canal
        #"P192_PRESENT",
        #"P256_PRESENT",
        #"P192_AND_256_PRESENT"
    )

    mitm_auth_reqs = (
        AuthenticationRequirements.DEDICATED_BONDING_MITM_PROTECTION,
        AuthenticationRequirements.GENERAL_BONDING_MITM_PROTECTION,
        AuthenticationRequirements.NO_BONDING_MITM_PROTECTION)

    def setup_class(self):
        super().setup_class(dut_module='SECURITY', cert_module='L2CAP')

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

        self.dut.neighbor.EnablePageScan(
            neighbor_facade.EnableMsg(enabled=True))
        self.cert.neighbor.EnablePageScan(
            neighbor_facade.EnableMsg(enabled=True))

        self.dut.name = b'DUT Device'
        self.dut.address = self.dut.hci_controller.GetMacAddress(
            empty_proto.Empty()).address
        self.cert.name = b'Cert Device'
        self.cert.address = self.cert.hci_controller.GetMacAddress(
            empty_proto.Empty()).address

        # TODO(optedoblivion): Make this happen in PySecurity or GdDevice
        self.dut.hci_controller.WriteLocalName(
            controller_facade.NameMsg(name=self.dut.name))
        self.cert.hci_controller.WriteLocalName(
            controller_facade.NameMsg(name=self.cert.name))

        self.dut_security = PySecurity(self.dut)
        self.cert_security = CertSecurity(self.cert)

        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)

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

    # Initiates the numeric comparison test
    def _run_ssp_numeric_comparison(self, initiator, responder,
                                    init_ui_response, resp_ui_response,
                                    expected_init_ui_event,
                                    expected_resp_ui_event,
                                    expected_init_bond_event,
                                    expected_resp_bond_event):
        initiator.enable_secure_simple_pairing()
        responder.enable_secure_simple_pairing()
        initiator.create_bond(
            responder.get_address(),
            common.BluetoothAddressTypeEnum.PUBLIC_DEVICE_ADDRESS)
        self._verify_ssp_numeric_comparison(initiator, responder,
                                            init_ui_response, resp_ui_response,
                                            expected_init_ui_event,
                                            expected_resp_ui_event,
                                            expected_init_bond_event,
                                            expected_resp_bond_event)

    # Verifies the events for the numeric comparion test
    def _verify_ssp_numeric_comparison(self, initiator, responder,
                                       init_ui_response, resp_ui_response,
                                       expected_init_ui_event,
                                       expected_resp_ui_event,
                                       expected_init_bond_event,
                                       expected_resp_bond_event):
        responder.accept_pairing(initiator.get_address(), resp_ui_response)
        initiator.on_user_input(responder.get_address(), init_ui_response,
                                expected_init_ui_event)
        initiator.wait_for_bond_event(expected_init_bond_event)
        responder.wait_for_bond_event(expected_resp_bond_event)

    def test_setup_teardown(self):
        """
            Make sure our setup and teardown is sane
        """
        pass

    # no_input_no_output + no_input_no_output is JustWorks no confirmation
    def test_dut_initiated_no_input_no_output_no_input_no_output_twice_bond_and_enforce(
            self):
        # Arrange
        self.dut_security.set_io_capabilities(
            IoCapabilities.NO_INPUT_NO_OUTPUT)
        self.dut_security.set_authentication_requirements(
            AuthenticationRequirements.DEDICATED_BONDING)
        self.dut_security.set_oob_data(OobDataPresent.NOT_PRESENT)
        self.cert_security.set_io_capabilities(
            IoCapabilities.NO_INPUT_NO_OUTPUT)
        self.cert_security.set_authentication_requirements(
            AuthenticationRequirements.DEDICATED_BONDING)
        self.cert_security.set_oob_data(OobDataPresent.NOT_PRESENT)

        # Act and Assert
        self._run_ssp_numeric_comparison(
            initiator=self.dut_security,
            responder=self.cert_security,
            init_ui_response=True,
            resp_ui_response=True,
            expected_init_ui_event=None,
            expected_resp_ui_event=None,
            expected_init_bond_event=BondMsgType.DEVICE_BONDED,
            expected_resp_bond_event=None)

        self.dut_security.enforce_security_policy(
            self.cert.address,
            common.BluetoothAddressTypeEnum.PUBLIC_DEVICE_ADDRESS,
            ClassicSecurityPolicy.ENCRYPTED_TRANSPORT)

        # TODO: We verify enforcement when we make sure EncryptionChange is received on DUT

    # no_input_no_output + no_input_no_output is JustWorks no confirmation
    def test_dut_initiated_no_input_no_output_no_input_no_output_twice_with_remove_bond(
            self):
        # Arrange
        self.dut_security.set_io_capabilities(
            IoCapabilities.NO_INPUT_NO_OUTPUT)
        self.dut_security.set_authentication_requirements(
            AuthenticationRequirements.DEDICATED_BONDING)
        self.dut_security.set_oob_data(OobDataPresent.NOT_PRESENT)
        self.cert_security.set_io_capabilities(
            IoCapabilities.NO_INPUT_NO_OUTPUT)
        self.cert_security.set_authentication_requirements(
            AuthenticationRequirements.DEDICATED_BONDING)
        self.cert_security.set_oob_data(OobDataPresent.NOT_PRESENT)

        # Act and Assert
        self._run_ssp_numeric_comparison(
            initiator=self.dut_security,
            responder=self.cert_security,
            init_ui_response=True,
            resp_ui_response=True,
            expected_init_ui_event=None,
            expected_resp_ui_event=None,
            expected_init_bond_event=BondMsgType.DEVICE_BONDED,
            expected_resp_bond_event=None)

        self.dut_security.remove_bond(
            self.cert.address,
            common.BluetoothAddressTypeEnum.PUBLIC_DEVICE_ADDRESS)

        self.dut_security.wait_for_disconnect_event()
        self.cert_security.wait_for_disconnect_event()

        # Act and Assert
        self._run_ssp_numeric_comparison(
            initiator=self.dut_security,
            responder=self.cert_security,
            init_ui_response=True,
            resp_ui_response=True,
            expected_init_ui_event=None,
            expected_resp_ui_event=None,
            expected_init_bond_event=BondMsgType.DEVICE_BONDED,
            expected_resp_bond_event=None)

    def test_successful_dut_initiated_ssp_numeric_comparison(self):
        test_count = len(self.io_capabilities) * len(self.auth_reqs) * len(
            self.oob_present) * len(self.io_capabilities) * len(
                self.auth_reqs) * len(self.oob_present)
        logging.info("Loading %d test combinations" % test_count)
        i = 0
        for dut_io_capability in self.io_capabilities:
            for dut_auth_reqs in self.auth_reqs:
                for dut_oob_present in self.oob_present:
                    for cert_io_capability in self.io_capabilities:
                        for cert_auth_reqs in self.auth_reqs:
                            for cert_oob_present in self.oob_present:
                                i = i + 1
                                logging.info("")
                                logging.info(
                                    "==================================================="
                                )
                                logging.info("Running test %d of %d" %
                                             (i, test_count))
                                logging.info(
                                    "DUT Test Config: %s ; %s ; %s " %
                                    (self._io_capabilities_name_lookup.get(
                                        dut_io_capability, "ERROR"),
                                     self._auth_reqs_name_lookup.get(
                                         dut_auth_reqs,
                                         "ERROR"), dut_oob_present))
                                logging.info(
                                    "CERT Test Config: %s ; %s ; %s " %
                                    (self._io_capabilities_name_lookup.get(
                                        cert_io_capability, "ERROR"),
                                     self._auth_reqs_name_lookup.get(
                                         cert_auth_reqs,
                                         "ERROR"), cert_oob_present))
                                logging.info(
                                    "==================================================="
                                )
                                logging.info("")
                                self.dut_security.set_io_capabilities(
                                    dut_io_capability)
                                self.dut_security.set_authentication_requirements(
                                    dut_auth_reqs)
                                self.dut_security.set_oob_data(dut_oob_present)
                                self.cert_security.set_io_capabilities(
                                    cert_io_capability)
                                self.cert_security.set_authentication_requirements(
                                    cert_auth_reqs)
                                self.cert_security.set_oob_data(
                                    cert_oob_present)
                                init_ui_response = True
                                resp_ui_response = True
                                expected_init_ui_event = None  # None is auto accept
                                expected_resp_ui_event = None  # None is auto accept
                                expected_init_bond_event = BondMsgType.DEVICE_BONDED
                                expected_resp_bond_event = None
                                if dut_io_capability == IoCapabilities.DISPLAY_ONLY:
                                    if cert_io_capability == IoCapabilities.DISPLAY_YES_NO_IO_CAP:
                                        expected_resp_ui_event = UiMsgType.DISPLAY_YES_NO_WITH_VALUE
                                        if dut_auth_reqs in self.mitm_auth_reqs or cert_auth_reqs in self.mitm_auth_reqs:
                                            expected_init_bond_event = BondMsgType.DEVICE_BOND_FAILED
                                    elif cert_io_capability == IoCapabilities.KEYBOARD_ONLY:
                                        expected_resp_ui_event = UiMsgType.DISPLAY_PASSKEY_ENTRY
                                    elif cert_io_capability == IoCapabilities.DISPLAY_ONLY:
                                        if dut_auth_reqs in self.mitm_auth_reqs or cert_auth_reqs in self.mitm_auth_reqs:
                                            expected_init_bond_event = BondMsgType.DEVICE_BOND_FAILED
                                    elif cert_io_capability == IoCapabilities.NO_INPUT_NO_OUTPUT:
                                        if dut_auth_reqs in self.mitm_auth_reqs or cert_auth_reqs in self.mitm_auth_reqs:
                                            expected_init_bond_event = BondMsgType.DEVICE_BOND_FAILED
                                elif dut_io_capability == IoCapabilities.DISPLAY_YES_NO_IO_CAP:
                                    expected_init_ui_event = UiMsgType.DISPLAY_YES_NO_WITH_VALUE
                                    if cert_io_capability == IoCapabilities.DISPLAY_YES_NO_IO_CAP:
                                        expected_resp_ui_event = UiMsgType.DISPLAY_YES_NO_WITH_VALUE
                                    elif cert_io_capability == IoCapabilities.KEYBOARD_ONLY:
                                        expected_init_ui_event = UiMsgType.DISPLAY_PASSKEY
                                        expected_resp_ui_event = UiMsgType.DISPLAY_PASSKEY_ENTRY
                                    elif cert_io_capability == IoCapabilities.NO_INPUT_NO_OUTPUT:
                                        expected_init_ui_event = UiMsgType.DISPLAY_YES_NO  # No value
                                elif dut_io_capability == IoCapabilities.KEYBOARD_ONLY:
                                    expected_init_ui_event = UiMsgType.DISPLAY_PASSKEY_ENTRY
                                    if cert_io_capability == IoCapabilities.DISPLAY_ONLY:
                                        expected_resp_ui_event = UiMsgType.DISPLAY_PASSKEY
                                    elif cert_io_capability == IoCapabilities.DISPLAY_YES_NO_IO_CAP:
                                        expected_resp_ui_event = UiMsgType.DISPLAY_PASSKEY_ENTRY
                                    elif cert_io_capability == IoCapabilities.KEYBOARD_ONLY:
                                        expected_resp_ui_event = UiMsgType.DISPLAY_PASSKEY_ENTRY
                                    elif cert_io_capability == IoCapabilities.NO_INPUT_NO_OUTPUT:
                                        if dut_auth_reqs in self.mitm_auth_reqs or cert_auth_reqs in self.mitm_auth_reqs:
                                            expected_init_bond_event = BondMsgType.DEVICE_BOND_FAILED
                                elif dut_io_capability == IoCapabilities.NO_INPUT_NO_OUTPUT:
                                    if cert_io_capability == IoCapabilities.DISPLAY_YES_NO_IO_CAP:
                                        expected_resp_ui_event = UiMsgType.DISPLAY_YES_NO  # No value

                                    if dut_auth_reqs in self.mitm_auth_reqs or cert_auth_reqs in self.mitm_auth_reqs:
                                        expected_init_bond_event = BondMsgType.DEVICE_BOND_FAILED

                                self._run_ssp_numeric_comparison(
                                    initiator=self.dut_security,
                                    responder=self.cert_security,
                                    init_ui_response=init_ui_response,
                                    resp_ui_response=resp_ui_response,
                                    expected_init_ui_event=
                                    expected_init_ui_event,
                                    expected_resp_ui_event=
                                    expected_resp_ui_event,
                                    expected_init_bond_event=
                                    expected_init_bond_event,
                                    expected_resp_bond_event=
                                    expected_resp_bond_event)

                                self.dut_security.remove_bond(
                                    self.cert_security.get_address(),
                                    common.BluetoothAddressTypeEnum.
                                    PUBLIC_DEVICE_ADDRESS)
                                self.cert_security.remove_bond(
                                    self.dut_security.get_address(),
                                    common.BluetoothAddressTypeEnum.
                                    PUBLIC_DEVICE_ADDRESS)

                                self.dut_security.wait_for_bond_event(
                                    BondMsgType.DEVICE_UNBONDED)
                                self.cert_security.wait_for_bond_event(
                                    BondMsgType.DEVICE_UNBONDED)

                                self.dut_security.wait_for_disconnect_event()
                                self.cert_security.wait_for_disconnect_event()