Loading tools/rootcanal/Android.bp +1 −0 Original line number Diff line number Diff line Loading @@ -309,6 +309,7 @@ python_test_host { "test/LL/CIS/CEN/*.py", "test/LL/CIS/PER/*.py", "test/LL/CON_/CEN/*.py", "test/LL/CON_/INI/*.py", "test/LL/CON_/PER/*.py", "test/LL/DDI/ADV/*.py", "test/LL/DDI/SCN/*.py", Loading tools/rootcanal/model/controller/link_layer_controller.cc +55 −65 Original line number Diff line number Diff line Loading @@ -209,7 +209,7 @@ bool LinkLayerController::ResolvingListBusy() { } std::optional<AddressWithType> LinkLayerController::ResolvePrivateAddress( AddressWithType address, IrkSelection irk) { AddressWithType address) { if (!address.IsRpa()) { return address; } Loading @@ -219,17 +219,12 @@ std::optional<AddressWithType> LinkLayerController::ResolvePrivateAddress( } for (auto& entry : le_resolving_list_) { std::array<uint8_t, LinkLayerController::kIrkSize> const& used_irk = irk == IrkSelection::Local ? entry.local_irk : entry.peer_irk; if (address.IsRpaThatMatchesIrk(used_irk)) { if (address.IsRpaThatMatchesIrk(entry.peer_irk)) { // Update the peer resolvable address used for the peer // with the returned identity address. if (irk == IrkSelection::Peer) { entry.peer_resolvable_address = address.GetAddress(); } return PeerIdentityAddress(entry.peer_identity_address, return PeerDeviceAddress(entry.peer_identity_address, entry.peer_identity_address_type); } } Loading @@ -237,6 +232,34 @@ std::optional<AddressWithType> LinkLayerController::ResolvePrivateAddress( return {}; } bool LinkLayerController::ResolveTargetA(AddressWithType target_a, AddressWithType adv_a) { if (!le_resolving_list_enabled_) { return false; } for (auto const& entry : le_resolving_list_) { if (adv_a == PeerDeviceAddress(entry.peer_identity_address, entry.peer_identity_address_type) && target_a.IsRpaThatMatchesIrk(entry.local_irk)) { return true; } } return false; } bool LinkLayerController::ValidateTargetA(AddressWithType target_a, AddressWithType adv_a) { if (IsLocalPublicOrRandomAddress(target_a)) { return true; } if (target_a.IsRpa()) { return ResolveTargetA(target_a, adv_a); } return false; } std::optional<AddressWithType> LinkLayerController::GenerateResolvablePrivateAddress(AddressWithType address, IrkSelection irk) { Loading Loading @@ -2940,11 +2963,7 @@ void LinkLayerController::ScanIncomingLeLegacyAdvertisingPdu( // address. The scanner’s filter policy shall then determine if the scanner // responds with a scan request. AddressWithType resolved_advertising_address = ResolvePrivateAddress(advertising_address, IrkSelection::Peer) .value_or(advertising_address); std::optional<AddressWithType> resolved_target_address = ResolvePrivateAddress(target_address, IrkSelection::Peer); ResolvePrivateAddress(advertising_address).value_or(advertising_address); if (resolved_advertising_address != advertising_address) { DEBUG(id_, "Resolved the advertising address {} to {}", advertising_address, Loading Loading @@ -2987,8 +3006,7 @@ void LinkLayerController::ScanIncomingLeLegacyAdvertisingPdu( // resolution is enabled, and the address is resolved successfully case bluetooth::hci::LeScanningFilterPolicy::ACCEPT_ALL: case bluetooth::hci::LeScanningFilterPolicy::FILTER_ACCEPT_LIST_ONLY: if (!IsLocalPublicOrRandomAddress(target_address) && !(target_address.IsRpa() && resolved_target_address)) { if (!ValidateTargetA(target_address, resolved_advertising_address)) { DEBUG(id_, "Legacy advertising ignored by scanner because the directed " "address {} does not match the current device or cannot be " Loading @@ -3014,7 +3032,8 @@ void LinkLayerController::ScanIncomingLeLegacyAdvertisingPdu( return; } should_send_directed_advertising_report = target_address.IsRpa() && !resolved_target_address; target_address.IsRpa() && !ResolveTargetA(target_address, resolved_advertising_address); break; } } Loading Loading @@ -3247,12 +3266,7 @@ void LinkLayerController::ConnectIncomingLeLegacyAdvertisingPdu( static_cast<AddressType>(pdu.GetTargetAddressType())}; AddressWithType resolved_advertising_address = ResolvePrivateAddress(advertising_address, IrkSelection::Peer) .value_or(advertising_address); AddressWithType resolved_target_address = ResolvePrivateAddress(target_address, IrkSelection::Peer) .value_or(target_address); ResolvePrivateAddress(advertising_address).value_or(advertising_address); // Vol 6, Part B § 4.3.5 Initiator filter policy. switch (initiator_.initiator_filter_policy) { Loading Loading @@ -3285,14 +3299,14 @@ void LinkLayerController::ConnectIncomingLeLegacyAdvertisingPdu( // contain Public or Static addresses for the target’s address (TargetA // field). if (directed_advertising) { if (!IsLocalPublicOrRandomAddress(resolved_target_address)) { if (!ValidateTargetA(target_address, resolved_advertising_address)) { DEBUG(id_, "Directed legacy advertising ignored by initiator because the " "target address {} does not match the current device addresses", resolved_advertising_address); target_address); return; } if (resolved_target_address == target_address && if (!target_address.IsRpa() && (initiator_.own_address_type == OwnAddressType::RESOLVABLE_OR_PUBLIC_ADDRESS || initiator_.own_address_type == Loading @@ -3301,7 +3315,7 @@ void LinkLayerController::ConnectIncomingLeLegacyAdvertisingPdu( "Directed legacy advertising ignored by initiator because the " "target address {} is static or public and the initiator is " "configured to use resolvable addresses", resolved_advertising_address); target_address); return; } } Loading Loading @@ -3415,11 +3429,7 @@ void LinkLayerController::ScanIncomingLeExtendedAdvertisingPdu( // address. The scanner’s filter policy shall then determine if the scanner // responds with a scan request. AddressWithType resolved_advertising_address = ResolvePrivateAddress(advertising_address, IrkSelection::Peer) .value_or(advertising_address); std::optional<AddressWithType> resolved_target_address = ResolvePrivateAddress(target_address, IrkSelection::Peer); ResolvePrivateAddress(advertising_address).value_or(advertising_address); if (resolved_advertising_address != advertising_address) { DEBUG(id_, "Resolved the advertising address {} to {}", advertising_address, Loading Loading @@ -3456,8 +3466,7 @@ void LinkLayerController::ScanIncomingLeExtendedAdvertisingPdu( // resolution is enabled, and the address is resolved successfully case bluetooth::hci::LeScanningFilterPolicy::ACCEPT_ALL: case bluetooth::hci::LeScanningFilterPolicy::FILTER_ACCEPT_LIST_ONLY: if (!IsLocalPublicOrRandomAddress(target_address) && !(target_address.IsRpa() && resolved_target_address)) { if (!ValidateTargetA(target_address, resolved_advertising_address)) { DEBUG(id_, "Extended advertising ignored by scanner because the directed " "address {} does not match the current device or cannot be " Loading Loading @@ -3676,12 +3685,7 @@ void LinkLayerController::ConnectIncomingLeExtendedAdvertisingPdu( static_cast<AddressType>(pdu.GetTargetAddressType())}; AddressWithType resolved_advertising_address = ResolvePrivateAddress(advertising_address, IrkSelection::Peer) .value_or(advertising_address); AddressWithType resolved_target_address = ResolvePrivateAddress(target_address, IrkSelection::Peer) .value_or(target_address); ResolvePrivateAddress(advertising_address).value_or(advertising_address); // Vol 6, Part B § 4.3.5 Initiator filter policy. switch (initiator_.initiator_filter_policy) { Loading Loading @@ -3714,14 +3718,14 @@ void LinkLayerController::ConnectIncomingLeExtendedAdvertisingPdu( // contain Public or Static addresses for the target’s address (TargetA // field). if (pdu.GetDirected()) { if (!IsLocalPublicOrRandomAddress(resolved_target_address)) { if (!ValidateTargetA(target_address, resolved_advertising_address)) { DEBUG(id_, "Directed extended advertising ignored by initiator because the " "target address {} does not match the current device addresses", resolved_advertising_address); target_address); return; } if (resolved_target_address == target_address && if (!target_address.IsRpa() && (initiator_.own_address_type == OwnAddressType::RESOLVABLE_OR_PUBLIC_ADDRESS || initiator_.own_address_type == Loading @@ -3730,7 +3734,7 @@ void LinkLayerController::ConnectIncomingLeExtendedAdvertisingPdu( "Directed extended advertising ignored by initiator because the " "target address {} is static or public and the initiator is " "configured to use resolvable addresses", resolved_advertising_address); target_address); return; } } Loading Loading @@ -3837,8 +3841,7 @@ void LinkLayerController::IncomingLePeriodicAdvertisingPdu( // address. The scanner's periodic sync establishment filter policy shall // determine if the scanner processes the advertising packet. AddressWithType resolved_advertiser_address = ResolvePrivateAddress(advertiser_address, IrkSelection::Peer) .value_or(advertiser_address); ResolvePrivateAddress(advertiser_address).value_or(advertiser_address); bluetooth::hci::AdvertiserAddressType advertiser_address_type; switch (resolved_advertiser_address.GetAddressType()) { Loading Loading @@ -4279,16 +4282,7 @@ uint16_t LinkLayerController::HandleLeConnection( AddressType peer_address_type = address.GetAddressType(); if (peer_resolved_address != AddressWithType()) { peer_resolvable_private_address = address.GetAddress(); if (peer_resolved_address.GetAddressType() == AddressType::PUBLIC_DEVICE_ADDRESS) { peer_address_type = AddressType::PUBLIC_IDENTITY_ADDRESS; } else if (peer_resolved_address.GetAddressType() == AddressType::RANDOM_DEVICE_ADDRESS) { peer_address_type = AddressType::RANDOM_IDENTITY_ADDRESS; } else { WARNING(id_, "Unhandled resolved address type {} -> {}", address, peer_resolved_address); } peer_address_type = peer_resolved_address.GetAddressType(); connection_address = peer_resolved_address.GetAddress(); } Address local_resolved_address = own_address.GetAddress(); Loading Loading @@ -4369,8 +4363,7 @@ bool LinkLayerController::ProcessIncomingLegacyConnectRequest( // The advertising filter policy shall then determine if the // advertiser establishes a connection. AddressWithType resolved_initiating_address = ResolvePrivateAddress(initiating_address, IrkSelection::Peer) .value_or(initiating_address); ResolvePrivateAddress(initiating_address).value_or(initiating_address); if (resolved_initiating_address != initiating_address) { DEBUG(id_, "Resolved the initiating address {} to {}", initiating_address, Loading Loading @@ -4481,8 +4474,7 @@ bool LinkLayerController::ProcessIncomingExtendedConnectRequest( // The advertising filter policy shall then determine if the // advertiser establishes a connection. AddressWithType resolved_initiating_address = ResolvePrivateAddress(initiating_address, IrkSelection::Peer) .value_or(initiating_address); ResolvePrivateAddress(initiating_address).value_or(initiating_address); if (resolved_initiating_address != initiating_address) { DEBUG(id_, "Resolved the initiating address {} to {}", initiating_address, Loading Loading @@ -4916,8 +4908,7 @@ void LinkLayerController::IncomingLeScanPacket( // address. The advertising filter policy shall then determine if // the advertiser processes the scan request. AddressWithType resolved_scanning_address = ResolvePrivateAddress(scanning_address, IrkSelection::Peer) .value_or(scanning_address); ResolvePrivateAddress(scanning_address).value_or(scanning_address); if (resolved_scanning_address != scanning_address) { DEBUG(id_, "Resolved the scanning address {} to {}", scanning_address, Loading Loading @@ -4966,8 +4957,7 @@ void LinkLayerController::IncomingLeScanResponsePacket( } AddressWithType resolved_advertising_address = ResolvePrivateAddress(advertising_address, IrkSelection::Peer) .value_or(advertising_address); ResolvePrivateAddress(advertising_address).value_or(advertising_address); if (advertising_address != resolved_advertising_address) { DEBUG(id_, "Resolved the advertising address {} to {}", advertising_address, Loading tools/rootcanal/model/controller/link_layer_controller.h +11 −2 Original line number Diff line number Diff line Loading @@ -229,8 +229,17 @@ class LinkLayerController { // resolve the address using the resolving list. If the address cannot // be resolved none is returned. If the address is not a Resolvable // Private Address, the original address is returned. std::optional<AddressWithType> ResolvePrivateAddress(AddressWithType address, IrkSelection irk); std::optional<AddressWithType> ResolvePrivateAddress(AddressWithType address); // Returns true if the input address resolves with the local IRK // associated with the given peer identity address. bool ResolveTargetA(AddressWithType target_a, AddressWithType adv_a); // Returns true if either: // • TargetA is identical to the device address, or // • TargetA is a resolvable private address, address // resolution is enabled, and the address is resolved successfully bool ValidateTargetA(AddressWithType target_a, AddressWithType adv_a); // Generate a Resolvable Private for the selected peer. // If the address is not found in the resolving list none is returned. Loading tools/rootcanal/test/LL/CON_/INI/BV_08_C.py 0 → 100644 +144 −0 Original line number Diff line number Diff line # Copyright 2023 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # https://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. import hci_packets as hci import link_layer_packets as ll import unittest from hci_packets import ErrorCode from py.bluetooth import Address from py.controller import ControllerTest, generate_rpa class Test(ControllerTest): LL_initiator_scanInterval_MIN = 0x2000 LL_initiator_scanInterval_MAX = 0x2000 LL_initiator_scanWindow_MIN = 0x200 LL_initiator_scanWindow_MAX = 0x200 LL_initiator_Adv_Channel_Map = 0x7 LL_initiator_Channel_Map = 0x7 # LL/CON/INI/BV-08-C [Network Privacy – Connection Establishment responding # to connectable undirected advertising, Initiator] async def test(self): # Test parameters. controller = self.controller local_irk = bytes([1] * 16) peer_address = Address('aa:bb:cc:dd:ee:ff') if not controller.le_features.ll_privacy: self.skipTest("LL privacy not supported") # 1. Configure the Lower Tester to advertise using a valid public or static random address (identity # address). # 2. The Upper Tester adds the Identity Address of the Lower Tester to the Resolving List with all zero # peer IRK, and with a local IRK. controller.send_cmd( hci.LeAddDeviceToResolvingList( peer_irk=bytes([0] * 16), local_irk=local_irk, peer_identity_address=peer_address, peer_identity_address_type=hci.PeerAddressType.PUBLIC_DEVICE_OR_IDENTITY_ADDRESS)) await self.expect_evt( hci.LeAddDeviceToResolvingListComplete(status=ErrorCode.SUCCESS, num_hci_command_packets=1)) controller.send_cmd(hci.LeSetResolvablePrivateAddressTimeout(rpa_timeout=0x10)) await self.expect_evt( hci.LeSetResolvablePrivateAddressTimeoutComplete(status=ErrorCode.SUCCESS, num_hci_command_packets=1)) controller.send_cmd(hci.LeSetAddressResolutionEnable(address_resolution_enable=hci.Enable.ENABLED)) await self.expect_evt( hci.LeSetAddressResolutionEnableComplete(status=ErrorCode.SUCCESS, num_hci_command_packets=1)) # 3. The Upper Tester enables the initiator state in the IUT. controller.send_cmd( hci.LeCreateConnection(le_scan_interval=Test.LL_initiator_scanInterval_MIN, le_scan_window=Test.LL_initiator_scanWindow_MIN, initiator_filter_policy=hci.InitiatorFilterPolicy.USE_PEER_ADDRESS, peer_address_type=hci.AddressType.PUBLIC_DEVICE_ADDRESS, peer_address=peer_address, own_address_type=hci.OwnAddressType.RESOLVABLE_OR_PUBLIC_ADDRESS, connection_interval_min=0x200, connection_interval_max=0x200, max_latency=0x6, supervision_timeout=0xc80, min_ce_length=0, max_ce_length=0)) await self.expect_evt(hci.LeCreateConnectionStatus(status=ErrorCode.SUCCESS, num_hci_command_packets=1)) # 4. Lower Tester sends ADV_IND packets, each advertising event on the selected advertising # channel, using the selected advertising interval. controller.send_ll(ll.LeLegacyAdvertisingPdu(source_address=peer_address, advertising_address_type=ll.AddressType.PUBLIC, advertising_type=ll.LegacyAdvertisingType.ADV_IND, advertising_data=[1, 2, 3]), rssi=-16) # 5. The Lower Tester receives a CONNECT_IND packet T_IFS after any of the ADV_IND packets. # The InitA field contains a resolvable private address from the IUT. connect_ind = await self.expect_ll( ll.LeConnect(source_address=self.Any, destination_address=peer_address, initiating_address_type=ll.AddressType.RANDOM, advertising_address_type=ll.AddressType.PUBLIC, conn_interval=0x200, conn_peripheral_latency=0x6, conn_supervision_timeout=0xc80)) self.assertTrue(connect_ind.source_address.is_resolvable()) self.assertTrue(connect_ind.source_address != controller.address) controller.send_ll( ll.LeConnectComplete(source_address=peer_address, destination_address=connect_ind.source_address, initiating_address_type=ll.AddressType.RANDOM, advertising_address_type=ll.AddressType.PUBLIC, conn_interval=0x200, conn_peripheral_latency=0x6, conn_supervision_timeout=0xc80)) # 6. Upper Tester receives an HCI_LE_Enhanced_Connection_Complete event from the IUT # including the Lower Tester address and connection interval selected. connect_complete = await self.expect_evt( hci.LeEnhancedConnectionComplete(status=ErrorCode.SUCCESS, connection_handle=self.Any, role=hci.Role.CENTRAL, peer_address_type=hci.AddressType.PUBLIC_DEVICE_ADDRESS, peer_address=peer_address, connection_interval=0x200, peripheral_latency=0x6, supervision_timeout=0xc80, local_resolvable_private_address=connect_ind.source_address, central_clock_accuracy=hci.ClockAccuracy.PPM_500)) # 7. After the CONNECT_IND has been received, the Lower Tester receives the first correctly # formatted LL Data Channel PDU on the data channel. # 8. The Lower Tester sends a correctly formatted LL Data Channel PDU to the IUT on the same data # channel using the acknowledgement scheme. controller.send_ll( ll.Disconnect(source_address=peer_address, destination_address=connect_ind.source_address, reason=hci.ErrorCode.REMOTE_USER_TERMINATED_CONNECTION)) await self.expect_evt( hci.DisconnectionComplete(status=hci.ErrorCode.SUCCESS, connection_handle=connect_complete.connection_handle, reason=hci.ErrorCode.REMOTE_USER_TERMINATED_CONNECTION)) tools/rootcanal/test/LL/CON_/INI/BV_09_C.py 0 → 100644 +179 −0 File added.Preview size limit exceeded, changes collapsed. Show changes Loading
tools/rootcanal/Android.bp +1 −0 Original line number Diff line number Diff line Loading @@ -309,6 +309,7 @@ python_test_host { "test/LL/CIS/CEN/*.py", "test/LL/CIS/PER/*.py", "test/LL/CON_/CEN/*.py", "test/LL/CON_/INI/*.py", "test/LL/CON_/PER/*.py", "test/LL/DDI/ADV/*.py", "test/LL/DDI/SCN/*.py", Loading
tools/rootcanal/model/controller/link_layer_controller.cc +55 −65 Original line number Diff line number Diff line Loading @@ -209,7 +209,7 @@ bool LinkLayerController::ResolvingListBusy() { } std::optional<AddressWithType> LinkLayerController::ResolvePrivateAddress( AddressWithType address, IrkSelection irk) { AddressWithType address) { if (!address.IsRpa()) { return address; } Loading @@ -219,17 +219,12 @@ std::optional<AddressWithType> LinkLayerController::ResolvePrivateAddress( } for (auto& entry : le_resolving_list_) { std::array<uint8_t, LinkLayerController::kIrkSize> const& used_irk = irk == IrkSelection::Local ? entry.local_irk : entry.peer_irk; if (address.IsRpaThatMatchesIrk(used_irk)) { if (address.IsRpaThatMatchesIrk(entry.peer_irk)) { // Update the peer resolvable address used for the peer // with the returned identity address. if (irk == IrkSelection::Peer) { entry.peer_resolvable_address = address.GetAddress(); } return PeerIdentityAddress(entry.peer_identity_address, return PeerDeviceAddress(entry.peer_identity_address, entry.peer_identity_address_type); } } Loading @@ -237,6 +232,34 @@ std::optional<AddressWithType> LinkLayerController::ResolvePrivateAddress( return {}; } bool LinkLayerController::ResolveTargetA(AddressWithType target_a, AddressWithType adv_a) { if (!le_resolving_list_enabled_) { return false; } for (auto const& entry : le_resolving_list_) { if (adv_a == PeerDeviceAddress(entry.peer_identity_address, entry.peer_identity_address_type) && target_a.IsRpaThatMatchesIrk(entry.local_irk)) { return true; } } return false; } bool LinkLayerController::ValidateTargetA(AddressWithType target_a, AddressWithType adv_a) { if (IsLocalPublicOrRandomAddress(target_a)) { return true; } if (target_a.IsRpa()) { return ResolveTargetA(target_a, adv_a); } return false; } std::optional<AddressWithType> LinkLayerController::GenerateResolvablePrivateAddress(AddressWithType address, IrkSelection irk) { Loading Loading @@ -2940,11 +2963,7 @@ void LinkLayerController::ScanIncomingLeLegacyAdvertisingPdu( // address. The scanner’s filter policy shall then determine if the scanner // responds with a scan request. AddressWithType resolved_advertising_address = ResolvePrivateAddress(advertising_address, IrkSelection::Peer) .value_or(advertising_address); std::optional<AddressWithType> resolved_target_address = ResolvePrivateAddress(target_address, IrkSelection::Peer); ResolvePrivateAddress(advertising_address).value_or(advertising_address); if (resolved_advertising_address != advertising_address) { DEBUG(id_, "Resolved the advertising address {} to {}", advertising_address, Loading Loading @@ -2987,8 +3006,7 @@ void LinkLayerController::ScanIncomingLeLegacyAdvertisingPdu( // resolution is enabled, and the address is resolved successfully case bluetooth::hci::LeScanningFilterPolicy::ACCEPT_ALL: case bluetooth::hci::LeScanningFilterPolicy::FILTER_ACCEPT_LIST_ONLY: if (!IsLocalPublicOrRandomAddress(target_address) && !(target_address.IsRpa() && resolved_target_address)) { if (!ValidateTargetA(target_address, resolved_advertising_address)) { DEBUG(id_, "Legacy advertising ignored by scanner because the directed " "address {} does not match the current device or cannot be " Loading @@ -3014,7 +3032,8 @@ void LinkLayerController::ScanIncomingLeLegacyAdvertisingPdu( return; } should_send_directed_advertising_report = target_address.IsRpa() && !resolved_target_address; target_address.IsRpa() && !ResolveTargetA(target_address, resolved_advertising_address); break; } } Loading Loading @@ -3247,12 +3266,7 @@ void LinkLayerController::ConnectIncomingLeLegacyAdvertisingPdu( static_cast<AddressType>(pdu.GetTargetAddressType())}; AddressWithType resolved_advertising_address = ResolvePrivateAddress(advertising_address, IrkSelection::Peer) .value_or(advertising_address); AddressWithType resolved_target_address = ResolvePrivateAddress(target_address, IrkSelection::Peer) .value_or(target_address); ResolvePrivateAddress(advertising_address).value_or(advertising_address); // Vol 6, Part B § 4.3.5 Initiator filter policy. switch (initiator_.initiator_filter_policy) { Loading Loading @@ -3285,14 +3299,14 @@ void LinkLayerController::ConnectIncomingLeLegacyAdvertisingPdu( // contain Public or Static addresses for the target’s address (TargetA // field). if (directed_advertising) { if (!IsLocalPublicOrRandomAddress(resolved_target_address)) { if (!ValidateTargetA(target_address, resolved_advertising_address)) { DEBUG(id_, "Directed legacy advertising ignored by initiator because the " "target address {} does not match the current device addresses", resolved_advertising_address); target_address); return; } if (resolved_target_address == target_address && if (!target_address.IsRpa() && (initiator_.own_address_type == OwnAddressType::RESOLVABLE_OR_PUBLIC_ADDRESS || initiator_.own_address_type == Loading @@ -3301,7 +3315,7 @@ void LinkLayerController::ConnectIncomingLeLegacyAdvertisingPdu( "Directed legacy advertising ignored by initiator because the " "target address {} is static or public and the initiator is " "configured to use resolvable addresses", resolved_advertising_address); target_address); return; } } Loading Loading @@ -3415,11 +3429,7 @@ void LinkLayerController::ScanIncomingLeExtendedAdvertisingPdu( // address. The scanner’s filter policy shall then determine if the scanner // responds with a scan request. AddressWithType resolved_advertising_address = ResolvePrivateAddress(advertising_address, IrkSelection::Peer) .value_or(advertising_address); std::optional<AddressWithType> resolved_target_address = ResolvePrivateAddress(target_address, IrkSelection::Peer); ResolvePrivateAddress(advertising_address).value_or(advertising_address); if (resolved_advertising_address != advertising_address) { DEBUG(id_, "Resolved the advertising address {} to {}", advertising_address, Loading Loading @@ -3456,8 +3466,7 @@ void LinkLayerController::ScanIncomingLeExtendedAdvertisingPdu( // resolution is enabled, and the address is resolved successfully case bluetooth::hci::LeScanningFilterPolicy::ACCEPT_ALL: case bluetooth::hci::LeScanningFilterPolicy::FILTER_ACCEPT_LIST_ONLY: if (!IsLocalPublicOrRandomAddress(target_address) && !(target_address.IsRpa() && resolved_target_address)) { if (!ValidateTargetA(target_address, resolved_advertising_address)) { DEBUG(id_, "Extended advertising ignored by scanner because the directed " "address {} does not match the current device or cannot be " Loading Loading @@ -3676,12 +3685,7 @@ void LinkLayerController::ConnectIncomingLeExtendedAdvertisingPdu( static_cast<AddressType>(pdu.GetTargetAddressType())}; AddressWithType resolved_advertising_address = ResolvePrivateAddress(advertising_address, IrkSelection::Peer) .value_or(advertising_address); AddressWithType resolved_target_address = ResolvePrivateAddress(target_address, IrkSelection::Peer) .value_or(target_address); ResolvePrivateAddress(advertising_address).value_or(advertising_address); // Vol 6, Part B § 4.3.5 Initiator filter policy. switch (initiator_.initiator_filter_policy) { Loading Loading @@ -3714,14 +3718,14 @@ void LinkLayerController::ConnectIncomingLeExtendedAdvertisingPdu( // contain Public or Static addresses for the target’s address (TargetA // field). if (pdu.GetDirected()) { if (!IsLocalPublicOrRandomAddress(resolved_target_address)) { if (!ValidateTargetA(target_address, resolved_advertising_address)) { DEBUG(id_, "Directed extended advertising ignored by initiator because the " "target address {} does not match the current device addresses", resolved_advertising_address); target_address); return; } if (resolved_target_address == target_address && if (!target_address.IsRpa() && (initiator_.own_address_type == OwnAddressType::RESOLVABLE_OR_PUBLIC_ADDRESS || initiator_.own_address_type == Loading @@ -3730,7 +3734,7 @@ void LinkLayerController::ConnectIncomingLeExtendedAdvertisingPdu( "Directed extended advertising ignored by initiator because the " "target address {} is static or public and the initiator is " "configured to use resolvable addresses", resolved_advertising_address); target_address); return; } } Loading Loading @@ -3837,8 +3841,7 @@ void LinkLayerController::IncomingLePeriodicAdvertisingPdu( // address. The scanner's periodic sync establishment filter policy shall // determine if the scanner processes the advertising packet. AddressWithType resolved_advertiser_address = ResolvePrivateAddress(advertiser_address, IrkSelection::Peer) .value_or(advertiser_address); ResolvePrivateAddress(advertiser_address).value_or(advertiser_address); bluetooth::hci::AdvertiserAddressType advertiser_address_type; switch (resolved_advertiser_address.GetAddressType()) { Loading Loading @@ -4279,16 +4282,7 @@ uint16_t LinkLayerController::HandleLeConnection( AddressType peer_address_type = address.GetAddressType(); if (peer_resolved_address != AddressWithType()) { peer_resolvable_private_address = address.GetAddress(); if (peer_resolved_address.GetAddressType() == AddressType::PUBLIC_DEVICE_ADDRESS) { peer_address_type = AddressType::PUBLIC_IDENTITY_ADDRESS; } else if (peer_resolved_address.GetAddressType() == AddressType::RANDOM_DEVICE_ADDRESS) { peer_address_type = AddressType::RANDOM_IDENTITY_ADDRESS; } else { WARNING(id_, "Unhandled resolved address type {} -> {}", address, peer_resolved_address); } peer_address_type = peer_resolved_address.GetAddressType(); connection_address = peer_resolved_address.GetAddress(); } Address local_resolved_address = own_address.GetAddress(); Loading Loading @@ -4369,8 +4363,7 @@ bool LinkLayerController::ProcessIncomingLegacyConnectRequest( // The advertising filter policy shall then determine if the // advertiser establishes a connection. AddressWithType resolved_initiating_address = ResolvePrivateAddress(initiating_address, IrkSelection::Peer) .value_or(initiating_address); ResolvePrivateAddress(initiating_address).value_or(initiating_address); if (resolved_initiating_address != initiating_address) { DEBUG(id_, "Resolved the initiating address {} to {}", initiating_address, Loading Loading @@ -4481,8 +4474,7 @@ bool LinkLayerController::ProcessIncomingExtendedConnectRequest( // The advertising filter policy shall then determine if the // advertiser establishes a connection. AddressWithType resolved_initiating_address = ResolvePrivateAddress(initiating_address, IrkSelection::Peer) .value_or(initiating_address); ResolvePrivateAddress(initiating_address).value_or(initiating_address); if (resolved_initiating_address != initiating_address) { DEBUG(id_, "Resolved the initiating address {} to {}", initiating_address, Loading Loading @@ -4916,8 +4908,7 @@ void LinkLayerController::IncomingLeScanPacket( // address. The advertising filter policy shall then determine if // the advertiser processes the scan request. AddressWithType resolved_scanning_address = ResolvePrivateAddress(scanning_address, IrkSelection::Peer) .value_or(scanning_address); ResolvePrivateAddress(scanning_address).value_or(scanning_address); if (resolved_scanning_address != scanning_address) { DEBUG(id_, "Resolved the scanning address {} to {}", scanning_address, Loading Loading @@ -4966,8 +4957,7 @@ void LinkLayerController::IncomingLeScanResponsePacket( } AddressWithType resolved_advertising_address = ResolvePrivateAddress(advertising_address, IrkSelection::Peer) .value_or(advertising_address); ResolvePrivateAddress(advertising_address).value_or(advertising_address); if (advertising_address != resolved_advertising_address) { DEBUG(id_, "Resolved the advertising address {} to {}", advertising_address, Loading
tools/rootcanal/model/controller/link_layer_controller.h +11 −2 Original line number Diff line number Diff line Loading @@ -229,8 +229,17 @@ class LinkLayerController { // resolve the address using the resolving list. If the address cannot // be resolved none is returned. If the address is not a Resolvable // Private Address, the original address is returned. std::optional<AddressWithType> ResolvePrivateAddress(AddressWithType address, IrkSelection irk); std::optional<AddressWithType> ResolvePrivateAddress(AddressWithType address); // Returns true if the input address resolves with the local IRK // associated with the given peer identity address. bool ResolveTargetA(AddressWithType target_a, AddressWithType adv_a); // Returns true if either: // • TargetA is identical to the device address, or // • TargetA is a resolvable private address, address // resolution is enabled, and the address is resolved successfully bool ValidateTargetA(AddressWithType target_a, AddressWithType adv_a); // Generate a Resolvable Private for the selected peer. // If the address is not found in the resolving list none is returned. Loading
tools/rootcanal/test/LL/CON_/INI/BV_08_C.py 0 → 100644 +144 −0 Original line number Diff line number Diff line # Copyright 2023 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # https://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. import hci_packets as hci import link_layer_packets as ll import unittest from hci_packets import ErrorCode from py.bluetooth import Address from py.controller import ControllerTest, generate_rpa class Test(ControllerTest): LL_initiator_scanInterval_MIN = 0x2000 LL_initiator_scanInterval_MAX = 0x2000 LL_initiator_scanWindow_MIN = 0x200 LL_initiator_scanWindow_MAX = 0x200 LL_initiator_Adv_Channel_Map = 0x7 LL_initiator_Channel_Map = 0x7 # LL/CON/INI/BV-08-C [Network Privacy – Connection Establishment responding # to connectable undirected advertising, Initiator] async def test(self): # Test parameters. controller = self.controller local_irk = bytes([1] * 16) peer_address = Address('aa:bb:cc:dd:ee:ff') if not controller.le_features.ll_privacy: self.skipTest("LL privacy not supported") # 1. Configure the Lower Tester to advertise using a valid public or static random address (identity # address). # 2. The Upper Tester adds the Identity Address of the Lower Tester to the Resolving List with all zero # peer IRK, and with a local IRK. controller.send_cmd( hci.LeAddDeviceToResolvingList( peer_irk=bytes([0] * 16), local_irk=local_irk, peer_identity_address=peer_address, peer_identity_address_type=hci.PeerAddressType.PUBLIC_DEVICE_OR_IDENTITY_ADDRESS)) await self.expect_evt( hci.LeAddDeviceToResolvingListComplete(status=ErrorCode.SUCCESS, num_hci_command_packets=1)) controller.send_cmd(hci.LeSetResolvablePrivateAddressTimeout(rpa_timeout=0x10)) await self.expect_evt( hci.LeSetResolvablePrivateAddressTimeoutComplete(status=ErrorCode.SUCCESS, num_hci_command_packets=1)) controller.send_cmd(hci.LeSetAddressResolutionEnable(address_resolution_enable=hci.Enable.ENABLED)) await self.expect_evt( hci.LeSetAddressResolutionEnableComplete(status=ErrorCode.SUCCESS, num_hci_command_packets=1)) # 3. The Upper Tester enables the initiator state in the IUT. controller.send_cmd( hci.LeCreateConnection(le_scan_interval=Test.LL_initiator_scanInterval_MIN, le_scan_window=Test.LL_initiator_scanWindow_MIN, initiator_filter_policy=hci.InitiatorFilterPolicy.USE_PEER_ADDRESS, peer_address_type=hci.AddressType.PUBLIC_DEVICE_ADDRESS, peer_address=peer_address, own_address_type=hci.OwnAddressType.RESOLVABLE_OR_PUBLIC_ADDRESS, connection_interval_min=0x200, connection_interval_max=0x200, max_latency=0x6, supervision_timeout=0xc80, min_ce_length=0, max_ce_length=0)) await self.expect_evt(hci.LeCreateConnectionStatus(status=ErrorCode.SUCCESS, num_hci_command_packets=1)) # 4. Lower Tester sends ADV_IND packets, each advertising event on the selected advertising # channel, using the selected advertising interval. controller.send_ll(ll.LeLegacyAdvertisingPdu(source_address=peer_address, advertising_address_type=ll.AddressType.PUBLIC, advertising_type=ll.LegacyAdvertisingType.ADV_IND, advertising_data=[1, 2, 3]), rssi=-16) # 5. The Lower Tester receives a CONNECT_IND packet T_IFS after any of the ADV_IND packets. # The InitA field contains a resolvable private address from the IUT. connect_ind = await self.expect_ll( ll.LeConnect(source_address=self.Any, destination_address=peer_address, initiating_address_type=ll.AddressType.RANDOM, advertising_address_type=ll.AddressType.PUBLIC, conn_interval=0x200, conn_peripheral_latency=0x6, conn_supervision_timeout=0xc80)) self.assertTrue(connect_ind.source_address.is_resolvable()) self.assertTrue(connect_ind.source_address != controller.address) controller.send_ll( ll.LeConnectComplete(source_address=peer_address, destination_address=connect_ind.source_address, initiating_address_type=ll.AddressType.RANDOM, advertising_address_type=ll.AddressType.PUBLIC, conn_interval=0x200, conn_peripheral_latency=0x6, conn_supervision_timeout=0xc80)) # 6. Upper Tester receives an HCI_LE_Enhanced_Connection_Complete event from the IUT # including the Lower Tester address and connection interval selected. connect_complete = await self.expect_evt( hci.LeEnhancedConnectionComplete(status=ErrorCode.SUCCESS, connection_handle=self.Any, role=hci.Role.CENTRAL, peer_address_type=hci.AddressType.PUBLIC_DEVICE_ADDRESS, peer_address=peer_address, connection_interval=0x200, peripheral_latency=0x6, supervision_timeout=0xc80, local_resolvable_private_address=connect_ind.source_address, central_clock_accuracy=hci.ClockAccuracy.PPM_500)) # 7. After the CONNECT_IND has been received, the Lower Tester receives the first correctly # formatted LL Data Channel PDU on the data channel. # 8. The Lower Tester sends a correctly formatted LL Data Channel PDU to the IUT on the same data # channel using the acknowledgement scheme. controller.send_ll( ll.Disconnect(source_address=peer_address, destination_address=connect_ind.source_address, reason=hci.ErrorCode.REMOTE_USER_TERMINATED_CONNECTION)) await self.expect_evt( hci.DisconnectionComplete(status=hci.ErrorCode.SUCCESS, connection_handle=connect_complete.connection_handle, reason=hci.ErrorCode.REMOTE_USER_TERMINATED_CONNECTION))
tools/rootcanal/test/LL/CON_/INI/BV_09_C.py 0 → 100644 +179 −0 File added.Preview size limit exceeded, changes collapsed. Show changes