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

Commit 38fbb220 authored by Myles Watson's avatar Myles Watson
Browse files

HCI: Add an API for sending security commands

Bug: 138259341
Test: bluetooth_test_gd
Change-Id: Ia9e99c9b5013787a7ff6c5a78cd2538c2be9ccbd
parent 1fdc5fa1
Loading
Loading
Loading
Loading
+56 −0
Original line number Original line Diff line number Diff line
@@ -98,6 +98,42 @@ void on_hci_timeout(OpCode op_code) {
}
}
}  // namespace
}  // namespace


class SecurityInterfaceImpl : public SecurityInterface {
 public:
  SecurityInterfaceImpl(HciLayer& hci) : hci_(hci) {}
  virtual ~SecurityInterfaceImpl() = default;

  virtual void EnqueueCommand(std::unique_ptr<SecurityCommandBuilder> command,
                              common::OnceCallback<void(CommandCompleteView)> on_complete,
                              os::Handler* handler) override {
    hci_.EnqueueCommand(std::move(command), std::move(on_complete), handler);
  }

  virtual void EnqueueCommand(std::unique_ptr<SecurityCommandBuilder> command,
                              common::OnceCallback<void(CommandStatusView)> on_status, os::Handler* handler) override {
    hci_.EnqueueCommand(std::move(command), std::move(on_status), handler);
  }
  HciLayer& hci_;
};

class LeSecurityInterfaceImpl : public LeSecurityInterface {
 public:
  LeSecurityInterfaceImpl(HciLayer& hci) : hci_(hci) {}
  virtual ~LeSecurityInterfaceImpl() = default;

  virtual void EnqueueCommand(std::unique_ptr<LeSecurityCommandBuilder> command,
                              common::OnceCallback<void(CommandCompleteView)> on_complete,
                              os::Handler* handler) override {
    hci_.EnqueueCommand(std::move(command), std::move(on_complete), handler);
  }

  virtual void EnqueueCommand(std::unique_ptr<LeSecurityCommandBuilder> command,
                              common::OnceCallback<void(CommandStatusView)> on_status, os::Handler* handler) override {
    hci_.EnqueueCommand(std::move(command), std::move(on_status), handler);
  }
  HciLayer& hci_;
};

struct HciLayer::impl : public hal::HciHalCallbacks {
struct HciLayer::impl : public hal::HciHalCallbacks {
  impl(HciLayer& module) : hal_(nullptr), module_(module) {}
  impl(HciLayer& module) : hal_(nullptr), module_(module) {}


@@ -350,6 +386,10 @@ struct HciLayer::impl : public hal::HciHalCallbacks {
  // A reference to the HciLayer module
  // A reference to the HciLayer module
  HciLayer& module_;
  HciLayer& module_;


  // Interfaces
  SecurityInterfaceImpl security_interface{module_};
  LeSecurityInterfaceImpl le_security_interface{module_};

  // Command Handling
  // Command Handling
  std::list<CommandQueueEntry> command_queue_;
  std::list<CommandQueueEntry> command_queue_;


@@ -402,6 +442,22 @@ void HciLayer::UnregisterLeEventHandler(SubeventCode subevent_code) {
  impl_->UnregisterLeEventHandler(subevent_code);
  impl_->UnregisterLeEventHandler(subevent_code);
}
}


const SecurityInterface* HciLayer::GetSecurityInterface(common::Callback<void(EventPacketView)> event_handler,
                                                        os::Handler* handler) {
  for (const auto event : SecurityInterface::SecurityEvents) {
    RegisterEventHandler(event, event_handler, handler);
  }
  return &impl_->security_interface;
}

const LeSecurityInterface* HciLayer::GetLeSecurityInterface(common::Callback<void(LeMetaEventView)> event_handler,
                                                            os::Handler* handler) {
  for (const auto subevent : LeSecurityInterface::LeSecurityEvents) {
    RegisterLeEventHandler(subevent, event_handler, handler);
  }
  return &impl_->le_security_interface;
}

const ModuleFactory HciLayer::Factory = ModuleFactory([]() { return new HciLayer(); });
const ModuleFactory HciLayer::Factory = ModuleFactory([]() { return new HciLayer(); });


void HciLayer::ListDependencies(ModuleList* list) {
void HciLayer::ListDependencies(ModuleList* list) {
+8 −0
Original line number Original line Diff line number Diff line
@@ -25,6 +25,8 @@
#include "common/class_of_device.h"
#include "common/class_of_device.h"
#include "hal/hci_hal.h"
#include "hal/hci_hal.h"
#include "hci/hci_packets.h"
#include "hci/hci_packets.h"
#include "hci/le_security_interface.h"
#include "hci/security_interface.h"
#include "module.h"
#include "module.h"
#include "os/utils.h"
#include "os/utils.h"


@@ -55,6 +57,12 @@ class HciLayer : public Module {


  virtual void UnregisterLeEventHandler(SubeventCode subevent_code);
  virtual void UnregisterLeEventHandler(SubeventCode subevent_code);


  const SecurityInterface* GetSecurityInterface(common::Callback<void(EventPacketView)> event_handler,
                                                os::Handler* handler);

  const LeSecurityInterface* GetLeSecurityInterface(common::Callback<void(LeMetaEventView)> event_handler,
                                                    os::Handler* handler);

  static const ModuleFactory Factory;
  static const ModuleFactory Factory;


  void ListDependencies(ModuleList* list) override;
  void ListDependencies(ModuleList* list) override;
+82 −0
Original line number Original line Diff line number Diff line
@@ -158,6 +158,26 @@ class DependsOnHci : public Module {
                         GetHandler());
                         GetHandler());
  }
  }


