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 <lib/fit/function.h>
17 
18 #include "pw_bluetooth_sapphire/internal/host/common/device_address.h"
19 #include "pw_bluetooth_sapphire/internal/host/hci/connection.h"
20 #include "pw_bluetooth_sapphire/internal/host/sm/pairing_channel.h"
21 #include "pw_bluetooth_sapphire/internal/host/sm/pairing_phase.h"
22 #include "pw_bluetooth_sapphire/internal/host/sm/smp.h"
23 #include "pw_bluetooth_sapphire/internal/host/sm/types.h"
24 
25 namespace bt::sm {
26 
27 // Represents Phase 3 of SM pairing. In this phase, the keys the devices agreed
28 // to distribute during Phase 1 are exchanged. Phase 3 must take place on an
29 // already-encrypted link.
30 //
31 // THREAD SAFETY
32 //
33 // This class is not thread safe and is meant to be accessed on the thread it
34 // was created on. All callbacks will be run by the default dispatcher of a
35 // Phase3's creation thread.
36 
37 using Phase3CompleteCallback = fit::function<void(PairingData)>;
38 
39 class Phase3 final : public PairingPhase, public PairingChannelHandler {
40  public:
41   // Initializes Phase3 with the following parameters:
42   //   - |chan|: The L2CAP SMP fixed channel.
43   //   - |role|: The local device's HCI role.
44   //   - |listener|: The current Phase's listener.
45   //   - |io_capability|: The local I/O capability.
46   //   - |features|: The features that determine pairing, negotiated during
47   //   Phase 1. There must be
48   //     some keys to distribute if Phase3 exists - construction will panic if
49   //     both the local & remote key_distribution fields of features are 0.
50   //   - |le_sec|: The current security properties of key encrypting the link.
51   Phase3(PairingChannel::WeakPtr chan,
52          Listener::WeakPtr listener,
53          Role role,
54          PairingFeatures features,
55          SecurityProperties le_sec,
56          Phase3CompleteCallback on_complete);
~Phase3()57   ~Phase3() override { InvalidatePairingChannelHandler(); }
58 
59   // Performs the key distribution phase of pairing.
60   void Start() final;
61 
62  private:
63   // Called when the Encryption Info (i.e. the LTK) is received from the peer.
64   void OnEncryptionInformation(const EncryptionInformationParams& ltk);
65 
66   // Called when EDiv and Rand values are received from the peer.
67   void OnCentralIdentification(const CentralIdentificationParams& params);
68 
69   // Called when the "Identity Resolving Key" is received from the peer.
70   void OnIdentityInformation(const IRK& irk);
71 
72   // Called when the "Identity Address" is received from the peer.
73   void OnIdentityAddressInformation(
74       const IdentityAddressInformationParams& params);
75 
76   // Called whenever a complete key is received from the peer.
77   void OnExpectedKeyReceived();
78 
79   // Called to send all agreed upon keys to the peer during Phase 3. Returns
80   // false if an error occurs and pairing should be aborted.
81   bool SendLocalKeys();
82 
83   // Only used during legacy pairing. Returns false if the command cannot be
84   // sent.
85   bool SendEncryptionKey();
86 
87   // Sends the identity information. Returns false if the command cannot be
88   // sent.
89   bool SendIdentityInfo();
90 
91   // Called to collect all pairing keys and notify the callback that we are
92   // complete
93   void SignalComplete();
94 
95   // l2cap::Channel callbacks:
OnChannelClosed()96   void OnChannelClosed() final { PairingPhase::HandleChannelClosed(); }
97   void OnRxBFrame(ByteBufferPtr sdu) final;
98 
99   // True if all keys that are expected from the remote have been received.
100   bool RequestedKeysObtained() const;
101 
102   // True if all local keys that were agreed to be distributed have been sent to
103   // the peer.
104   bool LocalKeysSent() const;
105 
KeyExchangeComplete()106   bool KeyExchangeComplete() const {
107     return RequestedKeysObtained() && LocalKeysSent();
108   }
109   bool ShouldReceiveLtk() const;       // True if peer should send the LTK
110   bool ShouldReceiveIdentity() const;  // True if peer should send identity
111   bool ShouldSendLtk() const;          // True if we should send the LTK
112   bool ShouldSendIdentity() const;     // True if we should send identity info
113 
114   // PairingPhase override
ToStringInternal()115   std::string ToStringInternal() override {
116     return bt_lib_cpp_string::StringPrintf(
117         "Pairing Phase 3 (security key distribution) - paired with %s security "
118         "properties, sending "
119         "0x%02X local key distribution value and expecting 0x%02X as peer key "
120         "distribution value",
121         le_sec_.ToString().c_str(),
122         features_.local_key_distribution,
123         features_.remote_key_distribution);
124   }
125 
126   const PairingFeatures features_;
127 
128   // Current security properties of the LE-U link.
129   const SecurityProperties le_sec_;
130 
131   // The remote keys that have been obtained so far.
132   KeyDistGenField obtained_remote_keys_;
133 
134   // True if all the local keys in features_ have been sent to the peer.
135   bool sent_local_keys_;
136 
137   // Generated and distributed if the EncKey bit of the local device's
138   // KeyDistGenField is set.
139   std::optional<LTK> local_ltk_;
140 
141   // Data from the peer tracked during Phase 3. Parts of the LTK are received in
142   // separate events. The LTK is only received in Legacy pairing.
143   std::optional<UInt128> peer_ltk_bytes_;  // LTK without ediv/rand.
144   std::optional<LTK> peer_ltk_;            // Full LTK with ediv/rand
145   std::optional<IRK> irk_;
146   std::optional<DeviceAddress> identity_address_;
147 
148   const Phase3CompleteCallback on_complete_;
149 
150   BT_DISALLOW_COPY_AND_ASSIGN_ALLOW_MOVE(Phase3);
151 };
152 
153 }  // namespace bt::sm
154