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