OSDN Git Service

HCI: Add an API for sending security commands
authorMyles Watson <mylesgw@google.com>
Tue, 20 Aug 2019 22:17:00 +0000 (15:17 -0700)
committerMyles Watson <mylesgw@google.com>
Wed, 21 Aug 2019 16:58:15 +0000 (09:58 -0700)
Bug: 138259341
Test: bluetooth_test_gd
Change-Id: Ia9e99c9b5013787a7ff6c5a78cd2538c2be9ccbd

gd/hci/hci_layer.cc
gd/hci/hci_layer.h
gd/hci/hci_layer_test.cc
gd/hci/hci_packets.pdl
gd/hci/le_security_interface.h [new file with mode: 0644]
gd/hci/security_interface.h [new file with mode: 0644]

index 7f86785..5c54266 100644 (file)
@@ -98,6 +98,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) {}
 
@@ -350,6 +386,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_;
 
@@ -402,6 +442,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) {
index e0c55dd..a5c9585 100644 (file)
@@ -25,6 +25,8 @@
 #include "common/class_of_device.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;
index 7d3fd77..55f6c38 100644 (file)
@@ -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();
index 036bcec..b70d392 100644 (file)
@@ -1931,7 +1931,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) {
diff --git a/gd/hci/le_security_interface.h b/gd/hci/le_security_interface.h
new file mode 100644 (file)
index 0000000..e282791
--- /dev/null
@@ -0,0 +1,45 @@
+/*
+ * 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
diff --git a/gd/hci/security_interface.h b/gd/hci/security_interface.h
new file mode 100644 (file)
index 0000000..efb20d0
--- /dev/null
@@ -0,0 +1,49 @@
+/*
+ * 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 SecurityInterface {
+ public:
+  SecurityInterface() = default;
+  virtual ~SecurityInterface() = default;
+  DISALLOW_COPY_AND_ASSIGN(SecurityInterface);
+
+  virtual void EnqueueCommand(std::unique_ptr<SecurityCommandBuilder> command,
+                              common::OnceCallback<void(CommandCompleteView)> on_complete, os::Handler* handler) = 0;
+
+  virtual void EnqueueCommand(std::unique_ptr<SecurityCommandBuilder> command,
+                              common::OnceCallback<void(CommandStatusView)> on_status, os::Handler* handler) = 0;
+
+  static constexpr hci::EventCode SecurityEvents[] = {
+      hci::EventCode::ENCRYPTION_CHANGE,         hci::EventCode::CHANGE_CONNECTION_LINK_KEY_COMPLETE,
+      hci::EventCode::MASTER_LINK_KEY_COMPLETE,  hci::EventCode::RETURN_LINK_KEYS,
+      hci::EventCode::PIN_CODE_REQUEST,          hci::EventCode::LINK_KEY_REQUEST,
+      hci::EventCode::LINK_KEY_NOTIFICATION,     hci::EventCode::ENCRYPTION_KEY_REFRESH_COMPLETE,
+      hci::EventCode::IO_CAPABILITY_REQUEST,     hci::EventCode::IO_CAPABILITY_RESPONSE,
+      hci::EventCode::REMOTE_OOB_DATA_REQUEST,   hci::EventCode::SIMPLE_PAIRING_COMPLETE,
+      hci::EventCode::USER_PASSKEY_NOTIFICATION, hci::EventCode::KEYPRESS_NOTIFICATION,
+  };
+};
+}  // namespace hci
+}  // namespace bluetooth