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

Commit ca90aba4 authored by Jakub Pawlowski's avatar Jakub Pawlowski
Browse files

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
parent faad53c7
Loading
Loading
Loading
Loading
+19 −2
Original line number Diff line number Diff line
@@ -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) {
+6 −1
Original line number Diff line number Diff line
@@ -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);
    }
  }

+40 −0
Original line number Diff line number Diff line
@@ -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<PairingFailure, EncryptionChangeView, EncryptionKeyRefreshCompleteView> 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<PairingFailure, hci::LeLongTermKeyRequestView> 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<std::mutex> 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<std::mutex> lock(queue_guard);
+3 −0
Original line number Diff line number Diff line
@@ -261,6 +261,9 @@ class PairingHandlerPairTest : public testing::Test {
          pairing_handler_a->OnHciEvent(EventBuilderToView(
              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)));
        });