xref: /aosp_15_r20/external/pigweed/pw_bluetooth_sapphire/host/sm/security_request_phase.cc (revision 61c4878ac05f98d0ceed94b57d316916de578985)
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