1# Copyright 2023 Google LLC
2#
3# Licensed under the Apache License, Version 2.0 (the "License");
4# you may not use this file except in compliance with the License.
5# You may obtain a copy of the License at
6#
7#     https://www.apache.org/licenses/LICENSE-2.0
8#
9# Unless required by applicable law or agreed to in writing, software
10# distributed under the License is distributed on an "AS IS" BASIS,
11# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12# See the License for the specific language governing permissions and
13# limitations under the License.
14
15import asyncio
16import hci_packets as hci
17import link_layer_packets as ll
18import math
19import random
20import unittest
21from dataclasses import dataclass
22from hci_packets import ErrorCode, FragmentPreference
23from py.bluetooth import Address
24from py.controller import ControllerTest, generate_rpa
25from typing import List
26
27
28@dataclass
29class TestRound:
30    data_length: int
31
32
33class Test(ControllerTest):
34    # Test parameters.
35    LL_advertiser_advInterval_MIN = 0x800
36    LL_advertiser_advInterval_MAX = 0x800
37    LL_advertiser_Adv_Channel_Map = 0x7
38    LL_initiator_connInterval = 0x200
39    LL_initiator_connPeripheralLatency = 0x200
40    LL_initiator_connSupervisionTimeout = 0x200
41
42    # LL/SEC/ADV/BV-11-C [Network Privacy - Directed Connectable Advertising
43    # using local and remote IRK]
44    #
45    # Verify that the IUT, when transmitting directed connectable advertising
46    # events, is using resolvable private addresses for AdvA and InitA fields
47    # when the Lower Tester has distributed its own IRK.
48    #
49    # Verify that when address resolution is disabled on the IUT, the Lower
50    # Tester resolvable private address is not resolved, and therefore a
51    # connection is not established.
52    async def test(self):
53        controller = self.controller
54        local_irk = bytes([1] * 16)
55        peer_irk = bytes([2] * 16)
56        random_irk = bytes([3] * 16)
57        peer_address = Address('aa:bb:cc:dd:ee:ff')
58
59        # 1. The Lower Tester adds the Device Identity of the IUT to its resolving list.
60        # 2. Configure the Lower Tester to initiate a connection while using a resolvable private address.
61
62        # 3. The Upper Tester populates the resolving list with the device identity of the Lower Tester
63        # connected with the local device identity. The IUT use these when generating resolvable private
64        # addresses for use in the advertising packet’s AdvA and InitA fields.
65        controller.send_cmd(
66            hci.LeAddDeviceToResolvingList(
67                peer_irk=peer_irk,
68                local_irk=local_irk,
69                peer_identity_address=peer_address,
70                peer_identity_address_type=hci.PeerAddressType.PUBLIC_DEVICE_OR_IDENTITY_ADDRESS))
71
72        await self.expect_evt(
73            hci.LeAddDeviceToResolvingListComplete(status=ErrorCode.SUCCESS, num_hci_command_packets=1))
74
75        controller.send_cmd(hci.LeSetResolvablePrivateAddressTimeout(rpa_timeout=0x10))
76
77        await self.expect_evt(
78            hci.LeSetResolvablePrivateAddressTimeoutComplete(status=ErrorCode.SUCCESS, num_hci_command_packets=1))
79
80        # 4. The Upper Tester enables resolving list and directed connectable advertising in the IUT.
81        controller.send_cmd(
82            hci.LeSetAdvertisingParameters(advertising_interval_min=Test.LL_advertiser_advInterval_MIN,
83                                           advertising_interval_max=Test.LL_advertiser_advInterval_MAX,
84                                           advertising_type=hci.AdvertisingType.ADV_DIRECT_IND_HIGH,
85                                           own_address_type=hci.OwnAddressType.RESOLVABLE_OR_PUBLIC_ADDRESS,
86                                           peer_address=peer_address,
87                                           peer_address_type=hci.PeerAddressType.PUBLIC_DEVICE_OR_IDENTITY_ADDRESS,
88                                           advertising_channel_map=0x7,
89                                           advertising_filter_policy=hci.AdvertisingFilterPolicy.ALL_DEVICES))
90
91        await self.expect_evt(
92            hci.LeSetAdvertisingParametersComplete(status=ErrorCode.SUCCESS, num_hci_command_packets=1))
93
94        controller.send_cmd(hci.LeSetAdvertisingData())
95
96        await self.expect_evt(hci.LeSetAdvertisingDataComplete(status=ErrorCode.SUCCESS, num_hci_command_packets=1))
97
98        controller.send_cmd(hci.LeSetAddressResolutionEnable(address_resolution_enable=hci.Enable.ENABLED))
99
100        await self.expect_evt(
101            hci.LeSetAddressResolutionEnableComplete(status=ErrorCode.SUCCESS, num_hci_command_packets=1))
102
103        controller.send_cmd(hci.LeSetAdvertisingEnable(advertising_enable=True))
104
105        await self.expect_evt(hci.LeSetAdvertisingEnableComplete(status=ErrorCode.SUCCESS, num_hci_command_packets=1))
106
107        # 5. The Lower Tester expects the IUT to send ADV_DIRECT_IND packets on an applicable
108        # advertising channel.
109        direct_ind = await self.expect_ll(ll.LeLegacyAdvertisingPdu(
110            source_address=self.Any,
111            destination_address=self.Any,
112            advertising_address_type=ll.AddressType.RANDOM,
113            target_address_type=ll.AddressType.RANDOM,
114            advertising_type=ll.LegacyAdvertisingType.ADV_DIRECT_IND,
115            advertising_data=[]),
116                                          timeout=5)
117
118        self.assertTrue(direct_ind.source_address.is_resolvable())
119        self.assertTrue(direct_ind.destination_address.is_resolvable())
120
121        # 6. The Lower Tester identifies the IUT. The Lower Tester sends a CONNECT_IND with the AdvA
122        # address of the ADV_DIRECT_IND and the InitA generated based on its Device Identity. The IUT
123        # verifies AdvA and resolves the InitA Address and identifies the Lower Tester.
124        # 7. The Lower Tester connects to the IUT. The Lower Tester sends empty LL DATA packets starting
125        # with the first event one connection interval after the connection request using the common data
126        # channel selection parameters.
127        init_a = generate_rpa(peer_irk)
128        controller.send_ll(
129            ll.LeConnect(source_address=init_a,
130                         destination_address=direct_ind.source_address,
131                         initiating_address_type=ll.AddressType.RANDOM,
132                         advertising_address_type=ll.AddressType.RANDOM,
133                         conn_interval=Test.LL_initiator_connInterval,
134                         conn_peripheral_latency=0x6,
135                         conn_supervision_timeout=0xc80))
136
137        await self.expect_ll(
138            ll.LeConnectComplete(source_address=direct_ind.source_address,
139                                 destination_address=init_a,
140                                 initiating_address_type=ll.AddressType.RANDOM,
141                                 advertising_address_type=ll.AddressType.RANDOM,
142                                 conn_interval=Test.LL_initiator_connInterval,
143                                 conn_peripheral_latency=0x6,
144                                 conn_supervision_timeout=0xc80))
145
146        connection_complete_evt = await self.expect_evt(
147            hci.LeEnhancedConnectionCompleteV1(
148                status=hci.ErrorCode.SUCCESS,
149                connection_handle=self.Any,
150                role=hci.Role.PERIPHERAL,
151                peer_address_type=hci.AddressType.PUBLIC_DEVICE_ADDRESS,
152                peer_address=peer_address,
153                local_resolvable_private_address=direct_ind.source_address,
154                peer_resolvable_private_address=init_a,
155                connection_interval=0x200,
156                peripheral_latency=0x6,
157                supervision_timeout=0xc80,
158                central_clock_accuracy=hci.ClockAccuracy.PPM_500,
159            ))
160
161        # 8. The Upper Tester terminates the connection.
162        controller.send_cmd(
163            hci.Disconnect(connection_handle=connection_complete_evt.connection_handle,
164                           reason=hci.DisconnectReason.REMOTE_USER_TERMINATED_CONNECTION))
165
166        await self.expect_evt(hci.DisconnectStatus(status=ErrorCode.SUCCESS, num_hci_command_packets=1))
167
168        await self.expect_ll(
169            ll.Disconnect(source_address=direct_ind.source_address,
170                          destination_address=init_a,
171                          reason=hci.DisconnectReason.REMOTE_USER_TERMINATED_CONNECTION))
172
173        await self.expect_evt(
174            hci.DisconnectionComplete(status=ErrorCode.SUCCESS,
175                                      connection_handle=connection_complete_evt.connection_handle,
176                                      reason=ErrorCode.CONNECTION_TERMINATED_BY_LOCAL_HOST))
177
178        # 9. The Upper Tester disables address resolution in the IUT.
179        controller.send_cmd(hci.LeSetAddressResolutionEnable(address_resolution_enable=hci.Enable.DISABLED))
180
181        await self.expect_evt(
182            hci.LeSetAddressResolutionEnableComplete(status=ErrorCode.SUCCESS, num_hci_command_packets=1))
183
184        # 10. Repeat steps 11–14 at least 20 times.
185
186        # 11. The Upper Tester enables directed connectable advertising in the IUT.
187        controller.send_cmd(hci.LeSetAdvertisingEnable(advertising_enable=True))
188
189        await self.expect_evt(hci.LeSetAdvertisingEnableComplete(status=ErrorCode.SUCCESS, num_hci_command_packets=1))
190
191        # 12. The Lower Tester expects the IUT to send ADV_DIRECT_IND packets on an applicable
192        # advertising channel. The Lower Tester resolves the AdvA address and identifies the IUT.
193        direct_ind = await self.expect_ll(ll.LeLegacyAdvertisingPdu(
194            source_address=self.Any,
195            destination_address=self.Any,
196            advertising_address_type=ll.AddressType.RANDOM,
197            target_address_type=ll.AddressType.RANDOM,
198            advertising_type=ll.LegacyAdvertisingType.ADV_DIRECT_IND,
199            advertising_data=[]),
200                                          timeout=5)
201
202        self.assertTrue(direct_ind.source_address.is_resolvable())
203        self.assertTrue(direct_ind.destination_address.is_resolvable())
204
205        # 13. The Lower Tester sends a CONNECT_IND with the AdvA address of the ADV_IND and the InitA
206        # set to a different address than the last CONNECT_IND. The IUT does not resolve the address in
207        # the InitA field. No connection event is sent to the Upper Tester.
208        init_a = generate_rpa(local_irk)
209        controller.send_ll(
210            ll.LeConnect(source_address=init_a,
211                         destination_address=direct_ind.source_address,
212                         initiating_address_type=ll.AddressType.RANDOM,
213                         advertising_address_type=ll.AddressType.RANDOM,
214                         conn_interval=0x200,
215                         conn_peripheral_latency=0x6,
216                         conn_supervision_timeout=0xc80))
217
218        # 14. The Upper Tester receives an HCI_LE_Connection_Complete event or an
219        # HCI_LE_Enhanced_Connection_Complete event with the Status code set to Advertising Timeout
220        # (0x3C).
221        await self.expect_evt(hci.LeConnectionComplete(status=hci.ErrorCode.ADVERTISING_TIMEOUT,))
222
223        # Empty the LL queue.
224        controller.ll_queue.clear()
225