1 // Copyright 2023 The Pigweed Authors
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License"); you may not
4 // use this file except in compliance with the License. You may obtain a copy of
5 // 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, WITHOUT
11 // WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
12 // License for the specific language governing permissions and limitations under
13 // the License.
14 
15 #pragma once
16 #include <optional>
17 #include <queue>
18 
19 #include "pw_bluetooth_sapphire/internal/host/common/device_address.h"
20 #include "pw_bluetooth_sapphire/internal/host/common/macros.h"
21 #include "pw_bluetooth_sapphire/internal/host/common/smart_task.h"
22 #include "pw_bluetooth_sapphire/internal/host/common/uint128.h"
23 #include "pw_bluetooth_sapphire/internal/host/hci/local_address_delegate.h"
24 #include "pw_bluetooth_sapphire/internal/host/transport/command_channel.h"
25 #include "pw_bluetooth_sapphire/internal/host/transport/error.h"
26 
27 namespace bt {
28 
29 namespace gap {
30 
31 // Manages the local LE device address used in scan, legacy advertising, and
32 // connection initiation procedures. The primary purpose of this class is to
33 // defer updating the random device address if we believe that doing so is
34 // disallowed by the controller. This is the case when scanning or legacy
35 // advertising is enabled, according to the Core Spec v5.3, Vol 4, Part E,
36 // 7.8.4.
37 //
38 // Procedures that need to know the value of the local address (both connection
39 // and advertising procedures need to assign this to any resultant
40 // hci::Connection object for SMP pairing to function correctly) should call the
41 // EnsureLocalAddress() method to obtain it and to lazily refresh the address
42 // if required.
43 //
44 // The type and value of the local address depends on whether or not the privacy
45 // feature is in use. The potential states are as follows:
46 //
47 //   * When privacy is DISABLED, the local address type and its value match
48 //     the public device address that this object gets initialized with.
49 //
50 //   * When privacy is ENABLED, the exact type and value depends on the state of
51 //     link layer procedures at that time. The "HCI LE Set Random Address"
52 //     command is used to assign the controller a random address, which it will
53 //     use for the next active scan, legacy advertising, or initiation command
54 //     with a random address type. A new local random address will be generated
55 //     at a regular interval (see kPrivateAddressTimeout in gap.h).
56 //
57 //     According to Vol 2, Part E, 7.8.4 the "HCI LE Set Random Address"
58 //     command is disallowed when scanning or legacy advertising are enabled.
59 //     Before any one of these procedures gets started, the EnsureLocalAddress()
60 //     method should be called to update the random address if it is allowed by
61 //     the controller (and the address needs a refresh). This function
62 //     asynchronously returns the device address that should be used by the
63 //     procedure.
64 //
65 // The state requested by EnablePrivacy() (enabled or disabled) may not take
66 // effect immediately if a scan, advertising, or connection procedure is in
67 // progress. The requested address type (public or private) will apply
68 // eventually when the controller allows it.
69 class LowEnergyAddressManager final : public hci::LocalAddressDelegate {
70  public:
71   // Function called when privacy is in use to determine if it is allowed to
72   // assign a new random address to the controller. This must return false if
73   // if scan, legacy advertising, and/or initiation procedures are in progress.
74   using StateQueryDelegate = fit::function<bool()>;
75 
76   LowEnergyAddressManager(const DeviceAddress& public_address,
77                           StateQueryDelegate delegate,
78                           hci::CommandChannel::WeakPtr cmd_channel,
79                           pw::async::Dispatcher& dispatcher);
80   ~LowEnergyAddressManager();
81 
82   // Assigns the IRK to generate a RPA for the next address refresh when privacy
83   // is enabled.
set_irk(const std::optional<UInt128> & irk)84   void set_irk(const std::optional<UInt128>& irk) { irk_ = irk; }
85 
86   // Enable or disable the privacy feature. When enabled, the controller will be
87   // configured to use a new random address if it is currently allowed to do so.
88   // If setting the random address is not allowed the update will be deferred
89   // until the the next successful attempt triggered by a call to
90   // TryRefreshRandomAddress().
91   //
92   // If an IRK has been assigned and |enabled| is true, then the generated
93   // random addresses will each be a Resolvable Private Address that can be
94   // resolved with the IRK. Otherwise, Non-resolvable Private Addresses will be
95   // used.
96   void EnablePrivacy(bool enabled);
97 
98   // Returns true if the privacy feature is currently enabled.
PrivacyEnabled()99   bool PrivacyEnabled() const { return privacy_enabled_; }
100 
101   // LocalAddressDelegate overrides:
irk()102   std::optional<UInt128> irk() const override { return irk_; }
identity_address()103   DeviceAddress identity_address() const override { return public_; }
104   void EnsureLocalAddress(std::optional<DeviceAddress::Type> address_type,
105                           AddressCallback callback) override;
106 
107   // Assign a callback to be notified any time the LE address changes.
register_address_changed_callback(AddressCallback callback)108   void register_address_changed_callback(AddressCallback callback) {
109     address_changed_callbacks_.emplace_back(std::move(callback));
110   }
111 
112   // Return the current address.
current_address()113   const DeviceAddress current_address() const {
114     return (privacy_enabled_ && random_) ? *random_ : public_;
115   }
116 
public_address()117   const DeviceAddress public_address() const { return public_; }
118 
119  private:
120   // Attempt to reconfigure the current random device address.
121   void TryRefreshRandomAddress();
122 
123   // Clears all privacy related state such that the random address will not be
124   // refreshed until privacy is re-enabled. |random_| is not modified and
125   // continues to reflect the most recently configured random address.
126   void CleanUpPrivacyState();
127 
128   void CancelExpiry();
129   bool CanUpdateRandomAddress() const;
130   void ResolveAddressRequests();
131 
132   // Notifies all address changed listeners of the change in device address.
133   void NotifyAddressUpdate();
134 
135   pw::async::Dispatcher& dispatcher_;
136 
137   StateQueryDelegate delegate_;
138   hci::CommandChannel::WeakPtr cmd_;
139   bool privacy_enabled_;
140 
141   // The public device address (i.e. BD_ADDR) that is assigned to the
142   // controller.
143   const DeviceAddress public_;
144 
145   // The random device address assigned to the controller by the most recent
146   // successful HCI_LE_Set_Random_Address command. std::nullopt if the command
147   // was never run successfully.
148   std::optional<DeviceAddress> random_;
149 
150   // True if the random address needs a refresh. This is the case when
151   //   a. Privacy is enabled and the random device address needs to get rotated;
152   //      or
153   //   b. Privacy has recently been enabled and the controller hasn't been
154   //      programmed with the new address yet
155   bool needs_refresh_;
156 
157   // True if a HCI command to update the random address is in progress.
158   bool refreshing_;
159 
160   // The local identity resolving key. If present, it is used to generate RPAs
161   // when privacy is enabled.
162   std::optional<UInt128> irk_;
163 
164   // Callbacks waiting to be notified of the local address.
165   std::queue<AddressCallback> address_callbacks_;
166   // Callbacks waiting to be notified of a change in the local address.
167   std::vector<AddressCallback> address_changed_callbacks_;
168 
169   // The task that executes when a random address expires and needs to be
170   // refreshed.
171   SmartTask random_address_expiry_task_{dispatcher_};
172 
173   WeakSelf<LowEnergyAddressManager> weak_self_;
174 
175   BT_DISALLOW_COPY_ASSIGN_AND_MOVE(LowEnergyAddressManager);
176 };
177 
178 }  // namespace gap
179 }  // namespace bt
180