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