}
} // 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) {}
// 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_;
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) {
#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"
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;
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();
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_;
.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();
}
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) {
--- /dev/null
+/*
+ * 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
--- /dev/null
+/*
+ * 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