Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 2638d409 authored by Martin Brabham's avatar Martin Brabham Committed by Myles Watson
Browse files

SecurityModule: Add callbacks to your callbacks

Add an argument to the external callback signature in order
to allow external caller to input user responses.

Bug: 139137147
Test: ./out/host/linux-x86/nativetest64/bluetooth_test_gd/bluetooth_test_gd --gtest_filter=ClassicPairing*
Change-Id: Ib827991dd2827ec0bad0206192387ad66696d740
parent cff9e10a
Loading
Loading
Loading
Loading
+6 −3
Original line number Diff line number Diff line
@@ -63,10 +63,13 @@ class SecurityModuleFacadeService : public SecurityModuleFacade::Service, public
    return ::grpc::Status::OK;
  }

  void OnDisplayYesNoDialogWithValue(const bluetooth::hci::AddressWithType& address, uint32_t numeric_value) {}
  void OnDisplayYesNoDialog(const bluetooth::hci::AddressWithType& address) {}
  void OnDisplayYesNoDialogWithValue(const bluetooth::hci::AddressWithType& address, uint32_t numeric_value,
                                     common::OnceCallback<void(bool)> input_callback) {}
  void OnDisplayYesNoDialog(const bluetooth::hci::AddressWithType& address,
                            common::OnceCallback<void(bool)> input_callback) {}
  void OnDisplayPasskeyDialog(const bluetooth::hci::AddressWithType& address, uint32_t passkey) {}
  void OnDisplayPasskeyInputDialog(const bluetooth::hci::AddressWithType& address){};
  void OnDisplayPasskeyInputDialog(const bluetooth::hci::AddressWithType& address,
                                   common::OnceCallback<void(uint32_t)> input_callback){};
  void OnDisplayCancelDialog(const bluetooth::hci::AddressWithType& address) {}
  void OnDeviceBonded(hci::AddressWithType device) {}
  void OnDeviceUnbonded(hci::AddressWithType device) {}
+56 −21
Original line number Diff line number Diff line
@@ -17,41 +17,46 @@
 */
#include "security/pairing/classic_pairing_handler.h"

#include "common/bind.h"

