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

Commit 6bd76a60 authored by Treehugger Robot's avatar Treehugger Robot Committed by Gerrit Code Review
Browse files

Merge "Initial security manager API create/remove bond."

parents b31803e9 bb00e5ae
Loading
Loading
Loading
Loading
+6 −2
Original line number Diff line number Diff line
@@ -7,8 +7,11 @@ filegroup {
        "pairing_handler_le.cc",
        "pairing_handler_le_legacy.cc",
        "pairing_handler_le_secure_connections.cc",
        "security_manager.cc",
        "internal/security_manager_impl.cc",
        "security_module.cc",
    ]
        ":BluetoothSecurityChannelSources",
    ],
}

filegroup {
@@ -18,5 +21,6 @@ filegroup {
        "pairing_handler_le_unittest.cc",
        "test/fake_l2cap_test.cc",
        "test/pairing_handler_le_pair_test.cc",
    ]
        ":BluetoothSecurityChannelTestSources",
    ],
}
+13 −0
Original line number Diff line number Diff line
filegroup {
    name: "BluetoothSecurityChannelSources",
    srcs: [
        "security_manager_channel.cc",
    ]
}

filegroup {
    name: "BluetoothSecurityChannelTestSources",
    srcs: [
        "security_manager_channel_unittest.cc",
    ]
}
+93 −0
Original line number Diff line number Diff line
/******************************************************************************
 *
 *  Copyright 2019 The Android Open Source Project
 *
 *  Licensed under the Apache License, Version 2.0 (the "License");
 *  you may not use this file except in compliance with the License.
 *  You may obtain a copy of the License at:
 *
 *  http://www.apache.org/licenses/LICENSE-2.0
 *
 *  Unless required by applicable law or agreed to in writing, software
 *  distributed under the License is distributed on an "AS IS" BASIS,
 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *  See the License for the specific language governing permissions and
 *  limitations under the License.
 *
 ******************************************************************************/
#include "security_manager_channel.h"

#include "security/smp_packets.h"

using namespace bluetooth::hci;
using namespace bluetooth::packet;
using namespace bluetooth::security::channel;

void SecurityManagerChannel::SendCommand(std::shared_ptr<hci::Device> device,
                                         std::unique_ptr<SecurityCommandBuilder> command) {
  hci_security_interface_->EnqueueCommand(
      std::move(command), common::BindOnce(&SecurityManagerChannel::OnCommandComplete, common::Unretained(this)),
      handler_);
}

void SecurityManagerChannel::OnCommandComplete(CommandCompleteView packet) {
  ASSERT_LOG(packet.IsValid(), "Received invalid packet: %hx", packet.GetCommandOpCode());
  // TODO(optedoblivion): Verify HCI commands
}

