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 "pw_bluetooth_sapphire/internal/host/hci-spec/link_key.h"
17 #include "pw_bluetooth_sapphire/internal/host/hci/connection.h"
18 
19 namespace bt::hci {
20 
21 // Represents an ACL-U or LE-U link, both of which use the ACL data channel and
22 // support encryption procedures.
23 // Concrete implementations are found in BrEdrConnection and
24 // LowEnergyConnection.
25 class AclConnection : public Connection {
26  public:
27   ~AclConnection() override;
28 
29   // Authenticate (i.e. encrypt) this connection using its current link key.
30   // Returns false if the procedure cannot be initiated. The result of the
31   // authentication procedure will be reported via the encryption change
32   // callback.
33   //
34   // If the link layer procedure fails, the connection will be disconnected. The
35   // encryption change callback will be notified of the failure.
36   virtual bool StartEncryption() = 0;
37 
38   // Assigns a callback that will run when the encryption state of the
39   // underlying link changes. The bool value parameter represents the new state.
set_encryption_change_callback(ResultFunction<bool> callback)40   void set_encryption_change_callback(ResultFunction<bool> callback) {
41     encryption_change_callback_ = std::move(callback);
42   }
43 
44   // Returns the role of the local device in the established connection.
role()45   pw::bluetooth::emboss::ConnectionRole role() const { return role_; }
46 
47   // Update the role of the local device when a role change occurs.
set_role(pw::bluetooth::emboss::ConnectionRole role)48   void set_role(pw::bluetooth::emboss::ConnectionRole role) { role_ = role; }
49 
50   // The current long term key of the connection.
ltk()51   const std::optional<hci_spec::LinkKey>& ltk() const { return ltk_; }
52 
set_use_secure_connections(bool use_secure_connections)53   void set_use_secure_connections(bool use_secure_connections) {
54     use_secure_connections_ = use_secure_connections;
55   }
56 
encryption_status()57   pw::bluetooth::emboss::EncryptionStatus encryption_status() const {
58     return encryption_status_;
59   }
set_encryption_status(pw::bluetooth::emboss::EncryptionStatus status)60   void set_encryption_status(pw::bluetooth::emboss::EncryptionStatus status) {
61     encryption_status_ = status;
62   }
63 
64  protected:
65   AclConnection(hci_spec::ConnectionHandle handle,
66                 const DeviceAddress& local_address,
67                 const DeviceAddress& peer_address,
68                 pw::bluetooth::emboss::ConnectionRole role,
69                 const Transport::WeakPtr& hci);
70 
set_ltk(const hci_spec::LinkKey & link_key)71   void set_ltk(const hci_spec::LinkKey& link_key) { ltk_ = link_key; }
72 
73   // Notifies subclasses of a change in encryption status.
74   virtual void HandleEncryptionStatus(Result<bool /*enabled*/> result,
75                                       bool key_refreshed) = 0;
76 
encryption_change_callback()77   ResultFunction<bool>& encryption_change_callback() {
78     return encryption_change_callback_;
79   }
80 
81  private:
82   // This method must be static since it may be invoked after the connection
83   // associated with it is destroyed.
84   static void OnDisconnectionComplete(hci_spec::ConnectionHandle handle,
85                                       const Transport::WeakPtr& hci);
86 
87   // HCI event handlers.
88   CommandChannel::EventCallbackResult OnEncryptionChangeEvent(
89       const EventPacket& event);
90   CommandChannel::EventCallbackResult OnEncryptionKeyRefreshCompleteEvent(
91       const EventPacket& event);
92 
93   // IDs for encryption related HCI event handlers.
94   CommandChannel::EventHandlerId enc_change_id_;
95   CommandChannel::EventHandlerId enc_key_refresh_cmpl_id_;
96 
97   // This connection's current link key.
98   std::optional<hci_spec::LinkKey> ltk_;
99 
100   // Flag indicating if peer and local Secure Connections support are both
101   // present. Set in OnLinkKeyNotification in SecureSimplePairingState
102   bool use_secure_connections_ = false;
103 
104   pw::bluetooth::emboss::EncryptionStatus encryption_status_ =
105       pw::bluetooth::emboss::EncryptionStatus::OFF;
106 
107   pw::bluetooth::emboss::ConnectionRole role_;
108 
109   ResultFunction<bool> encryption_change_callback_;
110 
111   WeakSelf<AclConnection> weak_self_;
112 };
113 
114 }  // namespace bt::hci
115