• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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