void SecurityManagerChannel::OnHciEventReceived(EventPacketView packet) {
  ASSERT_LOG(listener_ != nullptr, "No listener set!");
  std::shared_ptr<Device> device = nullptr;
  auto event = EventPacketView::Create(std::move(packet));
  ASSERT_LOG(event.IsValid(), "Received invalid packet: %hhx", event.GetEventCode());
  const hci::EventCode code = event.GetEventCode();
  switch (code) {
    case hci::EventCode::CHANGE_CONNECTION_LINK_KEY_COMPLETE:
      listener_->OnChangeConnectionLinkKeyComplete(device,
                                                   hci::ChangeConnectionLinkKeyCompleteView::Create(std::move(event)));
      break;
    case hci::EventCode::MASTER_LINK_KEY_COMPLETE:
      listener_->OnMasterLinkKeyComplete(device, hci::MasterLinkKeyCompleteView::Create(std::move(event)));
      break;
    case hci::EventCode::PIN_CODE_REQUEST:
      listener_->OnPinCodeRequest(device, hci::PinCodeRequestView::Create(std::move(event)));
      break;
    case hci::EventCode::LINK_KEY_REQUEST:
      listener_->OnLinkKeyRequest(device, hci::LinkKeyRequestView::Create(std::move(event)));
      break;
    case hci::EventCode::LINK_KEY_NOTIFICATION:
      listener_->OnLinkKeyNotification(device, hci::LinkKeyNotificationView::Create(std::move(event)));
      break;
    case hci::EventCode::IO_CAPABILITY_REQUEST:
      listener_->OnIoCapabilityRequest(device, hci::IoCapabilityRequestView::Create(std::move(event)));
      break;
    case hci::EventCode::IO_CAPABILITY_RESPONSE:
      listener_->OnIoCapabilityResponse(device, IoCapabilityResponseView::Create(std::move(event)));
      break;
    case hci::EventCode::SIMPLE_PAIRING_COMPLETE:
      listener_->OnSimplePairingComplete(device, SimplePairingCompleteView::Create(std::move(event)));
      break;
    case hci::EventCode::RETURN_LINK_KEYS:
      listener_->OnReturnLinkKeys(device, hci::ReturnLinkKeysView::Create(std::move(event)));
      break;
    case hci::EventCode::ENCRYPTION_CHANGE:
      listener_->OnEncryptionChange(device, hci::EncryptionChangeView::Create(std::move(event)));
      break;
    case hci::EventCode::ENCRYPTION_KEY_REFRESH_COMPLETE:
      listener_->OnEncryptionKeyRefreshComplete(device,
                                                hci::EncryptionKeyRefreshCompleteView::Create(std::move(event)));
      break;
    case hci::EventCode::REMOTE_OOB_DATA_REQUEST:
      listener_->OnRemoteOobDataRequest(device, hci::RemoteOobDataRequestView::Create(std::move(event)));
      break;
    case hci::EventCode::USER_PASSKEY_NOTIFICATION:
      //      listener_->OnUserPasskeyNotification(device, <packet>);
      break;
    case hci::EventCode::KEYPRESS_NOTIFICATION:
      //      listener_->OnSendKeypressNotification(device, <packet>);
      break;
    default:
      ASSERT_LOG(false, "Invalid packet received: %hhx", code);
      break;
  }
}
+113 −0
Original line number Diff line number Diff line
/******************************************************************************
 *
 *  Copyright 2019 The Android Open Source Project
 *
 *  Licensed under the Apache License, Version 2.0 (the "License");
 *  you may not use this file except in compliance with the License.
 *  You may obtain a copy of the License at:
 *
 *  http://www.apache.org/licenses/LICENSE-2.0;
 *
 *  Unless required by applicable law or agreed to in writing, software
 *  distributed under the License is distributed on an "AS IS" BASIS,
 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *  See the License for the specific language governing permissions and
 *  limitations under the License.
 *
 ******************************************************************************/
#pragma once

#include <memory>
#include <vector>

#include "hci/classic_device.h"
#include "hci/hci_layer.h"
#include "hci/security_interface.h"
#include "security/smp_packets.h"

namespace bluetooth {
namespace security {
namespace channel {

using hci::CommandCompleteView;
using hci::EventPacketView;
using hci::SecurityCommandBuilder;
using hci::SecurityCommandView;

/**
 * Interface for listening to the channel for SMP commands.
 */
class ISecurityManagerChannelListener {
 public:
  virtual ~ISecurityManagerChannelListener() = default;

  virtual void OnChangeConnectionLinkKeyComplete(std::shared_ptr<hci::Device> device,
                                                 hci::ChangeConnectionLinkKeyCompleteView packet) = 0;
  virtual void OnMasterLinkKeyComplete(std::shared_ptr<hci::Device> device, hci::MasterLinkKeyCompleteView packet) = 0;
  virtual void OnPinCodeRequest(std::shared_ptr<hci::Device> device, hci::PinCodeRequestView packet) = 0;
  virtual void OnLinkKeyRequest(std::shared_ptr<hci::Device> device, hci::LinkKeyRequestView packet) = 0;
  virtual void OnLinkKeyNotification(std::shared_ptr<hci::Device> device, hci::LinkKeyNotificationView packet) = 0;
  virtual void OnIoCapabilityRequest(std::shared_ptr<hci::Device> device, hci::IoCapabilityRequestView packet) = 0;
  virtual void OnIoCapabilityResponse(std::shared_ptr<hci::Device> device, hci::IoCapabilityResponseView packet) = 0;
  virtual void OnSimplePairingComplete(std::shared_ptr<hci::Device> device, hci::SimplePairingCompleteView packet) = 0;
  virtual void OnReturnLinkKeys(std::shared_ptr<hci::Device> device, hci::ReturnLinkKeysView packet) = 0;
  virtual void OnEncryptionChange(std::shared_ptr<hci::Device> device, hci::EncryptionChangeView packet) = 0;
  virtual void OnEncryptionKeyRefreshComplete(std::shared_ptr<hci::Device> device,
                                              hci::EncryptionKeyRefreshCompleteView packet) = 0;
  virtual void OnRemoteOobDataRequest(std::shared_ptr<hci::Device> device, hci::RemoteOobDataRequestView packet) = 0;
};

/**
 * Channel for consolidating traffic and making the transport agnostic.
 */
class SecurityManagerChannel {
 public:
  explicit SecurityManagerChannel(os::Handler* handler, hci::HciLayer* hci_layer)
      : listener_(nullptr),
        hci_security_interface_(hci_layer->GetSecurityInterface(
            common::Bind(&SecurityManagerChannel::OnHciEventReceived, common::Unretained(this)), handler)),
        handler_(handler) {}
  ~SecurityManagerChannel() {
    delete listener_;
  }

