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