Loading system/gd/cert/matchers.py +4 −0 Original line number Diff line number Diff line Loading @@ -89,6 +89,10 @@ class HciMatchers(object): def SimplePairingComplete(): return lambda event: HciMatchers.EventWithCode(EventCode.SIMPLE_PAIRING_COMPLETE) @staticmethod def Disconnect(): return lambda event: HciMatchers.EventWithCode(EventCode.DISCONNECT) class NeighborMatchers(object): Loading system/gd/cert/py_le_security.py +5 −7 Original line number Diff line number Diff line Loading @@ -46,16 +46,14 @@ class PyLeSecurity(Closable): self._ui_event_stream = EventStream(self._device.security.FetchUiEvents(empty_proto.Empty())) self._bond_event_stream = EventStream(self._device.security.FetchBondEvents(empty_proto.Empty())) def wait_for_bond_event(self, expected_bond_event, timeout=timedelta(seconds=3)): # =timedelta(seconds=DEFAULT_TIMEOUT_SECONDS) """ A bond event will be triggered once the bond process is complete. For the DUT we need to wait for it, for Cert it isn't needed. """ def wait_for_bond_event(self, expected_bond_event, timeout=timedelta(seconds=3)): self._bond_event_stream.assert_event_occurs( match_fn=lambda event: event.message_type == expected_bond_event, timeout=timeout) def wait_for_ui_event(self, expected_ui_event, timeout=timedelta(seconds=3)): self._ui_event_stream.assert_event_occurs( match_fn=lambda event: event.message_type == expected_ui_event, timeout=timeout) def close(self): if self._ui_event_stream is not None: safeClose(self._ui_event_stream) Loading system/gd/security/cert/le_security_test.py +70 −3 Original line number Diff line number Diff line Loading @@ -18,7 +18,9 @@ import time from bluetooth_packets_python3 import hci_packets from cert.event_stream import EventStream from cert.gd_base_test import GdBaseTestClass from cert.matchers import HciMatchers from cert.metadata import metadata from cert.py_hci import PyHci from cert.py_le_security import PyLeSecurity from cert.truth import assertThat from datetime import timedelta Loading @@ -30,9 +32,12 @@ from neighbor.facade import facade_pb2 as neighbor_facade from security.cert.cert_security import CertSecurity from security.facade_pb2 import AuthenticationRequirements from security.facade_pb2 import BondMsgType from security.facade_pb2 import IoCapabilities from security.facade_pb2 import OobDataPresent from security.facade_pb2 import UiCallbackMsg from security.facade_pb2 import UiCallbackType from security.facade_pb2 import UiMsgType from security.facade_pb2 import LeIoCapabilityMessage from bluetooth_packets_python3.hci_packets import OpCode class LeSecurityTest(GdBaseTestClass): Loading @@ -49,13 +54,17 @@ class LeSecurityTest(GdBaseTestClass): self.dut_security = PyLeSecurity(self.dut) self.cert_security = PyLeSecurity(self.cert) self.dut_hci = PyHci(self.dut) self.dut_address = common.BluetoothAddressWithType( address=common.BluetoothAddress(address=bytes(b'0D:05:04:03:02:01')), type=common.RANDOM_DEVICE_ADDRESS) address=common.BluetoothAddress(address=bytes(b'DD:05:04:03:02:01')), type=common.RANDOM_DEVICE_ADDRESS) self.dut.security.SetLeInitiatorAddress(self.dut_address) self.cert_address = common.BluetoothAddressWithType( address=common.BluetoothAddress(address=bytes(b'55:11:FF:AA:33:22')), type=common.RANDOM_DEVICE_ADDRESS) address=common.BluetoothAddress(address=bytes(b'C5:11:FF:AA:33:22')), type=common.RANDOM_DEVICE_ADDRESS) self.cert.security.SetLeInitiatorAddress(self.cert_address) def teardown_test(self): self.dut_hci.close() self.dut_security.close() self.cert_security.close() super().teardown_test() Loading @@ -80,6 +89,26 @@ class LeSecurityTest(GdBaseTestClass): request = le_advertising_facade.CreateAdvertiserRequest(config=config) create_response = self.cert.hci_le_advertising_manager.CreateAdvertiser(request) def _prepare_dut_for_connection(self): # DUT Advertises gap_name = hci_packets.GapData() gap_name.data_type = hci_packets.GapDataType.COMPLETE_LOCAL_NAME gap_name.data = list(bytes(b'Im_The_DUT')) gap_data = le_advertising_facade.GapDataMsg(data=bytes(gap_name.Serialize())) config = le_advertising_facade.AdvertisingConfig( advertisement=[gap_data], random_address=self.dut_address.address, interval_min=512, interval_max=768, event_type=le_advertising_facade.AdvertisingEventType.ADV_IND, address_type=common.RANDOM_DEVICE_ADDRESS, peer_address_type=common.PUBLIC_DEVICE_ADDRESS, peer_address=common.BluetoothAddress(address=bytes(b'00:00:00:00:00:00')), channel_map=7, filter_policy=le_advertising_facade.AdvertisingFilterPolicy.ALL_DEVICES) request = le_advertising_facade.CreateAdvertiserRequest(config=config) create_response = self.dut.hci_le_advertising_manager.CreateAdvertiser(request) @metadata(pts_test_id="SM/MAS/PROT/BV-01-C", pts_test_name="SMP Time Out – IUT Initiator") def test_le_smp_timeout_iut_initiator(self): """ Loading @@ -89,3 +118,41 @@ class LeSecurityTest(GdBaseTestClass): self.dut.security.CreateBondLe(self.cert_address) self.dut_security.wait_for_bond_event( expected_bond_event=BondMsgType.DEVICE_BOND_FAILED, timeout=timedelta(seconds=35)) @metadata(pts_test_id="SM/SLA/PROT/BV-02-C", pts_test_name="SMP Time Out – IUT Responder") def test_le_smp_timeout_iut_responder(self): """ Verify that the IUT handles the lack of pairing response after 30 seconds when acting as initiator. """ self.cert.security.SetLeIoCapability( LeIoCapabilityMessage(capabilities=LeIoCapabilityMessage.LeIoCapabilities.KEYBOARD_ONLY)) self.dut.security.SetLeIoCapability( LeIoCapabilityMessage(capabilities=LeIoCapabilityMessage.LeIoCapabilities.DISPLAY_ONLY)) self._prepare_dut_for_connection() # 1. Lower Tester transmits Pairing Request. self.cert.security.CreateBondLe(self.dut_address) self.dut_security.wait_for_ui_event( expected_ui_event=UiMsgType.DISPLAY_PAIRING_PROMPT, timeout=timedelta(seconds=35)) # 2. IUT responds with Pairing Response. self.dut.security.SendUiCallback( UiCallbackMsg( message_type=UiCallbackType.PAIRING_PROMPT, boolean=True, unique_id=1, address=self.cert_address)) # 3. In phase 2, Lower Tester does not issue the expected Pairing Confirm. # Here the cert receives DISPLAY_PASSKEY_ENTRY. By not replying to it we make sure Pairing Confirm is never sent self.cert_security.wait_for_ui_event( expected_ui_event=UiMsgType.DISPLAY_PASSKEY_ENTRY, timeout=timedelta(seconds=5)) # 4. IUT times out 30 seconds after issued Pairing Response and reports the failure to the Upper Tester. self.dut_security.wait_for_bond_event( expected_bond_event=BondMsgType.DEVICE_BOND_FAILED, timeout=timedelta(seconds=35)) # 5. After additionally (at least) 10 seconds the Lower Tester issues the expected Pairing Confirm. # 6. The IUT closes the connection before receiving the delayed response or does not respond to it when it is received. #TODO: #assertThat(self.dut_hci.get_event_stream()).emits(HciMatchers.Disconnect()) system/gd/security/facade.cc +36 −11 Original line number Diff line number Diff line Loading @@ -79,7 +79,7 @@ class SecurityModuleFacadeService : public SecurityModuleFacade::Service, public ::google::protobuf::Empty* response) override { hci::Address peer; ASSERT(hci::Address::FromString(request->address().address().address(), peer)); hci::AddressType remote_type = hci::AddressType::PUBLIC_DEVICE_ADDRESS; hci::AddressType remote_type = static_cast<hci::AddressType>(request->address().type()); switch (request->message_type()) { case UiCallbackType::PASSKEY: Loading @@ -89,6 +89,10 @@ class SecurityModuleFacadeService : public SecurityModuleFacade::Service, public security_module_->GetSecurityManager()->OnConfirmYesNo(hci::AddressWithType(peer, remote_type), request->boolean()); break; case UiCallbackType::PAIRING_PROMPT: security_module_->GetSecurityManager()->OnPairingPromptAccepted( hci::AddressWithType(peer, remote_type), request->boolean()); break; default: LOG_ERROR("Unknown UiCallbackType %d", static_cast<int>(request->message_type())); return ::grpc::Status(::grpc::StatusCode::INVALID_ARGUMENT, "Unknown UiCallbackType"); Loading @@ -108,6 +112,15 @@ class SecurityModuleFacadeService : public SecurityModuleFacade::Service, public return ::grpc::Status::OK; } ::grpc::Status SetLeIoCapability( ::grpc::ServerContext* context, const LeIoCapabilityMessage* request, ::google::protobuf::Empty* response) override { security_module_->GetFacadeConfigurationApi()->SetLeIoCapability( static_cast<security::IoCapability>(request->capabilities())); return ::grpc::Status::OK; } ::grpc::Status SetAuthenticationRequirements(::grpc::ServerContext* context, const AuthenticationRequirementsMessage* request, ::google::protobuf::Empty* response) override { Loading @@ -123,12 +136,23 @@ class SecurityModuleFacadeService : public SecurityModuleFacade::Service, public return ::grpc::Status::OK; } ::grpc::Status SetLeInitiatorAddress( ::grpc::ServerContext* context, const facade::BluetoothAddressWithType* request, ::google::protobuf::Empty* response) override { hci::Address peer; ASSERT(hci::Address::FromString(request->address().address(), peer)); hci::AddressType peer_type = static_cast<hci::AddressType>(request->type()); security_module_->GetSecurityManager()->SetLeInitiatorAddress(hci::AddressWithType(peer, peer_type)); return ::grpc::Status::OK; } void DisplayPairingPrompt(const bluetooth::hci::AddressWithType& peer, std::string name) { LOG_INFO("%s", peer.ToString().c_str()); UiMsg display_yes_no; display_yes_no.mutable_peer()->mutable_address()->set_address(peer.ToString()); display_yes_no.mutable_peer()->set_type(facade::BluetoothAddressTypeEnum::PUBLIC_DEVICE_ADDRESS); display_yes_no.set_message_type(UiMsgType::DISPLAY_YES_NO); display_yes_no.mutable_peer()->set_type(static_cast<facade::BluetoothAddressTypeEnum>(peer.GetAddressType())); display_yes_no.set_message_type(UiMsgType::DISPLAY_PAIRING_PROMPT); display_yes_no.set_unique_id(unique_id++); ui_events_.OnIncomingEvent(display_yes_no); } Loading @@ -138,7 +162,7 @@ class SecurityModuleFacadeService : public SecurityModuleFacade::Service, public LOG_INFO("%s value = 0x%x", peer.ToString().c_str(), numeric_value); UiMsg display_with_value; display_with_value.mutable_peer()->mutable_address()->set_address(peer.ToString()); display_with_value.mutable_peer()->set_type(facade::BluetoothAddressTypeEnum::PUBLIC_DEVICE_ADDRESS); display_with_value.mutable_peer()->set_type(static_cast<facade::BluetoothAddressTypeEnum>(peer.GetAddressType())); display_with_value.set_message_type(UiMsgType::DISPLAY_YES_NO_WITH_VALUE); display_with_value.set_numeric_value(numeric_value); display_with_value.set_unique_id(unique_id++); Loading @@ -149,7 +173,7 @@ class SecurityModuleFacadeService : public SecurityModuleFacade::Service, public LOG_INFO("%s", peer.ToString().c_str()); UiMsg display_yes_no; display_yes_no.mutable_peer()->mutable_address()->set_address(peer.ToString()); display_yes_no.mutable_peer()->set_type(facade::BluetoothAddressTypeEnum::PUBLIC_DEVICE_ADDRESS); display_yes_no.mutable_peer()->set_type(static_cast<facade::BluetoothAddressTypeEnum>(peer.GetAddressType())); display_yes_no.set_message_type(UiMsgType::DISPLAY_YES_NO); display_yes_no.set_unique_id(unique_id++); ui_events_.OnIncomingEvent(display_yes_no); Loading @@ -159,7 +183,7 @@ class SecurityModuleFacadeService : public SecurityModuleFacade::Service, public LOG_INFO("%s value = 0x%x", peer.ToString().c_str(), passkey); UiMsg display_passkey; display_passkey.mutable_peer()->mutable_address()->set_address(peer.ToString()); display_passkey.mutable_peer()->set_type(facade::BluetoothAddressTypeEnum::PUBLIC_DEVICE_ADDRESS); display_passkey.mutable_peer()->set_type(static_cast<facade::BluetoothAddressTypeEnum>(peer.GetAddressType())); display_passkey.set_message_type(UiMsgType::DISPLAY_PASSKEY); display_passkey.set_numeric_value(passkey); display_passkey.set_unique_id(unique_id++); Loading @@ -170,7 +194,8 @@ class SecurityModuleFacadeService : public SecurityModuleFacade::Service, public LOG_INFO("%s", peer.ToString().c_str()); UiMsg display_passkey_input; display_passkey_input.mutable_peer()->mutable_address()->set_address(peer.ToString()); display_passkey_input.mutable_peer()->set_type(facade::BluetoothAddressTypeEnum::PUBLIC_DEVICE_ADDRESS); display_passkey_input.mutable_peer()->set_type( static_cast<facade::BluetoothAddressTypeEnum>(peer.GetAddressType())); display_passkey_input.set_message_type(UiMsgType::DISPLAY_PASSKEY_ENTRY); display_passkey_input.set_unique_id(unique_id++); ui_events_.OnIncomingEvent(display_passkey_input); Loading @@ -180,7 +205,7 @@ class SecurityModuleFacadeService : public SecurityModuleFacade::Service, public LOG_INFO("%s", peer.ToString().c_str()); UiMsg display_cancel; display_cancel.mutable_peer()->mutable_address()->set_address(peer.ToString()); display_cancel.mutable_peer()->set_type(facade::BluetoothAddressTypeEnum::PUBLIC_DEVICE_ADDRESS); display_cancel.mutable_peer()->set_type(static_cast<facade::BluetoothAddressTypeEnum>(peer.GetAddressType())); display_cancel.set_message_type(UiMsgType::DISPLAY_CANCEL); display_cancel.set_unique_id(unique_id++); ui_events_.OnIncomingEvent(display_cancel); Loading @@ -190,7 +215,7 @@ class SecurityModuleFacadeService : public SecurityModuleFacade::Service, public LOG_INFO("%s", peer.ToString().c_str()); BondMsg bonded; bonded.mutable_peer()->mutable_address()->set_address(peer.ToString()); bonded.mutable_peer()->set_type(facade::BluetoothAddressTypeEnum::PUBLIC_DEVICE_ADDRESS); bonded.mutable_peer()->set_type(static_cast<facade::BluetoothAddressTypeEnum>(peer.GetAddressType())); bonded.set_message_type(BondMsgType::DEVICE_BONDED); bond_events_.OnIncomingEvent(bonded); } Loading @@ -201,7 +226,7 @@ class SecurityModuleFacadeService : public SecurityModuleFacade::Service, public LOG_INFO("%s", peer.ToString().c_str()); BondMsg unbonded; unbonded.mutable_peer()->mutable_address()->set_address(peer.ToString()); unbonded.mutable_peer()->set_type(facade::BluetoothAddressTypeEnum::PUBLIC_DEVICE_ADDRESS); unbonded.mutable_peer()->set_type(static_cast<facade::BluetoothAddressTypeEnum>(peer.GetAddressType())); unbonded.set_message_type(BondMsgType::DEVICE_UNBONDED); bond_events_.OnIncomingEvent(unbonded); } Loading @@ -210,7 +235,7 @@ class SecurityModuleFacadeService : public SecurityModuleFacade::Service, public LOG_INFO("%s", peer.ToString().c_str()); BondMsg bond_failed; bond_failed.mutable_peer()->mutable_address()->set_address(peer.ToString()); bond_failed.mutable_peer()->set_type(facade::BluetoothAddressTypeEnum::PUBLIC_DEVICE_ADDRESS); bond_failed.mutable_peer()->set_type(static_cast<facade::BluetoothAddressTypeEnum>(peer.GetAddressType())); bond_failed.set_message_type(BondMsgType::DEVICE_BOND_FAILED); bond_events_.OnIncomingEvent(bond_failed); } Loading system/gd/security/facade.proto +15 −0 Original line number Diff line number Diff line Loading @@ -11,8 +11,10 @@ service SecurityModuleFacade { rpc CancelBond(facade.BluetoothAddressWithType) returns (google.protobuf.Empty) {} rpc RemoveBond(facade.BluetoothAddressWithType) returns (google.protobuf.Empty) {} rpc SetIoCapability(IoCapabilityMessage) returns (google.protobuf.Empty) {} rpc SetLeIoCapability(LeIoCapabilityMessage) returns (google.protobuf.Empty) {} rpc SetAuthenticationRequirements(AuthenticationRequirementsMessage) returns (google.protobuf.Empty) {} rpc SetOobDataPresent(OobDataMessage) returns (google.protobuf.Empty) {} rpc SetLeInitiatorAddress(facade.BluetoothAddressWithType) returns (google.protobuf.Empty) {} rpc SendUiCallback(UiCallbackMsg) returns (google.protobuf.Empty) {} rpc FetchUiEvents(google.protobuf.Empty) returns (stream UiMsg) {} rpc FetchBondEvents(google.protobuf.Empty) returns (stream BondMsg) {} Loading @@ -24,6 +26,7 @@ enum UiMsgType { DISPLAY_PASSKEY = 2; DISPLAY_PASSKEY_ENTRY = 3; DISPLAY_CANCEL = 4; DISPLAY_PAIRING_PROMPT = 5; } message UiMsg { Loading @@ -36,6 +39,7 @@ message UiMsg { enum UiCallbackType { YES_NO = 0; PASSKEY = 1; PAIRING_PROMPT = 2; } message UiCallbackMsg { Loading Loading @@ -68,6 +72,17 @@ message IoCapabilityMessage { IoCapabilities capability = 1; } message LeIoCapabilityMessage { enum LeIoCapabilities { DISPLAY_ONLY = 0; DISPLAY_YES_NO_IO_CAP = 1; KEYBOARD_ONLY = 2; NO_INPUT_NO_OUTPUT = 3; KEYBOARD_DISPLAY = 4; } LeIoCapabilities capabilities = 1; } enum AuthenticationRequirements { NO_BONDING = 0; NO_BONDING_MITM_PROTECTION = 1; Loading Loading
system/gd/cert/matchers.py +4 −0 Original line number Diff line number Diff line Loading @@ -89,6 +89,10 @@ class HciMatchers(object): def SimplePairingComplete(): return lambda event: HciMatchers.EventWithCode(EventCode.SIMPLE_PAIRING_COMPLETE) @staticmethod def Disconnect(): return lambda event: HciMatchers.EventWithCode(EventCode.DISCONNECT) class NeighborMatchers(object): Loading
system/gd/cert/py_le_security.py +5 −7 Original line number Diff line number Diff line Loading @@ -46,16 +46,14 @@ class PyLeSecurity(Closable): self._ui_event_stream = EventStream(self._device.security.FetchUiEvents(empty_proto.Empty())) self._bond_event_stream = EventStream(self._device.security.FetchBondEvents(empty_proto.Empty())) def wait_for_bond_event(self, expected_bond_event, timeout=timedelta(seconds=3)): # =timedelta(seconds=DEFAULT_TIMEOUT_SECONDS) """ A bond event will be triggered once the bond process is complete. For the DUT we need to wait for it, for Cert it isn't needed. """ def wait_for_bond_event(self, expected_bond_event, timeout=timedelta(seconds=3)): self._bond_event_stream.assert_event_occurs( match_fn=lambda event: event.message_type == expected_bond_event, timeout=timeout) def wait_for_ui_event(self, expected_ui_event, timeout=timedelta(seconds=3)): self._ui_event_stream.assert_event_occurs( match_fn=lambda event: event.message_type == expected_ui_event, timeout=timeout) def close(self): if self._ui_event_stream is not None: safeClose(self._ui_event_stream) Loading
system/gd/security/cert/le_security_test.py +70 −3 Original line number Diff line number Diff line Loading @@ -18,7 +18,9 @@ import time from bluetooth_packets_python3 import hci_packets from cert.event_stream import EventStream from cert.gd_base_test import GdBaseTestClass from cert.matchers import HciMatchers from cert.metadata import metadata from cert.py_hci import PyHci from cert.py_le_security import PyLeSecurity from cert.truth import assertThat from datetime import timedelta Loading @@ -30,9 +32,12 @@ from neighbor.facade import facade_pb2 as neighbor_facade from security.cert.cert_security import CertSecurity from security.facade_pb2 import AuthenticationRequirements from security.facade_pb2 import BondMsgType from security.facade_pb2 import IoCapabilities from security.facade_pb2 import OobDataPresent from security.facade_pb2 import UiCallbackMsg from security.facade_pb2 import UiCallbackType from security.facade_pb2 import UiMsgType from security.facade_pb2 import LeIoCapabilityMessage from bluetooth_packets_python3.hci_packets import OpCode class LeSecurityTest(GdBaseTestClass): Loading @@ -49,13 +54,17 @@ class LeSecurityTest(GdBaseTestClass): self.dut_security = PyLeSecurity(self.dut) self.cert_security = PyLeSecurity(self.cert) self.dut_hci = PyHci(self.dut) self.dut_address = common.BluetoothAddressWithType( address=common.BluetoothAddress(address=bytes(b'0D:05:04:03:02:01')), type=common.RANDOM_DEVICE_ADDRESS) address=common.BluetoothAddress(address=bytes(b'DD:05:04:03:02:01')), type=common.RANDOM_DEVICE_ADDRESS) self.dut.security.SetLeInitiatorAddress(self.dut_address) self.cert_address = common.BluetoothAddressWithType( address=common.BluetoothAddress(address=bytes(b'55:11:FF:AA:33:22')), type=common.RANDOM_DEVICE_ADDRESS) address=common.BluetoothAddress(address=bytes(b'C5:11:FF:AA:33:22')), type=common.RANDOM_DEVICE_ADDRESS) self.cert.security.SetLeInitiatorAddress(self.cert_address) def teardown_test(self): self.dut_hci.close() self.dut_security.close() self.cert_security.close() super().teardown_test() Loading @@ -80,6 +89,26 @@ class LeSecurityTest(GdBaseTestClass): request = le_advertising_facade.CreateAdvertiserRequest(config=config) create_response = self.cert.hci_le_advertising_manager.CreateAdvertiser(request) def _prepare_dut_for_connection(self): # DUT Advertises gap_name = hci_packets.GapData() gap_name.data_type = hci_packets.GapDataType.COMPLETE_LOCAL_NAME gap_name.data = list(bytes(b'Im_The_DUT')) gap_data = le_advertising_facade.GapDataMsg(data=bytes(gap_name.Serialize())) config = le_advertising_facade.AdvertisingConfig( advertisement=[gap_data], random_address=self.dut_address.address, interval_min=512, interval_max=768, event_type=le_advertising_facade.AdvertisingEventType.ADV_IND, address_type=common.RANDOM_DEVICE_ADDRESS, peer_address_type=common.PUBLIC_DEVICE_ADDRESS, peer_address=common.BluetoothAddress(address=bytes(b'00:00:00:00:00:00')), channel_map=7, filter_policy=le_advertising_facade.AdvertisingFilterPolicy.ALL_DEVICES) request = le_advertising_facade.CreateAdvertiserRequest(config=config) create_response = self.dut.hci_le_advertising_manager.CreateAdvertiser(request) @metadata(pts_test_id="SM/MAS/PROT/BV-01-C", pts_test_name="SMP Time Out – IUT Initiator") def test_le_smp_timeout_iut_initiator(self): """ Loading @@ -89,3 +118,41 @@ class LeSecurityTest(GdBaseTestClass): self.dut.security.CreateBondLe(self.cert_address) self.dut_security.wait_for_bond_event( expected_bond_event=BondMsgType.DEVICE_BOND_FAILED, timeout=timedelta(seconds=35)) @metadata(pts_test_id="SM/SLA/PROT/BV-02-C", pts_test_name="SMP Time Out – IUT Responder") def test_le_smp_timeout_iut_responder(self): """ Verify that the IUT handles the lack of pairing response after 30 seconds when acting as initiator. """ self.cert.security.SetLeIoCapability( LeIoCapabilityMessage(capabilities=LeIoCapabilityMessage.LeIoCapabilities.KEYBOARD_ONLY)) self.dut.security.SetLeIoCapability( LeIoCapabilityMessage(capabilities=LeIoCapabilityMessage.LeIoCapabilities.DISPLAY_ONLY)) self._prepare_dut_for_connection() # 1. Lower Tester transmits Pairing Request. self.cert.security.CreateBondLe(self.dut_address) self.dut_security.wait_for_ui_event( expected_ui_event=UiMsgType.DISPLAY_PAIRING_PROMPT, timeout=timedelta(seconds=35)) # 2. IUT responds with Pairing Response. self.dut.security.SendUiCallback( UiCallbackMsg( message_type=UiCallbackType.PAIRING_PROMPT, boolean=True, unique_id=1, address=self.cert_address)) # 3. In phase 2, Lower Tester does not issue the expected Pairing Confirm. # Here the cert receives DISPLAY_PASSKEY_ENTRY. By not replying to it we make sure Pairing Confirm is never sent self.cert_security.wait_for_ui_event( expected_ui_event=UiMsgType.DISPLAY_PASSKEY_ENTRY, timeout=timedelta(seconds=5)) # 4. IUT times out 30 seconds after issued Pairing Response and reports the failure to the Upper Tester. self.dut_security.wait_for_bond_event( expected_bond_event=BondMsgType.DEVICE_BOND_FAILED, timeout=timedelta(seconds=35)) # 5. After additionally (at least) 10 seconds the Lower Tester issues the expected Pairing Confirm. # 6. The IUT closes the connection before receiving the delayed response or does not respond to it when it is received. #TODO: #assertThat(self.dut_hci.get_event_stream()).emits(HciMatchers.Disconnect())
system/gd/security/facade.cc +36 −11 Original line number Diff line number Diff line Loading @@ -79,7 +79,7 @@ class SecurityModuleFacadeService : public SecurityModuleFacade::Service, public ::google::protobuf::Empty* response) override { hci::Address peer; ASSERT(hci::Address::FromString(request->address().address().address(), peer)); hci::AddressType remote_type = hci::AddressType::PUBLIC_DEVICE_ADDRESS; hci::AddressType remote_type = static_cast<hci::AddressType>(request->address().type()); switch (request->message_type()) { case UiCallbackType::PASSKEY: Loading @@ -89,6 +89,10 @@ class SecurityModuleFacadeService : public SecurityModuleFacade::Service, public security_module_->GetSecurityManager()->OnConfirmYesNo(hci::AddressWithType(peer, remote_type), request->boolean()); break; case UiCallbackType::PAIRING_PROMPT: security_module_->GetSecurityManager()->OnPairingPromptAccepted( hci::AddressWithType(peer, remote_type), request->boolean()); break; default: LOG_ERROR("Unknown UiCallbackType %d", static_cast<int>(request->message_type())); return ::grpc::Status(::grpc::StatusCode::INVALID_ARGUMENT, "Unknown UiCallbackType"); Loading @@ -108,6 +112,15 @@ class SecurityModuleFacadeService : public SecurityModuleFacade::Service, public return ::grpc::Status::OK; } ::grpc::Status SetLeIoCapability( ::grpc::ServerContext* context, const LeIoCapabilityMessage* request, ::google::protobuf::Empty* response) override { security_module_->GetFacadeConfigurationApi()->SetLeIoCapability( static_cast<security::IoCapability>(request->capabilities())); return ::grpc::Status::OK; } ::grpc::Status SetAuthenticationRequirements(::grpc::ServerContext* context, const AuthenticationRequirementsMessage* request, ::google::protobuf::Empty* response) override { Loading @@ -123,12 +136,23 @@ class SecurityModuleFacadeService : public SecurityModuleFacade::Service, public return ::grpc::Status::OK; } ::grpc::Status SetLeInitiatorAddress( ::grpc::ServerContext* context, const facade::BluetoothAddressWithType* request, ::google::protobuf::Empty* response) override { hci::Address peer; ASSERT(hci::Address::FromString(request->address().address(), peer)); hci::AddressType peer_type = static_cast<hci::AddressType>(request->type()); security_module_->GetSecurityManager()->SetLeInitiatorAddress(hci::AddressWithType(peer, peer_type)); return ::grpc::Status::OK; } void DisplayPairingPrompt(const bluetooth::hci::AddressWithType& peer, std::string name) { LOG_INFO("%s", peer.ToString().c_str()); UiMsg display_yes_no; display_yes_no.mutable_peer()->mutable_address()->set_address(peer.ToString()); display_yes_no.mutable_peer()->set_type(facade::BluetoothAddressTypeEnum::PUBLIC_DEVICE_ADDRESS); display_yes_no.set_message_type(UiMsgType::DISPLAY_YES_NO); display_yes_no.mutable_peer()->set_type(static_cast<facade::BluetoothAddressTypeEnum>(peer.GetAddressType())); display_yes_no.set_message_type(UiMsgType::DISPLAY_PAIRING_PROMPT); display_yes_no.set_unique_id(unique_id++); ui_events_.OnIncomingEvent(display_yes_no); } Loading @@ -138,7 +162,7 @@ class SecurityModuleFacadeService : public SecurityModuleFacade::Service, public LOG_INFO("%s value = 0x%x", peer.ToString().c_str(), numeric_value); UiMsg display_with_value; display_with_value.mutable_peer()->mutable_address()->set_address(peer.ToString()); display_with_value.mutable_peer()->set_type(facade::BluetoothAddressTypeEnum::PUBLIC_DEVICE_ADDRESS); display_with_value.mutable_peer()->set_type(static_cast<facade::BluetoothAddressTypeEnum>(peer.GetAddressType())); display_with_value.set_message_type(UiMsgType::DISPLAY_YES_NO_WITH_VALUE); display_with_value.set_numeric_value(numeric_value); display_with_value.set_unique_id(unique_id++); Loading @@ -149,7 +173,7 @@ class SecurityModuleFacadeService : public SecurityModuleFacade::Service, public LOG_INFO("%s", peer.ToString().c_str()); UiMsg display_yes_no; display_yes_no.mutable_peer()->mutable_address()->set_address(peer.ToString()); display_yes_no.mutable_peer()->set_type(facade::BluetoothAddressTypeEnum::PUBLIC_DEVICE_ADDRESS); display_yes_no.mutable_peer()->set_type(static_cast<facade::BluetoothAddressTypeEnum>(peer.GetAddressType())); display_yes_no.set_message_type(UiMsgType::DISPLAY_YES_NO); display_yes_no.set_unique_id(unique_id++); ui_events_.OnIncomingEvent(display_yes_no); Loading @@ -159,7 +183,7 @@ class SecurityModuleFacadeService : public SecurityModuleFacade::Service, public LOG_INFO("%s value = 0x%x", peer.ToString().c_str(), passkey); UiMsg display_passkey; display_passkey.mutable_peer()->mutable_address()->set_address(peer.ToString()); display_passkey.mutable_peer()->set_type(facade::BluetoothAddressTypeEnum::PUBLIC_DEVICE_ADDRESS); display_passkey.mutable_peer()->set_type(static_cast<facade::BluetoothAddressTypeEnum>(peer.GetAddressType())); display_passkey.set_message_type(UiMsgType::DISPLAY_PASSKEY); display_passkey.set_numeric_value(passkey); display_passkey.set_unique_id(unique_id++); Loading @@ -170,7 +194,8 @@ class SecurityModuleFacadeService : public SecurityModuleFacade::Service, public LOG_INFO("%s", peer.ToString().c_str()); UiMsg display_passkey_input; display_passkey_input.mutable_peer()->mutable_address()->set_address(peer.ToString()); display_passkey_input.mutable_peer()->set_type(facade::BluetoothAddressTypeEnum::PUBLIC_DEVICE_ADDRESS); display_passkey_input.mutable_peer()->set_type( static_cast<facade::BluetoothAddressTypeEnum>(peer.GetAddressType())); display_passkey_input.set_message_type(UiMsgType::DISPLAY_PASSKEY_ENTRY); display_passkey_input.set_unique_id(unique_id++); ui_events_.OnIncomingEvent(display_passkey_input); Loading @@ -180,7 +205,7 @@ class SecurityModuleFacadeService : public SecurityModuleFacade::Service, public LOG_INFO("%s", peer.ToString().c_str()); UiMsg display_cancel; display_cancel.mutable_peer()->mutable_address()->set_address(peer.ToString()); display_cancel.mutable_peer()->set_type(facade::BluetoothAddressTypeEnum::PUBLIC_DEVICE_ADDRESS); display_cancel.mutable_peer()->set_type(static_cast<facade::BluetoothAddressTypeEnum>(peer.GetAddressType())); display_cancel.set_message_type(UiMsgType::DISPLAY_CANCEL); display_cancel.set_unique_id(unique_id++); ui_events_.OnIncomingEvent(display_cancel); Loading @@ -190,7 +215,7 @@ class SecurityModuleFacadeService : public SecurityModuleFacade::Service, public LOG_INFO("%s", peer.ToString().c_str()); BondMsg bonded; bonded.mutable_peer()->mutable_address()->set_address(peer.ToString()); bonded.mutable_peer()->set_type(facade::BluetoothAddressTypeEnum::PUBLIC_DEVICE_ADDRESS); bonded.mutable_peer()->set_type(static_cast<facade::BluetoothAddressTypeEnum>(peer.GetAddressType())); bonded.set_message_type(BondMsgType::DEVICE_BONDED); bond_events_.OnIncomingEvent(bonded); } Loading @@ -201,7 +226,7 @@ class SecurityModuleFacadeService : public SecurityModuleFacade::Service, public LOG_INFO("%s", peer.ToString().c_str()); BondMsg unbonded; unbonded.mutable_peer()->mutable_address()->set_address(peer.ToString()); unbonded.mutable_peer()->set_type(facade::BluetoothAddressTypeEnum::PUBLIC_DEVICE_ADDRESS); unbonded.mutable_peer()->set_type(static_cast<facade::BluetoothAddressTypeEnum>(peer.GetAddressType())); unbonded.set_message_type(BondMsgType::DEVICE_UNBONDED); bond_events_.OnIncomingEvent(unbonded); } Loading @@ -210,7 +235,7 @@ class SecurityModuleFacadeService : public SecurityModuleFacade::Service, public LOG_INFO("%s", peer.ToString().c_str()); BondMsg bond_failed; bond_failed.mutable_peer()->mutable_address()->set_address(peer.ToString()); bond_failed.mutable_peer()->set_type(facade::BluetoothAddressTypeEnum::PUBLIC_DEVICE_ADDRESS); bond_failed.mutable_peer()->set_type(static_cast<facade::BluetoothAddressTypeEnum>(peer.GetAddressType())); bond_failed.set_message_type(BondMsgType::DEVICE_BOND_FAILED); bond_events_.OnIncomingEvent(bond_failed); } Loading
system/gd/security/facade.proto +15 −0 Original line number Diff line number Diff line Loading @@ -11,8 +11,10 @@ service SecurityModuleFacade { rpc CancelBond(facade.BluetoothAddressWithType) returns (google.protobuf.Empty) {} rpc RemoveBond(facade.BluetoothAddressWithType) returns (google.protobuf.Empty) {} rpc SetIoCapability(IoCapabilityMessage) returns (google.protobuf.Empty) {} rpc SetLeIoCapability(LeIoCapabilityMessage) returns (google.protobuf.Empty) {} rpc SetAuthenticationRequirements(AuthenticationRequirementsMessage) returns (google.protobuf.Empty) {} rpc SetOobDataPresent(OobDataMessage) returns (google.protobuf.Empty) {} rpc SetLeInitiatorAddress(facade.BluetoothAddressWithType) returns (google.protobuf.Empty) {} rpc SendUiCallback(UiCallbackMsg) returns (google.protobuf.Empty) {} rpc FetchUiEvents(google.protobuf.Empty) returns (stream UiMsg) {} rpc FetchBondEvents(google.protobuf.Empty) returns (stream BondMsg) {} Loading @@ -24,6 +26,7 @@ enum UiMsgType { DISPLAY_PASSKEY = 2; DISPLAY_PASSKEY_ENTRY = 3; DISPLAY_CANCEL = 4; DISPLAY_PAIRING_PROMPT = 5; } message UiMsg { Loading @@ -36,6 +39,7 @@ message UiMsg { enum UiCallbackType { YES_NO = 0; PASSKEY = 1; PAIRING_PROMPT = 2; } message UiCallbackMsg { Loading Loading @@ -68,6 +72,17 @@ message IoCapabilityMessage { IoCapabilities capability = 1; } message LeIoCapabilityMessage { enum LeIoCapabilities { DISPLAY_ONLY = 0; DISPLAY_YES_NO_IO_CAP = 1; KEYBOARD_ONLY = 2; NO_INPUT_NO_OUTPUT = 3; KEYBOARD_DISPLAY = 4; } LeIoCapabilities capabilities = 1; } enum AuthenticationRequirements { NO_BONDING = 0; NO_BONDING_MITM_PROTECTION = 1; Loading