  /**
   * Send a given SMP command over the SecurityManagerChannel
   *
   * @param device target where command will be sent
   * @param command smp command to send
   */
  void SendCommand(std::shared_ptr<hci::Device> device, std::unique_ptr<SecurityCommandBuilder> command);

  /**
   * Sets the listener to listen for channel events
   *
   * @param listener the caller interested in events
   */
  void SetChannelListener(ISecurityManagerChannelListener* listener) {
    listener_ = listener;
  }

  /**
   * Called when an incoming HCI event happens
   *
   * @param event_packet
   */
  void OnHciEventReceived(EventPacketView packet);

  /**
   * Called when an HCI command is completed
   *
   * @param on_complete
   */
  void OnCommandComplete(CommandCompleteView packet);

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

}  // namespace channel
}  // namespace security
}  // namespace bluetooth
+276 −0
Original line number Diff line number Diff line
/******************************************************************************
 *
 *  Copyright 2019 The Android Open Source Project
 *
 *  Licensed under the Apache License, Version 2.0 (the "License");
 *  you may not use this file except in compliance with the License.
 *  You may obtain a copy of the License at:
 *
 *  http://www.apache.org/licenses/LICENSE-2.0
 *
 *  Unless required by applicable law or agreed to in writing, software
 *  distributed under the License is distributed on an "AS IS" BASIS,
 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *  See the License for the specific language governing permissions and
 *  limitations under the License.
 *
 ******************************************************************************/
#include "security_manager_channel.h"

#include <gtest/gtest.h>

#include "hci/device.h"
#include "hci/device_database.h"
#include "hci/hci_packets.h"
#include "packet/raw_builder.h"
#include "security/smp_packets.h"
#include "security/test/fake_hci_layer.h"

namespace bluetooth {
namespace security {
namespace channel {
namespace {

using bluetooth::security::channel::SecurityManagerChannel;
using hci::AuthenticationRequirements;
using hci::CommandCompleteBuilder;
using hci::Device;
using hci::DeviceDatabase;
using hci::IoCapabilityRequestReplyBuilder;
using hci::IoCapabilityRequestView;
using hci::OobDataPresent;
using hci::OpCode;
using os::Handler;
using os::Thread;
using packet::RawBuilder;

static DeviceDatabase kDeviceDatabase;

class TestPayloadBuilder : public PacketBuilder<kLittleEndian> {
 public:
  ~TestPayloadBuilder() override = default;
  size_t size() const override {
    return 1;
  }
  void Serialize(BitInserter& inserter) const override {}
  static std::unique_ptr<TestPayloadBuilder> Create() {
    return std::unique_ptr<TestPayloadBuilder>(new TestPayloadBuilder());
  }

 private:
  TestPayloadBuilder() : PacketBuilder<kLittleEndian>(){};
};

class SecurityManagerChannelCallback : public ISecurityManagerChannelListener {
 public:
  // HCI
  bool receivedChangeConnectionLinkKeyComplete = false;
  bool receivedMasterLinkKeyComplete = false;
  bool receivedPinCodeRequest = false;
  bool receivedLinkKeyRequest = false;
  bool receivedLinkKeyNotification = false;
  bool receivedIoCapabilityRequest = false;
  bool receivedIoCapabilityResponse = false;
  bool receivedSimplePairingComplete = false;
  bool receivedReturnLinkKeys = false;
  bool receivedEncryptionChange = false;
  bool receivedEncryptionKeyRefreshComplete = false;
  bool receivedRemoteOobDataRequest = false;

