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

Commit a164292c authored by Myles Watson's avatar Myles Watson Committed by android-build-merger
Browse files

Merge "HCI: Add an API for sending security commands" am: f29ecfc5 am: 947bf41c

am: 1b9b74a0

Change-Id: I828f0d634ae291c773504e27c6627c5d4b085b77
parents bbe17e7c 1b9b74a0
Loading
Loading
Loading
Loading
+56 −0
Original line number Diff line number Diff line
@@ -97,6 +97,42 @@ void on_hci_timeout(OpCode op_code) {
}
}  // 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 {
  impl(HciLayer& module) : hal_(nullptr), module_(module) {}

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

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

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

@@ -401,6 +441,22 @@ void HciLayer::UnregisterLeEventHandler(SubeventCode 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(); });

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

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

  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;

  void ListDependencies(ModuleList* list) override;
+82 −0
Original line number Diff line number Diff line
@@ -158,6 +158,26 @@ class DependsOnHci : public Module {
                         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) {
    outgoing_acl_.push(std::move(acl));
    auto queue_end = hci_->GetAclQueueEnd();
@@ -216,6 +236,8 @@ class DependsOnHci : public Module {

 private:
  HciLayer* hci_ = nullptr;
  const SecurityInterface* security_interface_;
  const LeSecurityInterface* le_security_interface_;
  std::list<EventPacketView> incoming_events_;
  std::list<AclPacketView> incoming_acl_packets_;
  std::unique_ptr<std::promise<void>> event_promise_;
@@ -478,6 +500,66 @@ TEST_F(HciTest, creditsTest) {
             .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) {
  // Send CreateConnection to the controller
  auto command_future = hal->GetSentCommandFuture();
+5 −1
Original line number Diff line number Diff line
@@ -1936,7 +1936,11 @@ packet LeEncrypt : LeSecurityCommand (op_code = LE_ENCRYPT) {
}

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) {
+45 −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 "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