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 #include "pw_bluetooth_sapphire/internal/host/sm/security_request_phase.h"
16
17 #include <type_traits>
18
19 #include "pw_bluetooth_sapphire/internal/host/common/assert.h"
20 #include "pw_bluetooth_sapphire/internal/host/common/log.h"
21 #include "pw_bluetooth_sapphire/internal/host/sm/packet.h"
22 #include "pw_bluetooth_sapphire/internal/host/sm/smp.h"
23 #include "pw_bluetooth_sapphire/internal/host/sm/types.h"
24 #include "pw_bluetooth_sapphire/internal/host/sm/util.h"
25
26 namespace bt::sm {
27
SecurityRequestPhase(PairingChannel::WeakPtr chan,Listener::WeakPtr listener,SecurityLevel desired_level,BondableMode bondable_mode,PairingRequestCallback on_pairing_req)28 SecurityRequestPhase::SecurityRequestPhase(
29 PairingChannel::WeakPtr chan,
30 Listener::WeakPtr listener,
31 SecurityLevel desired_level,
32 BondableMode bondable_mode,
33 PairingRequestCallback on_pairing_req)
34 : PairingPhase(std::move(chan), std::move(listener), Role::kResponder),
35 bondable_mode_(bondable_mode),
36 pending_security_request_(desired_level),
37 on_pairing_req_(std::move(on_pairing_req)) {
38 SetPairingChannelHandler(*this);
39 }
40
Start()41 void SecurityRequestPhase::Start() {
42 MakeSecurityRequest(pending_security_request_, bondable_mode_);
43 }
44
MakeSecurityRequest(SecurityLevel desired_level,BondableMode bondable_mode)45 void SecurityRequestPhase::MakeSecurityRequest(SecurityLevel desired_level,
46 BondableMode bondable_mode) {
47 PW_CHECK(desired_level >= SecurityLevel::kEncrypted);
48 AuthReqField security_req_payload = 0u;
49 if (desired_level >= SecurityLevel::kAuthenticated) {
50 // inclusive-language: ignore
51 security_req_payload |= AuthReq::kMITM;
52 }
53 if (bondable_mode == BondableMode::Bondable) {
54 security_req_payload |= AuthReq::kBondingFlag;
55 }
56 if (desired_level == SecurityLevel::kSecureAuthenticated) {
57 security_req_payload |= AuthReq::kSC;
58 }
59 pending_security_request_ = desired_level;
60 sm_chan().SendMessage(kSecurityRequest, security_req_payload);
61 }
62
OnPairingRequest(PairingRequestParams req_params)63 void SecurityRequestPhase::OnPairingRequest(PairingRequestParams req_params) {
64 on_pairing_req_(req_params);
65 }
66
OnRxBFrame(ByteBufferPtr sdu)67 void SecurityRequestPhase::OnRxBFrame(ByteBufferPtr sdu) {
68 fit::result<ErrorCode, ValidPacketReader> maybe_reader =
69 ValidPacketReader::ParseSdu(sdu);
70 if (maybe_reader.is_error()) {
71 Abort(maybe_reader.error_value());
72 return;
73 }
74 ValidPacketReader reader = maybe_reader.value();
75 Code smp_code = reader.code();
76
77 if (smp_code == kPairingRequest) {
78 OnPairingRequest(reader.payload<PairingRequestParams>());
79 } else {
80 bt_log(DEBUG,
81 "sm",
82 "received unexpected code %#.2X with pending Security Request",
83 smp_code);
84 Abort(ErrorCode::kUnspecifiedReason);
85 }
86 }
87
88 } // namespace bt::sm
89