  void OnChangeConnectionLinkKeyComplete(std::shared_ptr<hci::Device> device,
                                         hci::ChangeConnectionLinkKeyCompleteView packet) {
    EXPECT_TRUE(packet.IsValid());
    receivedChangeConnectionLinkKeyComplete = true;
  }
  void OnMasterLinkKeyComplete(std::shared_ptr<hci::Device> device, hci::MasterLinkKeyCompleteView packet) {
    EXPECT_TRUE(packet.IsValid());
    receivedMasterLinkKeyComplete = true;
  }
  void OnPinCodeRequest(std::shared_ptr<hci::Device> device, hci::PinCodeRequestView packet) {
    EXPECT_TRUE(packet.IsValid());
    receivedPinCodeRequest = true;
  }
  void OnLinkKeyRequest(std::shared_ptr<hci::Device> device, hci::LinkKeyRequestView packet) {
    EXPECT_TRUE(packet.IsValid());
    receivedLinkKeyRequest = true;
  }
  void OnLinkKeyNotification(std::shared_ptr<hci::Device> device, hci::LinkKeyNotificationView packet) {
    EXPECT_TRUE(packet.IsValid());
    receivedLinkKeyNotification = true;
  }
  void OnIoCapabilityRequest(std::shared_ptr<Device> device, hci::IoCapabilityRequestView packet) {
    EXPECT_TRUE(packet.IsValid());
    receivedIoCapabilityRequest = true;
  }
  void OnIoCapabilityResponse(std::shared_ptr<Device> device, hci::IoCapabilityResponseView packet) {
    EXPECT_TRUE(packet.IsValid());
    receivedIoCapabilityResponse = true;
  }
  void OnSimplePairingComplete(std::shared_ptr<Device> device, hci::SimplePairingCompleteView packet) {
    EXPECT_TRUE(packet.IsValid());
    receivedSimplePairingComplete = true;
  }
  void OnReturnLinkKeys(std::shared_ptr<Device> device, hci::ReturnLinkKeysView packet) {
    EXPECT_TRUE(packet.IsValid());
    receivedReturnLinkKeys = true;
  }
  void OnEncryptionChange(std::shared_ptr<Device> device, hci::EncryptionChangeView packet) {
    EXPECT_TRUE(packet.IsValid());
    receivedEncryptionChange = true;
  }
  void OnEncryptionKeyRefreshComplete(std::shared_ptr<Device> device, hci::EncryptionKeyRefreshCompleteView packet) {
    EXPECT_TRUE(packet.IsValid());
    receivedEncryptionKeyRefreshComplete = true;
  }
  void OnRemoteOobDataRequest(std::shared_ptr<Device> device, hci::RemoteOobDataRequestView packet) {
    EXPECT_TRUE(packet.IsValid());
    receivedRemoteOobDataRequest = true;
  }
};

class SecurityManagerChannelTest : public ::testing::Test {
 protected:
  void SetUp() override {
    device_ = kDeviceDatabase.CreateClassicDevice(hci::Address({0x01, 0x02, 0x03, 0x04, 0x05, 0x06}));
    handler_ = new Handler(&thread_);
    callback_ = new SecurityManagerChannelCallback();
    hci_layer_ = new FakeHciLayer();
    fake_registry_.InjectTestModule(&FakeHciLayer::Factory, hci_layer_);
    fake_registry_.Start<FakeHciLayer>(&thread_);
    channel_ = new SecurityManagerChannel(handler_, hci_layer_);
    channel_->SetChannelListener(callback_);
  }

  void TearDown() override {
    channel_->SetChannelListener(nullptr);
    handler_->Clear();
    fake_registry_.SynchronizeModuleHandler(&FakeHciLayer::Factory, std::chrono::milliseconds(20));
    fake_registry_.StopAll();
    delete handler_;
    delete channel_;
    delete callback_;
  }