  void SendSecurityCommandExpectingComplete(std::unique_ptr<SecurityCommandBuilder> command) {
    if (security_interface_ == nullptr) {
      security_interface_ = hci_->GetSecurityInterface(
          common::Bind(&DependsOnHci::handle_event<EventPacketView>, common::Unretained(this)), GetHandler());
    }
    hci_->EnqueueCommand(std::move(command),
                         common::Bind(&DependsOnHci::handle_event<CommandCompleteView>, common::Unretained(this)),
                         GetHandler());
  }

  void SendLeSecurityCommandExpectingComplete(std::unique_ptr<LeSecurityCommandBuilder> command) {
    if (le_security_interface_ == nullptr) {
      le_security_interface_ = hci_->GetLeSecurityInterface(
          common::Bind(&DependsOnHci::handle_event<LeMetaEventView>, common::Unretained(this)), GetHandler());
    }
    hci_->EnqueueCommand(std::move(command),
                         common::Bind(&DependsOnHci::handle_event<CommandCompleteView>, common::Unretained(this)),
                         GetHandler());
  }

  void SendAclData(std::unique_ptr<AclPacketBuilder> acl) {
  void SendAclData(std::unique_ptr<AclPacketBuilder> acl) {
    outgoing_acl_.push(std::move(acl));
    outgoing_acl_.push(std::move(acl));
    auto queue_end = hci_->GetAclQueueEnd();
    auto queue_end = hci_->GetAclQueueEnd();
@@ -216,6 +236,8 @@ class DependsOnHci : public Module {


 private:
 private:
  HciLayer* hci_ = nullptr;
  HciLayer* hci_ = nullptr;
  const SecurityInterface* security_interface_;
  const LeSecurityInterface* le_security_interface_;
  std::list<EventPacketView> incoming_events_;
  std::list<EventPacketView> incoming_events_;
  std::list<AclPacketView> incoming_acl_packets_;
  std::list<AclPacketView> incoming_acl_packets_;
  std::unique_ptr<std::promise<void>> event_promise_;
  std::unique_ptr<std::promise<void>> event_promise_;
@@ -478,6 +500,66 @@ TEST_F(HciTest, creditsTest) {
             .IsValid());
             .IsValid());
}
}


TEST_F(HciTest, leSecurityInterfaceTest) {
  // Send LeRand to the controller
  auto command_future = hal->GetSentCommandFuture();
  upper->SendLeSecurityCommandExpectingComplete(LeRandBuilder::Create());

  auto command_sent_status = command_future.wait_for(kTimeout);
  ASSERT_EQ(command_sent_status, std::future_status::ready);

  // Check the command
  auto sent_command = hal->GetSentCommand();
  ASSERT_LT(0, sent_command.size());
  LeRandView view = LeRandView::Create(LeSecurityCommandView::Create(CommandPacketView::Create(sent_command)));
  ASSERT_TRUE(view.IsValid());

  // Send a Command Complete to the host
  auto event_future = upper->GetReceivedEventFuture();
  uint8_t num_packets = 1;
  ErrorCode status = ErrorCode::SUCCESS;
  uint64_t rand = 0x0123456789abcdef;
  hal->callbacks->hciEventReceived(GetPacketBytes(LeRandCompleteBuilder::Create(num_packets, status, rand)));

  // Verify the event
  auto event_status = event_future.wait_for(kTimeout);
  ASSERT_EQ(event_status, std::future_status::ready);
  auto event = upper->GetReceivedEvent();
  ASSERT_TRUE(event.IsValid());
  ASSERT_EQ(EventCode::COMMAND_COMPLETE, event.GetEventCode());
  ASSERT_TRUE(LeRandCompleteView::Create(CommandCompleteView::Create(event)).IsValid());
}

TEST_F(HciTest, securityInterfacesTest) {
  // Send WriteSimplePairingMode to the controller
  auto command_future = hal->GetSentCommandFuture();
  Enable enable = Enable::ENABLED;
  upper->SendSecurityCommandExpectingComplete(WriteSimplePairingModeBuilder::Create(enable));

  auto command_sent_status = command_future.wait_for(kTimeout);
  ASSERT_EQ(command_sent_status, std::future_status::ready);

  // Check the command
  auto sent_command = hal->GetSentCommand();
  ASSERT_LT(0, sent_command.size());
  auto view = WriteSimplePairingModeView::Create(SecurityCommandView::Create(CommandPacketView::Create(sent_command)));
  ASSERT_TRUE(view.IsValid());

  // Send a Command Complete to the host
  auto event_future = upper->GetReceivedEventFuture();
  uint8_t num_packets = 1;
  ErrorCode status = ErrorCode::SUCCESS;
  hal->callbacks->hciEventReceived(GetPacketBytes(WriteSimplePairingModeCompleteBuilder::Create(num_packets, status)));

  // Verify the event
  auto event_status = event_future.wait_for(kTimeout);
  ASSERT_EQ(event_status, std::future_status::ready);
  auto event = upper->GetReceivedEvent();
  ASSERT_TRUE(event.IsValid());
  ASSERT_EQ(EventCode::COMMAND_COMPLETE, event.GetEventCode());
  ASSERT_TRUE(WriteSimplePairingModeCompleteView::Create(CommandCompleteView::Create(event)).IsValid());
}

TEST_F(HciTest, createConnectionTest) {
TEST_F(HciTest, createConnectionTest) {
  // Send CreateConnection to the controller
  // Send CreateConnection to the controller
  auto command_future = hal->GetSentCommandFuture();
  auto command_future = hal->GetSentCommandFuture();
+5 −1
Original line number Original line Diff line number Diff line
@@ -1931,7 +1931,11 @@ packet LeEncrypt : LeSecurityCommand (op_code = LE_ENCRYPT) {
}
}


packet LeRand : LeSecurityCommand (op_code = LE_RAND) {
packet LeRand : LeSecurityCommand (op_code = LE_RAND) {
  _payload_,  // placeholder (unimplemented)
}

packet LeRandComplete : CommandComplete (command_op_code = LE_RAND) {
  status : ErrorCode,
  random_number : 64,
}
}


packet LeStartEncryption : LeSecurityCommand (op_code = LE_START_ENCRYPTION) {
packet LeStartEncryption : LeSecurityCommand (op_code = LE_START_ENCRYPTION) {
+45 −0
Original line number Original line 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 "common/callback.h"
#include "hci/hci_packets.h"
#include "os/utils.h"

namespace bluetooth {
namespace hci {

class LeSecurityInterface {
 public:
  LeSecurityInterface() = default;
  virtual ~LeSecurityInterface() = default;
  DISALLOW_COPY_AND_ASSIGN(LeSecurityInterface);

  virtual void EnqueueCommand(std::unique_ptr<LeSecurityCommandBuilder> command,
                              common::OnceCallback<void(CommandCompleteView)> on_complete, os::Handler* handler) = 0;

  virtual void EnqueueCommand(std::unique_ptr<LeSecurityCommandBuilder> command,
                              common::OnceCallback<void(CommandStatusView)> on_status, os::Handler* handler) = 0;

  static constexpr hci::SubeventCode LeSecurityEvents[] = {
      hci::SubeventCode::LONG_TERM_KEY_REQUEST,
      hci::SubeventCode::READ_LOCAL_P256_PUBLIC_KEY_COMPLETE,
      hci::SubeventCode::GENERATE_DHKEY_COMPLETE,
  };
};
}  // namespace hci
}  // namespace bluetooth
Loading