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

Commit 4c8c7065 authored by Treehugger Robot's avatar Treehugger Robot Committed by Gerrit Code Review
Browse files

Merge "SM: Implement the LinkSecurityInterface for managing an ACL connection"

parents db614cbd 1da353d1
Loading
Loading
Loading
Loading
+42 −85
Original line number Diff line number Diff line
@@ -24,63 +24,50 @@ namespace bluetooth {
namespace security {
namespace channel {

/**
 * Constructor for testing only
 */
SecurityManagerChannel::SecurityManagerChannel(os::Handler* handler, hci::HciLayer* hci_layer)
    : listener_(nullptr), hci_security_interface_(hci_layer->GetSecurityInterface(
                              handler->BindOn(this, &SecurityManagerChannel::OnHciEventReceived))),
      handler_(handler) {
  is_test_mode_ = true;
}

/**
 * Main Constructor
 */
SecurityManagerChannel::SecurityManagerChannel(
    os::Handler* handler, hci::HciLayer* hci_layer,
    std::unique_ptr<l2cap::classic::FixedChannelManager> fixed_channel_manager)
    : listener_(nullptr), hci_security_interface_(hci_layer->GetSecurityInterface(
                              handler->BindOn(this, &SecurityManagerChannel::OnHciEventReceived))),
      handler_(handler), fixed_channel_manager_(std::move(fixed_channel_manager)) {
  ASSERT_LOG(fixed_channel_manager_ != nullptr, "No channel manager!");
  LOG_DEBUG("Registering for a fixed channel service");
  fixed_channel_manager_->RegisterService(
      l2cap::kClassicPairingTriggerCid,
      common::BindOnce(&SecurityManagerChannel::OnRegistrationComplete, common::Unretained(this)),
      common::Bind(&SecurityManagerChannel::OnConnectionOpen, common::Unretained(this)), handler_);
}
SecurityManagerChannel::SecurityManagerChannel(os::Handler* handler, hci::HciLayer* hci_layer)
    : listener_(nullptr),
      hci_security_interface_(
          hci_layer->GetSecurityInterface(handler->BindOn(this, &SecurityManagerChannel::OnHciEventReceived))),
      handler_(handler),
      l2cap_security_interface_(nullptr) {}

SecurityManagerChannel::~SecurityManagerChannel() {
  if (fixed_channel_service_ != nullptr) {
    fixed_channel_service_->Unregister(common::Bind(&SecurityManagerChannel::OnUnregistered, common::Unretained(this)),
                                       handler_);
    fixed_channel_service_.reset();
  }
  l2cap_security_interface_->Unregister();
  l2cap_security_interface_ = nullptr;
}

void SecurityManagerChannel::Connect(hci::Address address) {
  if (is_test_mode_) return;
  ASSERT_LOG(fixed_channel_manager_ != nullptr, "No channel manager!");
  auto entry = fixed_channel_map_.find(address);
  if (entry != fixed_channel_map_.end()) {
    LOG_ERROR("Already connected to device: %s", address.ToString().c_str());
  ASSERT_LOG(l2cap_security_interface_ != nullptr, "L2cap Security Interface is null!");
  if (link_map_.find(address) != link_map_.end()) {
    LOG_WARN("Already connected to '%s'", address.ToString().c_str());
    return;
  }
  fixed_channel_manager_->ConnectServices(
      address, common::Bind(&SecurityManagerChannel::OnConnectionFail, common::Unretained(this), address), handler_);
  l2cap_security_interface_->InitiateConnectionForSecurity(address);
}

void SecurityManagerChannel::Disconnect(hci::Address address) {
  if (is_test_mode_) return;
  auto entry = fixed_channel_map_.find(address);
  if (entry != fixed_channel_map_.end()) {
void SecurityManagerChannel::Release(hci::Address address) {
  auto entry = link_map_.find(address);
  if (entry == link_map_.end()) {
    LOG_WARN("Unknown address '%s'", address.ToString().c_str());
    return;
  }
  entry->second->Release();
  entry->second.reset();
    fixed_channel_map_.erase(entry);
  } else {
  link_map_.erase(entry);
}

void SecurityManagerChannel::Disconnect(hci::Address address) {
  auto entry = link_map_.find(address);
  if (entry == link_map_.end()) {
    LOG_WARN("Unknown address '%s'", address.ToString().c_str());
    return;
  }
  entry->second->Disconnect();
  entry->second.reset();
  link_map_.erase(entry);
}

void SecurityManagerChannel::OnCommandComplete(hci::CommandCompleteView packet) {
@@ -98,53 +85,23 @@ void SecurityManagerChannel::OnHciEventReceived(hci::EventPacketView packet) {
  listener_->OnHciEventReceived(packet);
}

void SecurityManagerChannel::OnRegistrationComplete(
    l2cap::classic::FixedChannelManager::RegistrationResult result,
    std::unique_ptr<l2cap::classic::FixedChannelService> fixed_channel_service) {
  ASSERT(fixed_channel_service_ == nullptr);
  ASSERT_LOG(result == l2cap::classic::FixedChannelManager::RegistrationResult::SUCCESS,
             "Failed service registration!");
  fixed_channel_service_ = std::move(fixed_channel_service);
}

void SecurityManagerChannel::OnUnregistered() {
  fixed_channel_manager_.reset();
}

void SecurityManagerChannel::OnConnectionOpen(std::unique_ptr<l2cap::classic::FixedChannel> fixed_channel) {
  ASSERT_LOG(fixed_channel != nullptr, "Null channel passed in");
  ASSERT_LOG(fixed_channel_map_.find(fixed_channel->GetDevice()) == fixed_channel_map_.end(),
             "Multiple fixed channel for a single device is not allowed.");
  fixed_channel->RegisterOnCloseCallback(
      handler_, common::BindOnce(&SecurityManagerChannel::OnConnectionClose, common::Unretained(this),
                                 fixed_channel->GetDevice()));
  fixed_channel->Acquire();
  auto new_entry = std::pair<hci::Address, std::unique_ptr<l2cap::classic::FixedChannel>>(fixed_channel->GetDevice(),
                                                                                          std::move(fixed_channel));
  fixed_channel_map_.insert(std::move(new_entry));
void SecurityManagerChannel::OnLinkConnected(std::unique_ptr<l2cap::classic::LinkSecurityInterface> link) {
  // Multiple links possible?
  link->Hold();
  link->EnsureAuthenticated();
  link_map_.emplace(link->GetRemoteAddress(), std::move(link));
}

void SecurityManagerChannel::OnConnectionFail(hci::Address address,
                                              l2cap::classic::FixedChannelManager::ConnectionResult result) {
  LOG_ERROR("Connection closed due to: %s ; %d", hci::ErrorCodeText(result.hci_error).c_str(),
            result.connection_result_code);
  auto entry = fixed_channel_map_.find(address);
  if (entry != fixed_channel_map_.end()) {
    entry->second.reset();
    fixed_channel_map_.erase(entry);
  }
  listener_->OnConnectionFailed(address, result);
void SecurityManagerChannel::OnLinkDisconnected(hci::Address address) {
  auto entry = link_map_.find(address);
  if (entry == link_map_.end()) {
    LOG_WARN("Unknown address '%s'", address.ToString().c_str());
    return;
  }

void SecurityManagerChannel::OnConnectionClose(hci::Address address, hci::ErrorCode error_code) {
  // Called when the connection gets closed
  LOG_ERROR("Connection closed due to: %s", hci::ErrorCodeText(error_code).c_str());
  auto entry = fixed_channel_map_.find(address);
  if (entry != fixed_channel_map_.end()) {
  entry->second.reset();
    fixed_channel_map_.erase(entry);
  }
  listener_->OnConnectionClosed(address, error_code);
  link_map_.erase(entry);
  ASSERT_LOG(listener_ != nullptr, "Set listener!");
  listener_->OnConnectionClosed(address);
}

}  // namespace channel
+27 −22
Original line number Diff line number Diff line
@@ -26,6 +26,7 @@
#include "hci/hci_packets.h"
#include "hci/security_interface.h"
#include "l2cap/classic/l2cap_classic_module.h"
#include "l2cap/classic/link_security_interface.h"

namespace bluetooth {
namespace security {
@@ -38,18 +39,15 @@ class ISecurityManagerChannelListener {
 public:
  virtual ~ISecurityManagerChannelListener() = default;
  virtual void OnHciEventReceived(hci::EventPacketView packet) = 0;
  virtual void OnConnectionClosed(hci::Address, bluetooth::hci::ErrorCode error_code) = 0;
  virtual void OnConnectionFailed(hci::Address,
                                  bluetooth::l2cap::classic::FixedChannelManager::ConnectionResult result) = 0;
  virtual void OnConnectionClosed(hci::Address) = 0;
};

/**
 * Channel for consolidating traffic and making the transport agnostic.
 */
class SecurityManagerChannel {
class SecurityManagerChannel : public l2cap::classic::LinkSecurityInterfaceListener {
 public:
  SecurityManagerChannel(os::Handler* handler, hci::HciLayer* hci_layer,
                         std::unique_ptr<l2cap::classic::FixedChannelManager> fixed_channel_manager);
  SecurityManagerChannel(os::Handler* handler, hci::HciLayer* hci_layer);

  virtual ~SecurityManagerChannel();

@@ -61,7 +59,20 @@ class SecurityManagerChannel {
  void Connect(hci::Address address);

  /**
   * Disconnects currently connected channel
   * Releases link hold so it can disconnect as normally
   *
   * i.e. signals we no longer need this if acl manager wants to clean it up
   *
   * @param address remote address to disconnect
   */
  void Release(hci::Address address);

  /**
   * Immediately disconnects currently connected channel
   *
   * i.e. force disconnect
   *
   * @param address remote address to disconnect
   */
  void Disconnect(hci::Address address);

@@ -81,6 +92,10 @@ class SecurityManagerChannel {
    listener_ = listener;
  }

  void SetSecurityInterface(l2cap::classic::SecurityInterface* security_interface) {
    l2cap_security_interface_ = security_interface;
  }

  /**
   * Called when an incoming HCI event happens
   *
@@ -95,26 +110,16 @@ class SecurityManagerChannel {
   */
  void OnCommandComplete(hci::CommandCompleteView packet);

 protected:
  SecurityManagerChannel(os::Handler* handler, hci::HciLayer* hci_layer);

  virtual void OnRegistrationComplete(l2cap::classic::FixedChannelManager::RegistrationResult result,
                                      std::unique_ptr<l2cap::classic::FixedChannelService> fixed_channel_service);
  virtual void OnUnregistered();
  virtual void OnConnectionOpen(std::unique_ptr<l2cap::classic::FixedChannel> fixed_channel);
  virtual void OnConnectionFail(hci::Address address, l2cap::classic::FixedChannelManager::ConnectionResult result);
  virtual void OnConnectionClose(hci::Address address, hci::ErrorCode error_code);

  bool is_test_mode_ = false;
  // Interface overrides
  void OnLinkConnected(std::unique_ptr<l2cap::classic::LinkSecurityInterface> link) override;
  void OnLinkDisconnected(hci::Address address) override;

 private:
  ISecurityManagerChannelListener* listener_{nullptr};
  hci::SecurityInterface* hci_security_interface_{nullptr};
  os::Handler* handler_{nullptr};

  std::unique_ptr<l2cap::classic::FixedChannelManager> fixed_channel_manager_{nullptr};
  std::unique_ptr<l2cap::classic::FixedChannelService> fixed_channel_service_{nullptr};
  std::unordered_map<hci::Address, std::unique_ptr<l2cap::classic::FixedChannel>> fixed_channel_map_;
  l2cap::classic::SecurityInterface* l2cap_security_interface_{nullptr};
  std::unordered_map<hci::Address, std::unique_ptr<l2cap::classic::LinkSecurityInterface>> link_map_;
};

}  // namespace channel
+32 −10
Original line number Diff line number Diff line
@@ -15,15 +15,16 @@
 *  limitations under the License.
 *
 */
#include "security_manager_channel.h"
#include "security/channel/security_manager_channel.h"

#include <gtest/gtest.h>

#include "hci/address.h"
#include "hci/hci_packets.h"
#include "l2cap/classic/fixed_channel.h"
#include "packet/raw_builder.h"
#include "security/smp_packets.h"
#include "security/test/fake_hci_layer.h"
#include "security/test/fake_security_interface.h"

namespace bluetooth {
namespace security {
@@ -42,14 +43,21 @@ using os::Handler;
using os::Thread;
using packet::RawBuilder;

static bool on_link_connected_called = false;
static bool on_link_disconnected_called = false;

class FakeSecurityManagerChannel : public SecurityManagerChannel {
 public:
  FakeSecurityManagerChannel(os::Handler* handler, hci::HciLayer* hci_layer)
      : SecurityManagerChannel(handler, hci_layer) {}
  ~FakeSecurityManagerChannel() {}

  void OnConnectionOpen(std::unique_ptr<l2cap::classic::FixedChannel> fixed_channel) override {
    LOG_ERROR("CALLED");
  void OnLinkConnected(std::unique_ptr<l2cap::classic::LinkSecurityInterface> link) {
    on_link_connected_called = true;
  }

  void OnLinkDisconnected(hci::Address address) {
    on_link_disconnected_called = true;
  }
};

@@ -197,19 +205,19 @@ class SecurityManagerChannelCallback : public ISecurityManagerChannelListener {
    }
  }

  void OnConnectionClosed(hci::Address address, bluetooth::hci::ErrorCode error_code) override {
  void OnConnectionClosed(hci::Address address) override {
    LOG_DEBUG("Called");
  }

  void OnConnectionFailed(hci::Address address,
                          bluetooth::l2cap::classic::FixedChannelManager::ConnectionResult result) override {
    LOG_DEBUG("Shouldn't be called");
  }
};

class SecurityManagerChannelTest : public ::testing::Test {
 protected:
  void SetUp() override {
    hci::Address address;
    hci::Address::FromString("01:23:45:67:89:AB:CD", address);
    device_ = hci::AddressWithType(address, hci::AddressType::PUBLIC_DEVICE_ADDRESS);
    on_link_connected_called = false;
    on_link_disconnected_called = false;
    handler_ = new Handler(&thread_);
    callback_ = new SecurityManagerChannelCallback();
    hci_layer_ = new FakeHciLayer();
@@ -217,6 +225,8 @@ class SecurityManagerChannelTest : public ::testing::Test {
    fake_registry_.Start<FakeHciLayer>(&thread_);
    channel_ = new FakeSecurityManagerChannel(handler_, hci_layer_);
    channel_->SetChannelListener(callback_);
    security_interface_ = new FakeSecurityInterface(handler_, channel_);
    channel_->SetSecurityInterface(security_interface_);
  }

  void TearDown() override {
@@ -227,6 +237,7 @@ class SecurityManagerChannelTest : public ::testing::Test {
    delete handler_;
    delete channel_;
    delete callback_;
    delete security_interface_;
  }

  void synchronize() {
@@ -237,6 +248,7 @@ class SecurityManagerChannelTest : public ::testing::Test {
  Thread& thread_ = fake_registry_.GetTestThread();
  Handler* handler_ = nullptr;
  FakeHciLayer* hci_layer_ = nullptr;
  l2cap::classic::SecurityInterface* security_interface_ = nullptr;
  SecurityManagerChannel* channel_ = nullptr;
  SecurityManagerChannelCallback* callback_ = nullptr;
  hci::AddressWithType device_;
@@ -673,6 +685,16 @@ TEST_F(SecurityManagerChannelTest, recv_user_passkey_request) {
  ASSERT_TRUE(callback_->receivedUserPasskeyRequest);
}

TEST_F(SecurityManagerChannelTest, test_l2cap_security_interface_api) {
  ASSERT_FALSE(on_link_connected_called);
  channel_->Connect(device_.GetAddress());
  ASSERT_TRUE(on_link_connected_called);
  ASSERT_FALSE(on_link_disconnected_called);
  channel_->Release(device_.GetAddress());
  // TODO(optedoblivion): Lock and wait
  // ASSERT_TRUE(on_link_disconnected_called);
}

}  // namespace
}  // namespace channel
}  // namespace security
+3 −14
Original line number Diff line number Diff line
@@ -104,6 +104,7 @@ void SecurityManagerImpl::CancelBond(hci::AddressWithType device) {
void SecurityManagerImpl::RemoveBond(hci::AddressWithType device) {
  CancelBond(device);
  security_database_.Remove(device);
  security_manager_channel_->Disconnect(device.GetAddress());
  // Signal disconnect
  // Remove security record
  // Signal Remove from database
@@ -250,19 +251,7 @@ void SecurityManagerImpl::OnHciEventReceived(hci::EventPacketView packet) {
  }
}

void SecurityManagerImpl::OnConnectionClosed(hci::Address address, bluetooth::hci::ErrorCode error_code) {
  LOG_DEBUG("Reason: %s ", hci::ErrorCodeText(error_code).c_str());
  auto entry = pairing_handler_map_.find(address);
  if (entry != pairing_handler_map_.end()) {
    LOG_DEBUG("Cancelling pairing handler for '%s'", address.ToString().c_str());
    entry->second->Cancel();
  }
}

void SecurityManagerImpl::OnConnectionFailed(hci::Address address,
                                             bluetooth::l2cap::classic::FixedChannelManager::ConnectionResult result) {
  LOG_DEBUG("HCI Reason: %s ", hci::ErrorCodeText(result.hci_error).c_str());
  LOG_DEBUG("L2CAP Reason: %d ", result.connection_result_code);
void SecurityManagerImpl::OnConnectionClosed(hci::Address address) {
  auto entry = pairing_handler_map_.find(address);
  if (entry != pairing_handler_map_.end()) {
    LOG_DEBUG("Cancelling pairing handler for '%s'", address.ToString().c_str());
@@ -312,7 +301,7 @@ void SecurityManagerImpl::OnPairingHandlerComplete(hci::Address address, Pairing
  auto entry = pairing_handler_map_.find(address);
  if (entry != pairing_handler_map_.end()) {
    pairing_handler_map_.erase(entry);
    security_manager_channel_->Disconnect(address);
    security_manager_channel_->Release(address);
  }
  if (!std::holds_alternative<PairingFailure>(status)) {
    NotifyDeviceBonded(hci::AddressWithType(address, hci::AddressType::PUBLIC_DEVICE_ADDRESS));
+1 −11
Original line number Diff line number Diff line
@@ -122,18 +122,8 @@ class SecurityManagerImpl : public channel::ISecurityManagerChannelListener, pub
   * When a conncetion closes we should clean up the pairing handler
   *
   * @param address Remote address
   * @param error_code HCI error
   */
  void OnConnectionClosed(hci::Address address, bluetooth::hci::ErrorCode error_code) override;

  /**
   * This can occur when a remote device isn't in range or doesn't agree with local device
   *
   * @param address Remote address
   * @param result holds hci error and connection error code
   */
  void OnConnectionFailed(hci::Address address,
                          bluetooth::l2cap::classic::FixedChannelManager::ConnectionResult result) override;
  void OnConnectionClosed(hci::Address address) override;

  /**
   * Pairing handler has finished or cancelled
Loading