  TestModuleRegistry fake_registry_;
  Thread& thread_ = fake_registry_.GetTestThread();
  Handler* handler_ = nullptr;
  FakeHciLayer* hci_layer_ = nullptr;
  SecurityManagerChannel* channel_ = nullptr;
  SecurityManagerChannelCallback* callback_ = nullptr;
  std::shared_ptr<Device> device_ = nullptr;
};

TEST_F(SecurityManagerChannelTest, setup_teardown) {}

TEST_F(SecurityManagerChannelTest, recv_io_cap_request) {
  hci_layer_->IncomingEvent(hci::IoCapabilityRequestBuilder::Create(device_->GetAddress()));
  EXPECT_TRUE(callback_->receivedIoCapabilityRequest);
}

TEST_F(SecurityManagerChannelTest, send_io_cap_request_reply) {
  // Arrange
  hci::IoCapability io_capability = (hci::IoCapability)0x00;
  OobDataPresent oob_present = (OobDataPresent)0x00;
  AuthenticationRequirements authentication_requirements = (AuthenticationRequirements)0x00;
  auto packet = hci::IoCapabilityRequestReplyBuilder::Create(device_->GetAddress(), io_capability, oob_present,
                                                             authentication_requirements);

  // Act
  channel_->SendCommand(device_, std::move(packet));
  auto last_command = std::move(hci_layer_->GetLastCommand()->command);
  auto command_packet = GetPacketView(std::move(last_command));
  hci::CommandPacketView packet_view = hci::CommandPacketView::Create(command_packet);

  // Assert
  EXPECT_TRUE(packet_view.IsValid());
  EXPECT_EQ(OpCode::IO_CAPABILITY_REQUEST_REPLY, packet_view.GetOpCode());
}

TEST_F(SecurityManagerChannelTest, send_io_cap_request_neg_reply) {
  // Arrange
  auto packet =
      hci::IoCapabilityRequestNegativeReplyBuilder::Create(device_->GetAddress(), hci::ErrorCode::COMMAND_DISALLOWED);

  // Act
  channel_->SendCommand(device_, std::move(packet));
  auto last_command = std::move(hci_layer_->GetLastCommand()->command);
  auto command_packet = GetPacketView(std::move(last_command));
  hci::CommandPacketView packet_view = hci::CommandPacketView::Create(command_packet);

  // Assert
  EXPECT_TRUE(packet_view.IsValid());
  EXPECT_EQ(OpCode::IO_CAPABILITY_REQUEST_NEGATIVE_REPLY, packet_view.GetOpCode());
}

TEST_F(SecurityManagerChannelTest, recv_io_cap_response) {
  hci::IoCapability io_capability = (hci::IoCapability)0x00;
  OobDataPresent oob_present = (OobDataPresent)0x00;
  AuthenticationRequirements authentication_requirements = (AuthenticationRequirements)0x00;
  hci_layer_->IncomingEvent(hci::IoCapabilityResponseBuilder::Create(device_->GetAddress(), io_capability, oob_present,
                                                                     authentication_requirements));
  EXPECT_TRUE(callback_->receivedIoCapabilityResponse);
}

TEST_F(SecurityManagerChannelTest, recv_pin_code_request) {
  hci_layer_->IncomingEvent(hci::PinCodeRequestBuilder::Create(device_->GetAddress()));
  EXPECT_TRUE(callback_->receivedPinCodeRequest);
}

TEST_F(SecurityManagerChannelTest, send_pin_code_request_reply) {}

TEST_F(SecurityManagerChannelTest, send_pin_code_request_neg_reply) {}

TEST_F(SecurityManagerChannelTest, recv_user_passkey_notification) {}

TEST_F(SecurityManagerChannelTest, send_user_confirmation_request_reply) {}

TEST_F(SecurityManagerChannelTest, send_user_confirmation_request_neg_reply) {}

TEST_F(SecurityManagerChannelTest, recv_remote_oob_data_request) {}

TEST_F(SecurityManagerChannelTest, send_remote_oob_data_request_reply) {}

TEST_F(SecurityManagerChannelTest, send_remote_oob_data_request_neg_reply) {}

TEST_F(SecurityManagerChannelTest, send_read_local_oob_data) {}

TEST_F(SecurityManagerChannelTest, send_read_local_oob_extended_data) {}

TEST_F(SecurityManagerChannelTest, recv_link_key_request) {}

TEST_F(SecurityManagerChannelTest, recv_link_key_notification) {}

TEST_F(SecurityManagerChannelTest, recv_master_link_complete) {}

TEST_F(SecurityManagerChannelTest, recv_change_connection_link_key_complete) {}

TEST_F(SecurityManagerChannelTest, recv_return_link_keys) {}

TEST_F(SecurityManagerChannelTest, send_link_key_reply) {}

TEST_F(SecurityManagerChannelTest, send_link_key_neg_reply) {}

TEST_F(SecurityManagerChannelTest, send_read_stored_link_key) {}

TEST_F(SecurityManagerChannelTest, send_write_stored_link_key) {}

TEST_F(SecurityManagerChannelTest, send_delete_stored_link_key) {}

TEST_F(SecurityManagerChannelTest, recv_encryption_change) {}

TEST_F(SecurityManagerChannelTest, send_refresh_encryption_key) {}

TEST_F(SecurityManagerChannelTest, send_read_encryption_key_size) {}

TEST_F(SecurityManagerChannelTest, recv_simple_pairing_complete) {}

TEST_F(SecurityManagerChannelTest, send_read_simple_pairing_mode) {}

TEST_F(SecurityManagerChannelTest, send_write_simple_pairing_mode) {}

TEST_F(SecurityManagerChannelTest, send_keypress_notification) {}

}  // namespace
}  // namespace channel
}  // namespace security
}  // namespace bluetooth
Loading