• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1#
2#   Copyright 2019 - The Android Open Source Project
3#
4#   Licensed under the Apache License, Version 2.0 (the "License");
5#   you may not use this file except in compliance with the License.
6#   You may obtain a copy of the License at
7#
8#       http://www.apache.org/licenses/LICENSE-2.0
9#
10#   Unless required by applicable law or agreed to in writing, software
11#   distributed under the License is distributed on an "AS IS" BASIS,
12#   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13#   See the License for the specific language governing permissions and
14#   limitations under the License.
15
16import logging
17
18from blueberry.tests.gd.cert.py_security import PySecurity
19from blueberry.tests.gd.cert.truth import assertThat
20from blueberry.tests.gd.cert import gd_base_test
21from blueberry.tests.gd.security.cert_security import CertSecurity
22from blueberry.facade import common_pb2 as common
23from google.protobuf import empty_pb2 as empty_proto
24from blueberry.facade.hci import controller_facade_pb2 as controller_facade
25from blueberry.facade.hci import le_initiator_address_facade_pb2 as le_initiator_address_facade
26from blueberry.facade.l2cap.classic.facade_pb2 import ClassicSecurityPolicy
27from blueberry.facade.neighbor import facade_pb2 as neighbor_facade
28from blueberry.facade.security.facade_pb2 import AuthenticationRequirements
29from blueberry.facade.security.facade_pb2 import BondMsgType
30from blueberry.facade.security.facade_pb2 import IoCapabilities
31from blueberry.facade.security.facade_pb2 import OobDataPresent
32from blueberry.facade.security.facade_pb2 import UiMsgType
33from mobly import test_runner
34
35
36class SecurityTest(gd_base_test.GdBaseTestClass):
37    """
38        Collection of tests that each sample results from
39        different (unique) combinations of io capabilities, authentication requirements, and oob data.
40    """
41
42    _io_capabilities_name_lookup = {
43        IoCapabilities.DISPLAY_ONLY: "DISPLAY_ONLY",
44        IoCapabilities.DISPLAY_YES_NO_IO_CAP: "DISPLAY_YES_NO_IO_CAP",
45        #IoCapabilities.KEYBOARD_ONLY:"KEYBOARD_ONLY",
46        IoCapabilities.NO_INPUT_NO_OUTPUT: "NO_INPUT_NO_OUTPUT",
47    }
48
49    _auth_reqs_name_lookup = {
50        AuthenticationRequirements.NO_BONDING: "NO_BONDING",
51        AuthenticationRequirements.NO_BONDING_MITM_PROTECTION: "NO_BONDING_MITM_PROTECTION",
52        AuthenticationRequirements.DEDICATED_BONDING: "DEDICATED_BONDING",
53        AuthenticationRequirements.DEDICATED_BONDING_MITM_PROTECTION: "DEDICATED_BONDING_MITM_PROTECTION",
54        AuthenticationRequirements.GENERAL_BONDING: "GENERAL_BONDING",
55        AuthenticationRequirements.GENERAL_BONDING_MITM_PROTECTION: "GENERAL_BONDING_MITM_PROTECTION",
56    }
57
58    # Possible IO Capabilities
59    io_capabilities = (
60        IoCapabilities.DISPLAY_ONLY,
61        IoCapabilities.DISPLAY_YES_NO_IO_CAP,
62        # TODO(optedoblivion): Uncomment when Passkey Entry is implemented in ClassicPairingHandler
63        #IoCapabilities.KEYBOARD_ONLY,
64        IoCapabilities.NO_INPUT_NO_OUTPUT)
65
66    # Possible Authentication Requirements
67    auth_reqs = (AuthenticationRequirements.NO_BONDING, AuthenticationRequirements.NO_BONDING_MITM_PROTECTION,
68                 AuthenticationRequirements.DEDICATED_BONDING,
69                 AuthenticationRequirements.DEDICATED_BONDING_MITM_PROTECTION,
70                 AuthenticationRequirements.GENERAL_BONDING, AuthenticationRequirements.GENERAL_BONDING_MITM_PROTECTION)
71
72    # Possible Out-of-Band data options
73    oob_present = (
74        OobDataPresent.NOT_PRESENT,
75        # TODO(optedoblivion): Uncomment when OOB is implemented in root canal
76        #"P192_PRESENT",
77        #"P256_PRESENT",
78        #"P192_AND_256_PRESENT"
79    )
80
81    mitm_auth_reqs = (AuthenticationRequirements.DEDICATED_BONDING_MITM_PROTECTION,
82                      AuthenticationRequirements.GENERAL_BONDING_MITM_PROTECTION,
83                      AuthenticationRequirements.NO_BONDING_MITM_PROTECTION)
84
85    def setup_class(self):
86        gd_base_test.GdBaseTestClass.setup_class(self, dut_module='SECURITY', cert_module='L2CAP')
87
88    def setup_test(self):
89        gd_base_test.GdBaseTestClass.setup_test(self)
90
91        self.dut.neighbor.EnablePageScan(neighbor_facade.EnableMsg(enabled=True))
92        self.cert.neighbor.EnablePageScan(neighbor_facade.EnableMsg(enabled=True))
93
94        self.dut.name = b'DUT Device'
95        self.dut.address = self.dut.hci_controller.GetMacAddress(empty_proto.Empty()).address
96        self.cert.name = b'Cert Device'
97        self.cert.address = self.cert.hci_controller.GetMacAddress(empty_proto.Empty()).address
98
99        # TODO(optedoblivion): Make this happen in PySecurity or GdDevice
100        self.dut.hci_controller.WriteLocalName(controller_facade.NameMsg(name=self.dut.name))
101        self.cert.hci_controller.WriteLocalName(controller_facade.NameMsg(name=self.cert.name))
102
103        self.dut_security = PySecurity(self.dut)
104        self.cert_security = CertSecurity(self.cert)
105
106        self.dut_address = common.BluetoothAddressWithType(
107            address=common.BluetoothAddress(address=bytes(b'DD:05:04:03:02:01')), type=common.RANDOM_DEVICE_ADDRESS)
108        privacy_policy = le_initiator_address_facade.PrivacyPolicy(
109            address_policy=le_initiator_address_facade.AddressPolicy.USE_STATIC_ADDRESS,
110            address_with_type=self.dut_address)
111        self.dut.security.SetLeInitiatorAddressPolicy(privacy_policy)
112
113    def teardown_test(self):
114        self.dut_security.close()
115        self.cert_security.close()
116        gd_base_test.GdBaseTestClass.teardown_test(self)
117
118    # Initiates the numeric comparison test
119    def _run_ssp_numeric_comparison(self, initiator, responder, init_ui_response, resp_ui_response,
120                                    expected_init_ui_event, expected_resp_ui_event, expected_init_bond_event,
121                                    expected_resp_bond_event):
122        initiator.enable_secure_simple_pairing()
123        responder.enable_secure_simple_pairing()
124        initiator.create_bond(responder.get_address(), common.BluetoothAddressTypeEnum.PUBLIC_DEVICE_ADDRESS)
125        self._verify_ssp_numeric_comparison(initiator, responder, init_ui_response, resp_ui_response,
126                                            expected_init_ui_event, expected_resp_ui_event, expected_init_bond_event,
127                                            expected_resp_bond_event)
128
129    # Verifies the events for the numeric comparion test
130    def _verify_ssp_numeric_comparison(self, initiator, responder, init_ui_response, resp_ui_response,
131                                       expected_init_ui_event, expected_resp_ui_event, expected_init_bond_event,
132                                       expected_resp_bond_event):
133
134        def on_responder_reply():
135            initiator.on_user_input(responder.get_address(), init_ui_response, expected_init_ui_event)
136
137        responder.accept_pairing(initiator.get_address(), resp_ui_response, init_ui_response, on_responder_reply)
138        initiator.wait_for_bond_event(expected_init_bond_event)
139        responder.wait_for_bond_event(expected_resp_bond_event)
140
141    def _run_ssp_oob(self, initiator, responder, init_ui_response, resp_ui_response, expected_init_ui_event,
142                     expected_resp_ui_event, expected_init_bond_event, expected_resp_bond_event, p192_oob_data,
143                     p256_oob_data):
144        initiator.enable_secure_simple_pairing()
145        responder.enable_secure_simple_pairing()
146        initiator.create_bond_out_of_band(responder.get_address(),
147                                          common.BluetoothAddressTypeEnum.PUBLIC_DEVICE_ADDRESS, p192_oob_data,
148                                          p256_oob_data)
149        self._verify_ssp_oob(initiator, responder, init_ui_response, resp_ui_response, expected_init_ui_event,
150                             expected_resp_ui_event, expected_init_bond_event, expected_resp_bond_event, p192_oob_data,
151                             p256_oob_data)
152
153    # Verifies the events for the numeric comparion test
154    def _verify_ssp_oob(self, initiator, responder, init_ui_response, resp_ui_response, expected_init_ui_event,
155                        expected_resp_ui_event, expected_init_bond_event, expected_resp_bond_event, p192_oob_data,
156                        p256_oob_data):
157        responder.accept_oob_pairing(initiator.get_address())
158        initiator.on_user_input(responder.get_address(), init_ui_response, expected_init_ui_event)
159        initiator.wait_for_bond_event(expected_init_bond_event)
160        responder.wait_for_bond_event(expected_resp_bond_event)
161
162    def _run_ssp_passkey(self, initiator, responder, expected_init_bond_event, expected_resp_bond_event):
163        initiator.enable_secure_simple_pairing()
164        responder.enable_secure_simple_pairing()
165        initiator.create_bond(responder.get_address(), common.BluetoothAddressTypeEnum.PUBLIC_DEVICE_ADDRESS)
166        self._verify_ssp_passkey(initiator, responder, expected_init_bond_event, expected_resp_bond_event)
167
168    def _verify_ssp_passkey(self, initiator, responder, expected_init_bond_event, expected_resp_bond_event):
169        responder.send_io_caps(initiator.get_address())
170        passkey = initiator.wait_for_passkey(responder.get_address())
171        responder.input_passkey(initiator.get_address(), passkey)
172        initiator.wait_for_bond_event(expected_init_bond_event)
173        responder.wait_for_bond_event(expected_resp_bond_event)
174
175    def _run_pin(self, initiator, responder, expected_init_bond_event, expected_resp_bond_event):
176        initiator.create_bond(responder.get_address(), common.BluetoothAddressTypeEnum.PUBLIC_DEVICE_ADDRESS)
177        self._verify_pin(initiator, responder, expected_init_bond_event, expected_resp_bond_event)
178
179    def _verify_pin(self, initiator, responder, expected_init_bond_event, expected_resp_bond_event):
180        pin = b'123456789A'
181        logging.info("pin: %s" % pin)
182        initiator.input_pin(responder.get_address(), pin)
183        responder.input_pin(initiator.get_address(), pin)
184        initiator.wait_for_bond_event(expected_init_bond_event)
185        responder.wait_for_bond_event(expected_resp_bond_event)
186
187    def test_setup_teardown(self):
188        """
189            Make sure our setup and teardown is sane
190        """
191        pass
192
193    # no_input_no_output + no_input_no_output is JustWorks no confirmation
194    def test_dut_initiated_no_input_no_output_no_input_no_output_twice_bond_and_enforce(self):
195        # Arrange
196        self.dut_security.set_io_capabilities(IoCapabilities.NO_INPUT_NO_OUTPUT)
197        self.dut_security.set_authentication_requirements(AuthenticationRequirements.DEDICATED_BONDING)
198        self.cert_security.set_io_capabilities(IoCapabilities.NO_INPUT_NO_OUTPUT)
199        self.cert_security.set_authentication_requirements(AuthenticationRequirements.DEDICATED_BONDING)
200
201        # Act and Assert
202        self._run_ssp_numeric_comparison(
203            initiator=self.dut_security,
204            responder=self.cert_security,
205            init_ui_response=True,
206            resp_ui_response=True,
207            expected_init_ui_event=None,
208            expected_resp_ui_event=None,
209            expected_init_bond_event=BondMsgType.DEVICE_BONDED,
210            expected_resp_bond_event=None)
211
212        self.dut_security.enforce_security_policy(self.cert.address,
213                                                  common.BluetoothAddressTypeEnum.PUBLIC_DEVICE_ADDRESS,
214                                                  ClassicSecurityPolicy.ENCRYPTED_TRANSPORT)
215
216        # TODO: We verify enforcement when we make sure EncryptionChange is received on DUT
217
218    # no_input_no_output + no_input_no_output is JustWorks no confirmation
219    def test_dut_initiated_no_input_no_output_no_input_no_output_twice_with_remove_bond(self):
220        # Arrange
221        self.dut_security.set_io_capabilities(IoCapabilities.NO_INPUT_NO_OUTPUT)
222        self.dut_security.set_authentication_requirements(AuthenticationRequirements.DEDICATED_BONDING)
223        self.cert_security.set_io_capabilities(IoCapabilities.NO_INPUT_NO_OUTPUT)
224        self.cert_security.set_authentication_requirements(AuthenticationRequirements.DEDICATED_BONDING)
225
226        # Act and Assert
227        self._run_ssp_numeric_comparison(
228            initiator=self.dut_security,
229            responder=self.cert_security,
230            init_ui_response=True,
231            resp_ui_response=True,
232            expected_init_ui_event=None,
233            expected_resp_ui_event=None,
234            expected_init_bond_event=BondMsgType.DEVICE_BONDED,
235            expected_resp_bond_event=None)
236
237        self.dut_security.remove_bond(self.cert.address, common.BluetoothAddressTypeEnum.PUBLIC_DEVICE_ADDRESS)
238        self.cert_security.remove_bond(self.cert.address, common.BluetoothAddressTypeEnum.PUBLIC_DEVICE_ADDRESS)
239        self.dut_security.wait_for_bond_event(BondMsgType.DEVICE_UNBONDED)
240        self.cert_security.wait_for_bond_event(BondMsgType.DEVICE_UNBONDED)
241
242        self.dut_security.wait_for_disconnect_event()
243        self.cert_security.wait_for_disconnect_event()
244
245        # Act and Assert
246        self._run_ssp_numeric_comparison(
247            initiator=self.dut_security,
248            responder=self.cert_security,
249            init_ui_response=True,
250            resp_ui_response=True,
251            expected_init_ui_event=None,
252            expected_resp_ui_event=None,
253            expected_init_bond_event=BondMsgType.DEVICE_BONDED,
254            expected_resp_bond_event=None)
255
256        self.dut_security.remove_bond(self.cert.address, common.BluetoothAddressTypeEnum.PUBLIC_DEVICE_ADDRESS)
257        self.cert_security.remove_bond(self.cert.address, common.BluetoothAddressTypeEnum.PUBLIC_DEVICE_ADDRESS)
258        self.dut_security.wait_for_bond_event(BondMsgType.DEVICE_UNBONDED)
259        self.cert_security.wait_for_bond_event(BondMsgType.DEVICE_UNBONDED)
260
261        self.dut_security.wait_for_disconnect_event()
262        self.cert_security.wait_for_disconnect_event()
263
264    def test_successful_dut_initiated_ssp_numeric_comparison(self):
265        test_count = len(self.io_capabilities) * len(self.auth_reqs) * len(self.oob_present) * len(
266            self.io_capabilities) * len(self.auth_reqs) * len(self.oob_present)
267        logging.info("Loading %d test combinations" % test_count)
268        i = 0
269        for dut_io_capability in self.io_capabilities:
270            for dut_auth_reqs in self.auth_reqs:
271                for dut_oob_present in self.oob_present:
272                    for cert_io_capability in self.io_capabilities:
273                        for cert_auth_reqs in self.auth_reqs:
274                            for cert_oob_present in self.oob_present:
275                                i = i + 1
276                                logging.info("")
277                                logging.info("===================================================")
278                                logging.info("Running test %d of %d" % (i, test_count))
279                                logging.info("DUT Test Config: %s ; %s ; %s " % (self._io_capabilities_name_lookup.get(
280                                    dut_io_capability, "ERROR"), self._auth_reqs_name_lookup.get(
281                                        dut_auth_reqs, "ERROR"), dut_oob_present))
282                                logging.info(
283                                    "CERT Test Config: %s ; %s ; %s " %
284                                    (self._io_capabilities_name_lookup.get(cert_io_capability, "ERROR"),
285                                     self._auth_reqs_name_lookup.get(cert_auth_reqs, "ERROR"), cert_oob_present))
286                                logging.info("===================================================")
287                                logging.info("")
288                                self.dut_security.set_io_capabilities(dut_io_capability)
289                                self.dut_security.set_authentication_requirements(dut_auth_reqs)
290                                self.cert_security.set_io_capabilities(cert_io_capability)
291                                self.cert_security.set_authentication_requirements(cert_auth_reqs)
292                                init_ui_response = True
293                                resp_ui_response = True
294                                expected_init_ui_event = None  # None is auto accept
295                                expected_resp_ui_event = None  # None is auto accept
296                                expected_init_bond_event = BondMsgType.DEVICE_BONDED
297                                expected_resp_bond_event = None
298                                if dut_io_capability == IoCapabilities.DISPLAY_ONLY:
299                                    if cert_io_capability == IoCapabilities.DISPLAY_YES_NO_IO_CAP:
300                                        expected_resp_ui_event = UiMsgType.DISPLAY_YES_NO_WITH_VALUE
301                                        if dut_auth_reqs in self.mitm_auth_reqs or cert_auth_reqs in self.mitm_auth_reqs:
302                                            expected_init_bond_event = BondMsgType.DEVICE_BOND_FAILED
303                                    elif cert_io_capability == IoCapabilities.KEYBOARD_ONLY:
304                                        expected_resp_ui_event = UiMsgType.DISPLAY_PASSKEY_ENTRY
305                                    elif cert_io_capability == IoCapabilities.DISPLAY_ONLY:
306                                        if dut_auth_reqs in self.mitm_auth_reqs or cert_auth_reqs in self.mitm_auth_reqs:
307                                            expected_init_bond_event = BondMsgType.DEVICE_BOND_FAILED
308                                    elif cert_io_capability == IoCapabilities.NO_INPUT_NO_OUTPUT:
309                                        if dut_auth_reqs in self.mitm_auth_reqs or cert_auth_reqs in self.mitm_auth_reqs:
310                                            expected_init_bond_event = BondMsgType.DEVICE_BOND_FAILED
311                                elif dut_io_capability == IoCapabilities.DISPLAY_YES_NO_IO_CAP:
312                                    expected_init_ui_event = UiMsgType.DISPLAY_YES_NO_WITH_VALUE
313                                    if cert_io_capability == IoCapabilities.DISPLAY_YES_NO_IO_CAP:
314                                        expected_resp_ui_event = UiMsgType.DISPLAY_YES_NO_WITH_VALUE
315                                    elif cert_io_capability == IoCapabilities.KEYBOARD_ONLY:
316                                        expected_init_ui_event = UiMsgType.DISPLAY_PASSKEY
317                                        expected_resp_ui_event = UiMsgType.DISPLAY_PASSKEY_ENTRY
318                                    elif cert_io_capability == IoCapabilities.NO_INPUT_NO_OUTPUT:
319                                        expected_init_ui_event = UiMsgType.DISPLAY_YES_NO  # No value
320                                elif dut_io_capability == IoCapabilities.KEYBOARD_ONLY:
321                                    expected_init_ui_event = UiMsgType.DISPLAY_PASSKEY_ENTRY
322                                    if cert_io_capability == IoCapabilities.DISPLAY_ONLY:
323                                        expected_resp_ui_event = UiMsgType.DISPLAY_PASSKEY
324                                    elif cert_io_capability == IoCapabilities.DISPLAY_YES_NO_IO_CAP:
325                                        expected_resp_ui_event = UiMsgType.DISPLAY_PASSKEY_ENTRY
326                                    elif cert_io_capability == IoCapabilities.KEYBOARD_ONLY:
327                                        expected_resp_ui_event = UiMsgType.DISPLAY_PASSKEY_ENTRY
328                                    elif cert_io_capability == IoCapabilities.NO_INPUT_NO_OUTPUT:
329                                        if dut_auth_reqs in self.mitm_auth_reqs or cert_auth_reqs in self.mitm_auth_reqs:
330                                            expected_init_bond_event = BondMsgType.DEVICE_BOND_FAILED
331                                elif dut_io_capability == IoCapabilities.NO_INPUT_NO_OUTPUT:
332                                    if cert_io_capability == IoCapabilities.DISPLAY_YES_NO_IO_CAP:
333                                        expected_resp_ui_event = UiMsgType.DISPLAY_YES_NO  # No value
334
335                                    if dut_auth_reqs in self.mitm_auth_reqs or cert_auth_reqs in self.mitm_auth_reqs:
336                                        expected_init_bond_event = BondMsgType.DEVICE_BOND_FAILED
337
338                                if cert_oob_present == OobDataPresent.NOT_PRESENT:
339                                    self._run_ssp_numeric_comparison(
340                                        initiator=self.dut_security,
341                                        responder=self.cert_security,
342                                        init_ui_response=init_ui_response,
343                                        resp_ui_response=resp_ui_response,
344                                        expected_init_ui_event=expected_init_ui_event,
345                                        expected_resp_ui_event=expected_resp_ui_event,
346                                        expected_init_bond_event=expected_init_bond_event,
347                                        expected_resp_bond_event=expected_resp_bond_event)
348                                else:
349                                    logging.error("Code path not yet implemented")
350                                    assertThat(False).isTrue()
351
352                                self.dut_security.remove_bond(self.cert_security.get_address(),
353                                                              common.BluetoothAddressTypeEnum.PUBLIC_DEVICE_ADDRESS)
354                                self.cert_security.remove_bond(self.dut_security.get_address(),
355                                                               common.BluetoothAddressTypeEnum.PUBLIC_DEVICE_ADDRESS)
356
357                                self.dut_security.wait_for_bond_event(BondMsgType.DEVICE_UNBONDED)
358                                self.cert_security.wait_for_bond_event(BondMsgType.DEVICE_UNBONDED)
359
360                                self.dut_security.wait_for_disconnect_event()
361                                self.cert_security.wait_for_disconnect_event()
362
363    def test_enable_secure_simple_pairing(self):
364        self.dut_security.enable_secure_simple_pairing()
365        self.cert_security.enable_secure_simple_pairing()
366
367    def test_enable_secure_connections(self):
368        self.dut_security.enable_secure_simple_pairing()
369        self.cert_security.enable_secure_simple_pairing()
370        self.dut_security.enable_secure_connections()
371        self.cert_security.enable_secure_connections()
372
373    def test_get_oob_data_from_dut_controller_p192_present(self):
374        oob_data = self.dut_security.get_oob_data_from_controller(OobDataPresent.P192_PRESENT)
375        assertThat(len(oob_data)).isEqualTo(4)
376        has192C = not all([i == 0 for i in oob_data[0]])
377        has192R = not all([i == 0 for i in oob_data[1]])
378        has256C = not all([i == 0 for i in oob_data[2]])
379        has256R = not all([i == 0 for i in oob_data[3]])
380        assertThat(has192C).isTrue()
381        assertThat(has192R).isTrue()
382        assertThat(has256C).isFalse()
383        assertThat(has256R).isFalse()
384
385    def test_get_oob_data_from_cert_controller_not_present(self):
386        oob_data = self.cert_security.get_oob_data_from_controller(OobDataPresent.NOT_PRESENT)
387        assertThat(len(oob_data)).isEqualTo(4)
388        has192C = not all([i == 0 for i in oob_data[0]])
389        has192R = not all([i == 0 for i in oob_data[1]])
390        has256C = not all([i == 0 for i in oob_data[2]])
391        has256R = not all([i == 0 for i in oob_data[3]])
392        assertThat(has192C).isFalse()
393        assertThat(has192R).isFalse()
394        assertThat(has256C).isFalse()
395        assertThat(has256R).isFalse()
396
397    def test_get_oob_data_from_cert_controller_p192_present_no_secure_connections(self):
398        oob_data = self.cert_security.get_oob_data_from_controller(OobDataPresent.P192_PRESENT)
399        assertThat(len(oob_data)).isEqualTo(4)
400        has192C = not all([i == 0 for i in oob_data[0]])
401        has192R = not all([i == 0 for i in oob_data[1]])
402        has256C = not all([i == 0 for i in oob_data[2]])
403        has256R = not all([i == 0 for i in oob_data[3]])
404        assertThat(has192C).isTrue()
405        assertThat(has192R).isTrue()
406        assertThat(has256C).isFalse()
407        assertThat(has256R).isFalse()
408
409    def test_get_oob_data_from_cert_controller_p192_present(self):
410        self.cert_security.enable_secure_simple_pairing()
411        self.cert_security.enable_secure_connections()
412        oob_data = self.cert_security.get_oob_data_from_controller(OobDataPresent.P192_PRESENT)
413        assertThat(len(oob_data)).isEqualTo(4)
414        has192C = not all([i == 0 for i in oob_data[0]])
415        has192R = not all([i == 0 for i in oob_data[1]])
416        has256C = not all([i == 0 for i in oob_data[2]])
417        has256R = not all([i == 0 for i in oob_data[3]])
418        assertThat(has192C).isTrue()
419        assertThat(has192R).isTrue()
420        assertThat(has256C).isFalse()
421        assertThat(has256R).isFalse()
422
423    def test_get_oob_data_from_cert_controller_p256_present(self):
424        self.cert_security.enable_secure_simple_pairing()
425        self.cert_security.enable_secure_connections()
426        oob_data = self.cert_security.get_oob_data_from_controller(OobDataPresent.P256_PRESENT)
427        assertThat(len(oob_data)).isEqualTo(4)
428        has192C = not all([i == 0 for i in oob_data[0]])
429        has192R = not all([i == 0 for i in oob_data[1]])
430        has256C = not all([i == 0 for i in oob_data[2]])
431        has256R = not all([i == 0 for i in oob_data[3]])
432        assertThat(has192C).isFalse()
433        assertThat(has192R).isFalse()
434        assertThat(has256C).isTrue()
435        assertThat(has256R).isTrue()
436
437    def test_get_oob_data_from_cert_controller_p192_and_p256_present(self):
438        self.cert_security.enable_secure_simple_pairing()
439        self.cert_security.enable_secure_connections()
440        oob_data = self.cert_security.get_oob_data_from_controller(OobDataPresent.P192_AND_256_PRESENT)
441        assertThat(len(oob_data)).isEqualTo(4)
442        has192C = not all([i == 0 for i in oob_data[0]])
443        has192R = not all([i == 0 for i in oob_data[1]])
444        has256C = not all([i == 0 for i in oob_data[2]])
445        has256R = not all([i == 0 for i in oob_data[3]])
446        assertThat(has192C).isTrue()
447        assertThat(has192R).isTrue()
448        assertThat(has256C).isTrue()
449        assertThat(has256R).isTrue()
450
451    def test_successful_dut_initiated_ssp_oob(self):
452        dut_io_capability = IoCapabilities.NO_INPUT_NO_OUTPUT
453        cert_io_capability = IoCapabilities.NO_INPUT_NO_OUTPUT
454        dut_auth_reqs = AuthenticationRequirements.DEDICATED_BONDING_MITM_PROTECTION
455        cert_auth_reqs = AuthenticationRequirements.DEDICATED_BONDING_MITM_PROTECTION
456        cert_oob_present = OobDataPresent.P192_PRESENT
457        self.dut_security.enable_secure_simple_pairing()
458        self.dut_security.enable_secure_connections()
459        self.cert_security.enable_secure_simple_pairing()
460        self.cert_security.enable_secure_connections()
461        self.dut_security.set_io_capabilities(dut_io_capability)
462        self.dut_security.set_authentication_requirements(dut_auth_reqs)
463        self.cert_security.set_io_capabilities(cert_io_capability)
464        self.cert_security.set_authentication_requirements(cert_auth_reqs)
465        init_ui_response = True
466        resp_ui_response = True
467        expected_init_ui_event = None  # None is auto accept
468        expected_resp_ui_event = None  # None is auto accept
469        expected_init_bond_event = BondMsgType.DEVICE_BONDED
470        expected_resp_bond_event = None
471        # get_oob_data returns a tuple of bytes (p192c,p192r,p256c,p256r)
472        local_oob_data = self.cert_security.get_oob_data_from_controller(cert_oob_present)
473        p192_oob_data = local_oob_data[0:2]
474        p256_oob_data = local_oob_data[2:4]
475        self._run_ssp_oob(
476            initiator=self.dut_security,
477            responder=self.cert_security,
478            init_ui_response=init_ui_response,
479            resp_ui_response=resp_ui_response,
480            expected_init_ui_event=expected_init_ui_event,
481            expected_resp_ui_event=expected_resp_ui_event,
482            expected_init_bond_event=expected_init_bond_event,
483            expected_resp_bond_event=expected_resp_bond_event,
484            p192_oob_data=p192_oob_data,
485            p256_oob_data=p256_oob_data)
486        self.dut_security.remove_bond(self.cert_security.get_address(),
487                                      common.BluetoothAddressTypeEnum.PUBLIC_DEVICE_ADDRESS)
488        self.cert_security.remove_bond(self.dut_security.get_address(),
489                                       common.BluetoothAddressTypeEnum.PUBLIC_DEVICE_ADDRESS)
490        self.dut_security.wait_for_bond_event(BondMsgType.DEVICE_UNBONDED)
491        self.cert_security.wait_for_bond_event(BondMsgType.DEVICE_UNBONDED)
492        self.dut_security.wait_for_disconnect_event()
493        self.cert_security.wait_for_disconnect_event()
494
495    def test_successful_dut_initiated_ssp_keyboard(self):
496        dut_io_capability = IoCapabilities.DISPLAY_YES_NO_IO_CAP
497        dut_auth_reqs = AuthenticationRequirements.DEDICATED_BONDING_MITM_PROTECTION
498        dut_oob_present = OobDataPresent.NOT_PRESENT
499        cert_io_capability = IoCapabilities.KEYBOARD_ONLY
500        cert_auth_reqs = AuthenticationRequirements.DEDICATED_BONDING_MITM_PROTECTION
501        cert_oob_present = OobDataPresent.NOT_PRESENT
502        self.dut_security.set_io_capabilities(dut_io_capability)
503        self.dut_security.set_authentication_requirements(dut_auth_reqs)
504        self.cert_security.set_io_capabilities(cert_io_capability)
505        self.cert_security.set_authentication_requirements(cert_auth_reqs)
506
507        self._run_ssp_passkey(
508            initiator=self.dut_security,
509            responder=self.cert_security,
510            expected_init_bond_event=BondMsgType.DEVICE_BONDED,
511            expected_resp_bond_event=BondMsgType.DEVICE_BONDED)
512
513        self.dut_security.remove_bond(self.cert_security.get_address(),
514                                      common.BluetoothAddressTypeEnum.PUBLIC_DEVICE_ADDRESS)
515        self.cert_security.remove_bond(self.dut_security.get_address(),
516                                       common.BluetoothAddressTypeEnum.PUBLIC_DEVICE_ADDRESS)
517
518        self.dut_security.wait_for_bond_event(BondMsgType.DEVICE_UNBONDED)
519        self.cert_security.wait_for_bond_event(BondMsgType.DEVICE_UNBONDED)
520
521        self.dut_security.wait_for_disconnect_event()
522        self.cert_security.wait_for_disconnect_event()
523
524    def test_successful_dut_initiated_pin(self):
525        self.dut_security.set_io_capabilities(IoCapabilities.DISPLAY_YES_NO_IO_CAP)
526        self.dut_security.set_authentication_requirements(AuthenticationRequirements.DEDICATED_BONDING)
527
528        self._run_pin(
529            initiator=self.dut_security,
530            responder=self.cert_security,
531            expected_init_bond_event=BondMsgType.DEVICE_BONDED,
532            expected_resp_bond_event=BondMsgType.DEVICE_BONDED)
533
534        self.dut_security.remove_bond(self.cert_security.get_address(),
535                                      common.BluetoothAddressTypeEnum.PUBLIC_DEVICE_ADDRESS)
536        self.cert_security.remove_bond(self.dut_security.get_address(),
537                                       common.BluetoothAddressTypeEnum.PUBLIC_DEVICE_ADDRESS)
538
539        self.dut_security.wait_for_bond_event(BondMsgType.DEVICE_UNBONDED)
540        self.cert_security.wait_for_bond_event(BondMsgType.DEVICE_UNBONDED)
541
542        self.dut_security.wait_for_disconnect_event()
543        self.cert_security.wait_for_disconnect_event()
544
545    def test_make_sure_oob_data_different(self):
546        oob_data = self.dut_security.get_oob_data_from_controller(OobDataPresent.P192_PRESENT)
547        oob_data2 = self.dut_security.get_oob_data_from_controller(OobDataPresent.P192_PRESENT)
548        assertThat(oob_data).isNotEqualTo(oob_data2)
549
550
551if __name__ == '__main__':
552    test_runner.main()
553