From 178f8e5946266a4d1c9423f2301b59b882e179bb Mon Sep 17 00:00:00 2001 From: Jakub Pawlowski Date: Fri, 21 Aug 2020 17:39:11 +0200 Subject: [PATCH] Properly process the LE Long Term Key Request Stack in peripheral should properly accept and pass the LTK request. Bug: 155399771 Test: cert/run --host LeSecurityTest Tag: #gd-refactor Change-Id: I7fcce47310480a435386975756900734239e4203 --- gd/security/internal/security_manager_impl.cc | 21 +++++++++++-- gd/security/pairing_handler_le.cc | 7 ++++- gd/security/pairing_handler_le.h | 40 ++++++++++++++++++++++++ gd/security/test/pairing_handler_le_pair_test.cc | 3 ++ 4 files changed, 68 insertions(+), 3 deletions(-) diff --git a/gd/security/internal/security_manager_impl.cc b/gd/security/internal/security_manager_impl.cc index b2d065ee9..2041d4945 100644 --- a/gd/security/internal/security_manager_impl.cc +++ b/gd/security/internal/security_manager_impl.cc @@ -338,10 +338,27 @@ void SecurityManagerImpl::OnEncryptionChange(hci::Address address, bool encrypte } void SecurityManagerImpl::OnHciLeEvent(hci::LeMetaEventView event) { - // hci::SubeventCode::LONG_TERM_KEY_REQUEST, + hci::SubeventCode code = event.GetSubeventCode(); + + if (code == hci::SubeventCode::LONG_TERM_KEY_REQUEST) { + hci::LeLongTermKeyRequestView le_long_term_key_request_view = hci::LeLongTermKeyRequestView::Create(event); + if (!le_long_term_key_request_view.IsValid()) { + LOG_ERROR("Invalid LeLongTermKeyRequestView packet received"); + return; + } + + if (le_long_term_key_request_view.GetConnectionHandle() == pending_le_pairing_.connection_handle_) { + pending_le_pairing_.handler_->OnHciLeEvent(event); + return; + } + + LOG_INFO("Unhandled HCI LE security event, code %s", hci::SubeventCodeText(code).c_str()); + return; + } + // hci::SubeventCode::READ_LOCAL_P256_PUBLIC_KEY_COMPLETE, // hci::SubeventCode::GENERATE_DHKEY_COMPLETE, - LOG_ERROR("Unhandled HCI LE security event"); + LOG_ERROR("Unhandled HCI LE security event, code %s", hci::SubeventCodeText(code).c_str()); } void SecurityManagerImpl::OnPairingPromptAccepted(const bluetooth::hci::AddressWithType& address, bool confirmed) { diff --git a/gd/security/pairing_handler_le.cc b/gd/security/pairing_handler_le.cc index 12cf967d2..dec6afd4c 100644 --- a/gd/security/pairing_handler_le.cc +++ b/gd/security/pairing_handler_le.cc @@ -113,8 +113,10 @@ void PairingHandlerLe::PairingMain(InitialInformations i) { if (IAmMaster(i)) { LOG_INFO("Sending start encryption request"); SendHciLeStartEncryption(i, i.connection_handle, {0}, {0}, ltk); + } else { + auto ltk_req = WaitLeLongTermKeyRequest(); + SendHciLeLongTermKeyReply(i, i.connection_handle, ltk); } - } else { // 2.3.5.5 LE legacy pairing phase 2 LOG_INFO("Pairing Phase 2 LE legacy pairing Started"); @@ -138,6 +140,9 @@ void PairingHandlerLe::PairingMain(InitialInformations i) { if (IAmMaster(i)) { LOG_INFO("Sending start encryption request"); SendHciLeStartEncryption(i, i.connection_handle, {0}, {0}, stk); + } else { + auto ltk_req = WaitLeLongTermKeyRequest(); + SendHciLeLongTermKeyReply(i, i.connection_handle, stk); } } diff --git a/gd/security/pairing_handler_le.h b/gd/security/pairing_handler_le.h index 31abba081..542187ecc 100644 --- a/gd/security/pairing_handler_le.h +++ b/gd/security/pairing_handler_le.h @@ -145,6 +145,12 @@ class PairingHandlerLe { })); } + void SendHciLeLongTermKeyReply(const InitialInformations& i, uint16_t conn_handle, const Octet16& ltk) { + i.le_security_interface->EnqueueCommand( + hci::LeLongTermKeyRequestReplyBuilder::Create(conn_handle, ltk), + i.l2cap_handler->BindOnce([](hci::CommandCompleteView) {})); + } + std::variant WaitEncryptionChanged() { PairingEvent e = WaitForEvent(); if (e.type != PairingEvent::HCI_EVENT) return PairingFailure("Was expecting HCI event but received something else"); @@ -170,6 +176,31 @@ class PairingHandlerLe { return PairingFailure("Was expecting Encryption Change or Key Refresh Complete but received something else"); } + std::variant WaitLeLongTermKeyRequest() { + PairingEvent e = WaitForEvent(); + if (e.type != PairingEvent::HCI_EVENT) return PairingFailure("Was expecting HCI event but received something else"); + + if (!e.hci_event->IsValid()) return PairingFailure("Received invalid HCI event"); + + if (e.hci_event->GetEventCode() != hci::EventCode::LE_META_EVENT) return PairingFailure("Was expecting LE event"); + + hci::LeMetaEventView le_event = hci::LeMetaEventView::Create(*e.hci_event); + if (!le_event.IsValid()) { + return PairingFailure("Invalid LE Event received"); + } + + if (le_event.GetSubeventCode() != hci::SubeventCode::LONG_TERM_KEY_REQUEST) { + return PairingFailure("Was expecting Long Term Key Request"); + } + + hci::LeLongTermKeyRequestView ltk_req_packet = hci::LeLongTermKeyRequestView::Create(le_event); + if (!ltk_req_packet.IsValid()) { + return PairingFailure("Invalid LE Long Term Key Request received"); + } + + return ltk_req_packet; + } + inline bool IAmMaster(const InitialInformations& i) { return i.my_role == hci::Role::MASTER; } @@ -259,6 +290,15 @@ class PairingHandlerLe { pairing_thread_blocker_.notify_one(); } + /* HCI LE event received from remote device */ + void OnHciLeEvent(hci::LeMetaEventView hci_event) { + { + std::unique_lock lock(queue_guard); + queue.push(PairingEvent(std::move(hci_event))); + } + pairing_thread_blocker_.notify_one(); + } + /* Blocks the pairing process until some external interaction, or timeout happens */ PairingEvent WaitForEvent() { std::unique_lock lock(queue_guard); diff --git a/gd/security/test/pairing_handler_le_pair_test.cc b/gd/security/test/pairing_handler_le_pair_test.cc index 0f5bfaa0b..62fe0fdf4 100644 --- a/gd/security/test/pairing_handler_le_pair_test.cc +++ b/gd/security/test/pairing_handler_le_pair_test.cc @@ -262,6 +262,9 @@ class PairingHandlerPairTest : public testing::Test { EncryptionChangeBuilder::Create(ErrorCode::SUCCESS, CONN_HANDLE_MASTER, EncryptionEnabled::ON))); pairing_handler_b->OnHciEvent(EventBuilderToView( + hci::LeLongTermKeyRequestBuilder::Create(CONN_HANDLE_SLAVE, {0,0,0,0,0,0,0,0}, 0))); + + pairing_handler_b->OnHciEvent(EventBuilderToView( EncryptionChangeBuilder::Create(ErrorCode::SUCCESS, CONN_HANDLE_SLAVE, EncryptionEnabled::ON))); }); } -- 2.11.0