namespace bluetooth {
namespace security {
namespace pairing {

void ClassicPairingHandler::NotifyUiDisplayYesNo(uint32_t numeric_value) {
void ClassicPairingHandler::NotifyUiDisplayYesNo(uint32_t numeric_value,
                                                 common::OnceCallback<void(bool)> input_callback) {
  for (auto& iter : client_listeners_) {
    iter.second->Post(common::Bind(&ISecurityManagerListener::OnDisplayYesNoDialogWithValue,
                                   common::Unretained(iter.first), GetRecord()->GetPseudoAddress(), numeric_value));
    iter.second->Post(common::BindOnce(&ISecurityManagerListener::OnDisplayYesNoDialogWithValue,
                                       common::Unretained(iter.first), GetRecord()->GetPseudoAddress(), numeric_value,
                                       std::move(input_callback)));
  }
}

void ClassicPairingHandler::NotifyUiDisplayYesNo() {
void ClassicPairingHandler::NotifyUiDisplayYesNo(common::OnceCallback<void(bool)> input_callback) {
  for (auto& iter : client_listeners_) {
    iter.second->Post(common::Bind(&ISecurityManagerListener::OnDisplayYesNoDialog, common::Unretained(iter.first),
                                   GetRecord()->GetPseudoAddress()));
    iter.second->Post(common::BindOnce(&ISecurityManagerListener::OnDisplayYesNoDialog, common::Unretained(iter.first),
                                       GetRecord()->GetPseudoAddress(), std::move(input_callback)));
  }
}

void ClassicPairingHandler::NotifyUiDisplayPasskey(uint32_t passkey) {
  for (auto& iter : client_listeners_) {
    iter.second->Post(common::Bind(&ISecurityManagerListener::OnDisplayPasskeyDialog, common::Unretained(iter.first),
                                   GetRecord()->GetPseudoAddress(), passkey));
    iter.second->Post(common::BindOnce(&ISecurityManagerListener::OnDisplayPasskeyDialog,
                                       common::Unretained(iter.first), GetRecord()->GetPseudoAddress(), passkey));
  }
}

void ClassicPairingHandler::NotifyUiDisplayPasskeyInput() {
void ClassicPairingHandler::NotifyUiDisplayPasskeyInput(common::OnceCallback<void(uint32_t passkey)> input_callback) {
  for (auto& iter : client_listeners_) {
    iter.second->Post(common::Bind(&ISecurityManagerListener::OnDisplayPasskeyInputDialog,
                                   common::Unretained(iter.first), GetRecord()->GetPseudoAddress()));
    iter.second->Post(common::BindOnce(&ISecurityManagerListener::OnDisplayPasskeyInputDialog,
                                       common::Unretained(iter.first), GetRecord()->GetPseudoAddress(),
                                       std::move(input_callback)));
  }
}

void ClassicPairingHandler::NotifyUiDisplayCancel() {
  for (auto& iter : client_listeners_) {
    iter.second->Post(common::Bind(&ISecurityManagerListener::OnDisplayCancelDialog, common::Unretained(iter.first),
    iter.second->Post(common::BindOnce(&ISecurityManagerListener::OnDisplayCancelDialog, common::Unretained(iter.first),
                                       GetRecord()->GetPseudoAddress()));
  }
}
@@ -160,6 +165,7 @@ void ClassicPairingHandler::OnReceive(hci::LinkKeyNotificationView packet) {
  LOG_INFO("Received: %s", hci::EventCodeText(packet.GetEventCode()).c_str());
  ASSERT_LOG(GetRecord()->GetPseudoAddress().GetAddress() == packet.GetBdAddr(), "Address mismatch");
  GetRecord()->SetLinkKey(packet.GetLinkKey(), packet.GetKeyType());
  Cancel();
}

void ClassicPairingHandler::OnReceive(hci::IoCapabilityRequestView packet) {
@@ -181,7 +187,6 @@ void ClassicPairingHandler::OnReceive(hci::IoCapabilityResponseView packet) {

  // Using local variable until device database pointer is ready
  remote_io_capability_ = packet.GetIoCapability();
  // TODO(optedoblivion): device->SetIoCapability(packet.GetIoCapability);
}

void ClassicPairingHandler::OnReceive(hci::SimplePairingCompleteView packet) {
@@ -189,8 +194,11 @@ void ClassicPairingHandler::OnReceive(hci::SimplePairingCompleteView packet) {
  LOG_INFO("Received: %s", hci::EventCodeText(packet.GetEventCode()).c_str());
  ASSERT_LOG(GetRecord()->GetPseudoAddress().GetAddress() == packet.GetBdAddr(), "Address mismatch");
  last_status_ = packet.GetStatus();
  if (last_status_ != hci::ErrorCode::SUCCESS) {
    LOG_INFO("Failed SimplePairingComplete: %s", hci::ErrorCodeText(last_status_).c_str());
    Cancel();
  }
}

void ClassicPairingHandler::OnReceive(hci::ReturnLinkKeysView packet) {
  ASSERT(packet.IsValid());
@@ -292,13 +300,15 @@ void ClassicPairingHandler::OnReceive(hci::UserConfirmationRequestView packet) {
        case hci::IoCapability::DISPLAY_ONLY:
          // NumericComparison, Initiator display, Responder auto confirm
          LOG_INFO("Numeric Comparison: A DisplayYesNo, B auto confirm");
          NotifyUiDisplayYesNo(packet.GetNumericValue());
          NotifyUiDisplayYesNo(packet.GetNumericValue(),
                               common::BindOnce(&ClassicPairingHandler::OnUserInput, common::Unretained(this)));
          // Unauthenticated
          break;
        case hci::IoCapability::DISPLAY_YES_NO:
          // NumericComparison Both Display, Both confirm
          LOG_INFO("Numeric Comparison: A and B DisplayYesNo");
          NotifyUiDisplayYesNo(packet.GetNumericValue());
          NotifyUiDisplayYesNo(packet.GetNumericValue(),
                               common::BindOnce(&ClassicPairingHandler::OnUserInput, common::Unretained(this)));
          // Authenticated
          break;
        case hci::IoCapability::KEYBOARD_ONLY:
@@ -309,7 +319,7 @@ void ClassicPairingHandler::OnReceive(hci::UserConfirmationRequestView packet) {
          break;
        case hci::IoCapability::NO_INPUT_NO_OUTPUT:
          // NumericComparison, auto confirm Responder, Yes/No confirm Initiator. Don't show confirmation value
          NotifyUiDisplayYesNo();
          NotifyUiDisplayYesNo(common::BindOnce(&ClassicPairingHandler::OnUserInput, common::Unretained(this)));
          LOG_INFO("Numeric Comparison: A DisplayYesNo, B auto confirm, no show value");
          // Unauthenticated
          break;
@@ -319,19 +329,22 @@ void ClassicPairingHandler::OnReceive(hci::UserConfirmationRequestView packet) {
      switch (responder_io_capability) {
        case hci::IoCapability::DISPLAY_ONLY:
          // PassKey Entry, Responder display, Initiator input
          NotifyUiDisplayPasskeyInput();
          NotifyUiDisplayPasskeyInput(
              common::BindOnce(&ClassicPairingHandler::OnPasskeyInput, common::Unretained(this)));
          LOG_INFO("Passkey Entry: A input, B display");
          // Authenticated
          break;
        case hci::IoCapability::DISPLAY_YES_NO:
          // PassKey Entry, Responder display, Initiator input
          NotifyUiDisplayPasskeyInput();
          NotifyUiDisplayPasskeyInput(
              common::BindOnce(&ClassicPairingHandler::OnPasskeyInput, common::Unretained(this)));
          LOG_INFO("Passkey Entry: A input, B display");
          // Authenticated
          break;
        case hci::IoCapability::KEYBOARD_ONLY:
          // PassKey Entry, both input
          NotifyUiDisplayPasskeyInput();
          NotifyUiDisplayPasskeyInput(
              common::BindOnce(&ClassicPairingHandler::OnPasskeyInput, common::Unretained(this)));
          LOG_INFO("Passkey Entry: A input, B input");
          // Authenticated
          break;
@@ -384,6 +397,28 @@ void ClassicPairingHandler::OnReceive(hci::UserPasskeyRequestView packet) {
  ASSERT_LOG(GetRecord()->GetPseudoAddress().GetAddress() == packet.GetBdAddr(), "Address mismatch");
}

void ClassicPairingHandler::OnUserInput(bool user_input) {
  if (user_input) {
    UserClickedYes();
  } else {
    UserClickedNo();
  }
}

void ClassicPairingHandler::UserClickedYes() {
  GetChannel()->SendCommand(
      hci::UserConfirmationRequestReplyBuilder::Create(GetRecord()->GetPseudoAddress().GetAddress()));
}

void ClassicPairingHandler::UserClickedNo() {
  GetChannel()->SendCommand(
      hci::UserConfirmationRequestNegativeReplyBuilder::Create(GetRecord()->GetPseudoAddress().GetAddress()));
}

void ClassicPairingHandler::OnPasskeyInput(uint32_t passkey) {
  passkey_ = passkey;
}

}  // namespace pairing
}  // namespace security
}  // namespace bluetooth
+9 −3
Original line number Diff line number Diff line
@@ -21,6 +21,7 @@

#include <utility>

#include "common/callback.h"
#include "l2cap/classic/l2cap_classic_module.h"
#include "security/initial_informations.h"
#include "security/security_manager_listener.h"
@@ -81,11 +82,15 @@ class ClassicPairingHandler : public PairingHandler {
  void OnConnectionOpen(std::unique_ptr<l2cap::classic::FixedChannel> fixed_channel);
  void OnConnectionFail(l2cap::classic::FixedChannelManager::ConnectionResult result);
  void OnConnectionClose(hci::ErrorCode error_code);
  void NotifyUiDisplayYesNo(uint32_t numeric_value);
  void NotifyUiDisplayYesNo();
  void OnUserInput(bool user_input);
  void OnPasskeyInput(uint32_t passkey);
  void NotifyUiDisplayYesNo(uint32_t numeric_value, common::OnceCallback<void(bool)> input_callback);
  void NotifyUiDisplayYesNo(common::OnceCallback<void(bool)> input_callback);
  void NotifyUiDisplayPasskey(uint32_t passkey);
  void NotifyUiDisplayPasskeyInput();
  void NotifyUiDisplayPasskeyInput(common::OnceCallback<void(uint32_t)> input_callback);
  void NotifyUiDisplayCancel();
  void UserClickedYes();
  void UserClickedNo();

  std::shared_ptr<l2cap::classic::FixedChannelManager> fixed_channel_manager_;
  std::unique_ptr<l2cap::classic::FixedChannelService> fixed_channel_service_{nullptr};
@@ -100,6 +105,7 @@ class ClassicPairingHandler : public PairingHandler {
  std::vector<std::pair<ISecurityManagerListener*, os::Handler*>>& client_listeners_;
  hci::ErrorCode last_status_;
  bool locally_initiated_ = false;
  uint32_t passkey_ = 0;
};

}  // namespace pairing
+10 −6
Original line number Diff line number Diff line
@@ -18,6 +18,8 @@

#pragma once

#include "common/callback.h"

namespace bluetooth {
namespace security {

@@ -34,15 +36,16 @@ class ISecurityManagerListener {
   * @param address pairing device
   * @param numeric_value numeric comparison value to verify
   */
  virtual void OnDisplayYesNoDialogWithValue(const bluetooth::hci::AddressWithType& address,
                                             uint32_t numeric_value) = 0;
  virtual void OnDisplayYesNoDialogWithValue(const bluetooth::hci::AddressWithType& address, uint32_t numeric_value,
                                             common::OnceCallback<void(bool)> input_callback) = 0;

  /**
   * Display Yes/No dialog with numeric value
   * Display Yes/No
   *
   * @param address pairing device
   */
  virtual void OnDisplayYesNoDialog(const bluetooth::hci::AddressWithType& address) = 0;
  virtual void OnDisplayYesNoDialog(const bluetooth::hci::AddressWithType& address,
                                    common::OnceCallback<void(bool)> input_callback) = 0;

  /**
   * Present the passkey value to the user
@@ -52,11 +55,12 @@ class ISecurityManagerListener {
  /**
   * Display a dialog box that will let user enter the Passkey
   */
  virtual void OnDisplayPasskeyInputDialog(const bluetooth::hci::AddressWithType& address) = 0;
  virtual void OnDisplayPasskeyInputDialog(const bluetooth::hci::AddressWithType& address,
                                           common::OnceCallback<void(uint32_t)> input_callback) = 0;

  /**
   * Remove the pairing prompt from DisplayPairingPrompt, i.e. remote device
   * disconnected, or some application requested bond with this device
   * disconnected, or some application requested bond with this device.  So the UI should dismiss the pairing prompt.
   */
  virtual void OnDisplayCancelDialog(const bluetooth::hci::AddressWithType& address) = 0;