aboutsummaryrefslogtreecommitdiff
path: root/gd/security/pairing_handler_le_unittest.cc
diff options
context:
space:
mode:
Diffstat (limited to 'gd/security/pairing_handler_le_unittest.cc')
-rw-r--r--gd/security/pairing_handler_le_unittest.cc122
1 files changed, 78 insertions, 44 deletions
diff --git a/gd/security/pairing_handler_le_unittest.cc b/gd/security/pairing_handler_le_unittest.cc
index 1f585fe9c..690c080c0 100644
--- a/gd/security/pairing_handler_le_unittest.cc
+++ b/gd/security/pairing_handler_le_unittest.cc
@@ -21,6 +21,7 @@
#include <memory>
#include "os/log.h"
+#include "os/rand.h"
#include "security/pairing_handler_le.h"
#include "security/test/mocks.h"
@@ -29,6 +30,7 @@ using ::testing::Eq;
using ::testing::Field;
using ::testing::VariantWith;
+using bluetooth::os::GenerateRandom;
using bluetooth::security::CommandView;
namespace bluetooth {
@@ -45,18 +47,6 @@ CommandView BuilderToView(std::unique_ptr<BasePacketBuilder> builder) {
return CommandView::Create(temp_cmd_view);
}
-std::condition_variable outgoing_l2cap_blocker_;
-std::optional<bluetooth::security::CommandView> outgoing_l2cap_packet_;
-
-bool WaitForOutgoingL2capPacket() {
- std::mutex mutex;
- std::unique_lock<std::mutex> lock(mutex);
- if (outgoing_l2cap_blocker_.wait_for(lock, std::chrono::seconds(5)) == std::cv_status::timeout) {
- return false;
- }
- return true;
-}
-
class PairingResultHandlerMock {
public:
MOCK_CONST_METHOD1(OnPairingFinished, void(PairingResultOrFailure));
@@ -111,16 +101,42 @@ class PairingHandlerUnitTest : public testing::Test {
outgoing_l2cap_blocker_.notify_one();
}
+ std::optional<bluetooth::security::CommandView> WaitForOutgoingL2capPacket() {
+ std::mutex mutex;
+ std::unique_lock<std::mutex> lock(mutex);
+
+ // It is possible that we lost wakeup from condition_variable, check if data is already waiting to be processed
+ if (outgoing_l2cap_packet_ != std::nullopt) {
+ std::optional<bluetooth::security::CommandView> tmp = std::nullopt;
+ outgoing_l2cap_packet_.swap(tmp);
+ return tmp;
+ }
+
+ // Data not ready yet, wait for it.
+ if (outgoing_l2cap_blocker_.wait_for(lock, std::chrono::seconds(5)) == std::cv_status::timeout) {
+ return std::nullopt;
+ }
+
+ std::optional<bluetooth::security::CommandView> tmp = std::nullopt;
+ outgoing_l2cap_packet_.swap(tmp);
+ return tmp;
+ }
+
public:
os::Thread* thread_;
os::Handler* handler_;
std::unique_ptr<common::BidiQueue<packet::PacketView<packet::kLittleEndian>, packet::BasePacketBuilder>> bidi_queue_;
std::unique_ptr<os::EnqueueBuffer<packet::BasePacketBuilder>> up_buffer_;
+ std::condition_variable outgoing_l2cap_blocker_;
+ std::optional<bluetooth::security::CommandView> outgoing_l2cap_packet_ = std::nullopt;
};
InitialInformations initial_informations{
- .my_role = hci::Role::MASTER,
+ .my_role = hci::Role::CENTRAL,
.my_connection_address = {{}, hci::AddressType::PUBLIC_DEVICE_ADDRESS},
+ .my_identity_address = {{}, hci::AddressType::PUBLIC_DEVICE_ADDRESS},
+ .my_identity_resolving_key =
+ {0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f},
.myPairingCapabilities = {.io_capability = IoCapability::NO_INPUT_NO_OUTPUT,
.oob_data_flag = OobDataFlag::NOT_PRESENT,
@@ -144,8 +160,9 @@ TEST_F(PairingHandlerUnitTest, test_phase_1_failure) {
std::unique_ptr<PairingHandlerLe> pairing_handler =
std::make_unique<PairingHandlerLe>(PairingHandlerLe::PHASE1, initial_informations);
- EXPECT_TRUE(WaitForOutgoingL2capPacket());
- EXPECT_EQ(outgoing_l2cap_packet_->GetCode(), Code::PAIRING_REQUEST);
+ std::optional<bluetooth::security::CommandView> pairing_request = WaitForOutgoingL2capPacket();
+ EXPECT_TRUE(pairing_request.has_value());
+ EXPECT_EQ(pairing_request->GetCode(), Code::PAIRING_REQUEST);
EXPECT_CALL(*pairingResult, OnPairingFinished(VariantWith<PairingFailure>(_))).Times(1);
@@ -154,8 +171,9 @@ TEST_F(PairingHandlerUnitTest, test_phase_1_failure) {
bad_pairing_response.IsValid();
pairing_handler->OnCommandView(bad_pairing_response);
- EXPECT_TRUE(WaitForOutgoingL2capPacket());
- EXPECT_EQ(outgoing_l2cap_packet_->GetCode(), Code::PAIRING_FAILED);
+ std::optional<bluetooth::security::CommandView> pairing_failure = WaitForOutgoingL2capPacket();
+ EXPECT_TRUE(pairing_failure.has_value());
+ EXPECT_EQ(pairing_failure->GetCode(), Code::PAIRING_FAILED);
}
TEST_F(PairingHandlerUnitTest, test_secure_connections_just_works) {
@@ -168,9 +186,10 @@ TEST_F(PairingHandlerUnitTest, test_secure_connections_just_works) {
std::unique_ptr<PairingHandlerLe> pairing_handler =
std::make_unique<PairingHandlerLe>(PairingHandlerLe::PHASE1, initial_informations);
- EXPECT_TRUE(WaitForOutgoingL2capPacket());
- EXPECT_EQ(outgoing_l2cap_packet_->GetCode(), Code::PAIRING_REQUEST);
- CommandView pairing_request = outgoing_l2cap_packet_.value();
+ std::optional<bluetooth::security::CommandView> pairing_request_pkt = WaitForOutgoingL2capPacket();
+ EXPECT_TRUE(pairing_request_pkt.has_value());
+ EXPECT_EQ(pairing_request_pkt->GetCode(), Code::PAIRING_REQUEST);
+ CommandView pairing_request = pairing_request_pkt.value();
auto pairing_response = BuilderToView(
PairingResponseBuilder::Create(IoCapability::KEYBOARD_DISPLAY, OobDataFlag::NOT_PRESENT,
@@ -179,10 +198,11 @@ TEST_F(PairingHandlerUnitTest, test_secure_connections_just_works) {
// Phase 1 finished.
// pairing public key
- EXPECT_TRUE(WaitForOutgoingL2capPacket());
- EXPECT_EQ(Code::PAIRING_PUBLIC_KEY, outgoing_l2cap_packet_->GetCode());
+ std::optional<bluetooth::security::CommandView> public_key_pkt = WaitForOutgoingL2capPacket();
+ EXPECT_TRUE(public_key_pkt.has_value());
+ EXPECT_EQ(Code::PAIRING_PUBLIC_KEY, public_key_pkt->GetCode());
EcdhPublicKey my_public_key;
- auto ppkv = PairingPublicKeyView::Create(outgoing_l2cap_packet_.value());
+ auto ppkv = PairingPublicKeyView::Create(public_key_pkt.value());
ppkv.IsValid();
my_public_key.x = ppkv.GetPublicKeyX();
my_public_key.y = ppkv.GetPublicKeyY();
@@ -197,7 +217,7 @@ TEST_F(PairingHandlerUnitTest, test_secure_connections_just_works) {
Octet16 ra, rb;
ra = rb = {0};
- Octet16 Nb = PairingHandlerLe::GenerateRandom<16>();
+ Octet16 Nb = GenerateRandom<16>();
// Compute confirm
Octet16 Cb = crypto_toolbox::f4((uint8_t*)public_key.x.data(), (uint8_t*)my_public_key.x.data(), Nb, 0);
@@ -205,9 +225,10 @@ TEST_F(PairingHandlerUnitTest, test_secure_connections_just_works) {
pairing_handler->OnCommandView(BuilderToView(PairingConfirmBuilder::Create(Cb)));
// random
- EXPECT_TRUE(WaitForOutgoingL2capPacket());
- EXPECT_EQ(Code::PAIRING_RANDOM, outgoing_l2cap_packet_->GetCode());
- auto prv = PairingRandomView::Create(outgoing_l2cap_packet_.value());
+ std::optional<bluetooth::security::CommandView> random_pkt = WaitForOutgoingL2capPacket();
+ EXPECT_TRUE(random_pkt.has_value());
+ EXPECT_EQ(Code::PAIRING_RANDOM, random_pkt->GetCode());
+ auto prv = PairingRandomView::Create(random_pkt.value());
prv.IsValid();
Octet16 Na = prv.GetRandomValue();
@@ -216,9 +237,9 @@ TEST_F(PairingHandlerUnitTest, test_secure_connections_just_works) {
// Start of authentication stage 2
uint8_t a[7];
uint8_t b[7];
- memcpy(b, initial_informations.remote_connection_address.GetAddress().address, 6);
+ memcpy(b, initial_informations.remote_connection_address.GetAddress().data(), hci::Address::kLength);
b[6] = (uint8_t)initial_informations.remote_connection_address.GetAddressType();
- memcpy(a, initial_informations.my_connection_address.GetAddress().address, 6);
+ memcpy(a, initial_informations.my_connection_address.GetAddress().data(), hci::Address::kLength);
a[6] = (uint8_t)initial_informations.my_connection_address.GetAddressType();
Octet16 ltk, mac_key;
@@ -237,9 +258,10 @@ TEST_F(PairingHandlerUnitTest, test_secure_connections_just_works) {
Octet16 Ea = crypto_toolbox::f6(mac_key, Na, Nb, rb, iocapA.data(), a, b);
Octet16 Eb = crypto_toolbox::f6(mac_key, Nb, Na, ra, iocapB.data(), b, a);
- EXPECT_TRUE(WaitForOutgoingL2capPacket());
- EXPECT_EQ(Code::PAIRING_DH_KEY_CHECK, outgoing_l2cap_packet_->GetCode());
- auto pdhkcv = PairingDhKeyCheckView::Create(outgoing_l2cap_packet_.value());
+ std::optional<bluetooth::security::CommandView> dh_key_pkt = WaitForOutgoingL2capPacket();
+ EXPECT_TRUE(dh_key_pkt.has_value());
+ EXPECT_EQ(Code::PAIRING_DH_KEY_CHECK, dh_key_pkt->GetCode());
+ auto pdhkcv = PairingDhKeyCheckView::Create(dh_key_pkt.value());
pdhkcv.IsValid();
EXPECT_EQ(pdhkcv.GetDhKeyCheck(), Ea);
@@ -250,8 +272,11 @@ TEST_F(PairingHandlerUnitTest, test_secure_connections_just_works) {
}
InitialInformations initial_informations_trsi{
- .my_role = hci::Role::MASTER,
+ .my_role = hci::Role::CENTRAL,
.my_connection_address = hci::AddressWithType(),
+ .my_identity_address = {{}, hci::AddressType::PUBLIC_DEVICE_ADDRESS},
+ .my_identity_resolving_key =
+ {0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f},
.myPairingCapabilities = {.io_capability = IoCapability::NO_INPUT_NO_OUTPUT,
.oob_data_flag = OobDataFlag::NOT_PRESENT,
@@ -267,9 +292,9 @@ InitialInformations initial_informations_trsi{
.OnPairingFinished = OnPairingFinished,
};
-/* This test verifies that when remote slave device sends security request , and user
+/* This test verifies that when remote peripheral device sends security request , and user
* does accept the prompt, we do send pairing request */
-TEST_F(PairingHandlerUnitTest, test_remote_slave_initiating) {
+TEST_F(PairingHandlerUnitTest, test_remote_peripheral_initiating) {
initial_informations_trsi.proper_l2cap_interface = up_buffer_.get();
initial_informations_trsi.l2cap_handler = handler_;
initial_informations_trsi.user_interface_handler = handler_;
@@ -280,16 +305,20 @@ TEST_F(PairingHandlerUnitTest, test_remote_slave_initiating) {
// Simulate user accepting the pairing in UI
pairing_handler->OnUiAction(PairingEvent::PAIRING_ACCEPTED, 0x01 /* Non-zero value means success */);
- EXPECT_TRUE(WaitForOutgoingL2capPacket());
- EXPECT_EQ(Code::PAIRING_REQUEST, outgoing_l2cap_packet_->GetCode());
+ std::optional<bluetooth::security::CommandView> pairing_request_pkt = WaitForOutgoingL2capPacket();
+ EXPECT_TRUE(pairing_request_pkt.has_value());
+ EXPECT_EQ(Code::PAIRING_REQUEST, pairing_request_pkt->GetCode());
// We don't care for the rest of the flow, let it die.
pairing_handler.reset();
}
InitialInformations initial_informations_trmi{
- .my_role = hci::Role::SLAVE,
+ .my_role = hci::Role::PERIPHERAL,
.my_connection_address = hci::AddressWithType(),
+ .my_identity_address = {{}, hci::AddressType::PUBLIC_DEVICE_ADDRESS},
+ .my_identity_resolving_key =
+ {0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f},
.myPairingCapabilities = {.io_capability = IoCapability::NO_INPUT_NO_OUTPUT,
.oob_data_flag = OobDataFlag::NOT_PRESENT,
@@ -300,9 +329,13 @@ InitialInformations initial_informations_trmi{
.remotely_initiated = true,
.remote_connection_address = hci::AddressWithType(),
- .pairing_request = PairingRequestView::Create(BuilderToView(
- PairingRequestBuilder::Create(IoCapability::NO_INPUT_NO_OUTPUT, OobDataFlag::NOT_PRESENT,
- AuthReqMaskBondingFlag | AuthReqMaskMitm | AuthReqMaskSc, 16, 0x03, 0x03))),
+ .pairing_request = PairingRequestView::Create(BuilderToView(PairingRequestBuilder::Create(
+ IoCapability::NO_INPUT_NO_OUTPUT,
+ OobDataFlag::NOT_PRESENT,
+ AuthReqMaskBondingFlag | AuthReqMaskMitm | AuthReqMaskSc,
+ 16,
+ 0x03,
+ 0x03))),
.user_interface = &uiMock,
.le_security_interface = &leSecurityMock,
@@ -311,7 +344,7 @@ InitialInformations initial_informations_trmi{
/* This test verifies that when remote device sends pairing request, and user does accept the prompt, we do send proper
* reply back */
-TEST_F(PairingHandlerUnitTest, test_remote_master_initiating) {
+TEST_F(PairingHandlerUnitTest, test_remote_central_initiating) {
initial_informations_trmi.proper_l2cap_interface = up_buffer_.get();
initial_informations_trmi.l2cap_handler = handler_;
initial_informations_trmi.user_interface_handler = handler_;
@@ -322,8 +355,9 @@ TEST_F(PairingHandlerUnitTest, test_remote_master_initiating) {
// Simulate user accepting the pairing in UI
pairing_handler->OnUiAction(PairingEvent::PAIRING_ACCEPTED, 0x01 /* Non-zero value means success */);
- EXPECT_TRUE(WaitForOutgoingL2capPacket());
- EXPECT_EQ(Code::PAIRING_RESPONSE, outgoing_l2cap_packet_->GetCode());
+ std::optional<bluetooth::security::CommandView> pairing_response_pkt = WaitForOutgoingL2capPacket();
+ EXPECT_TRUE(pairing_response_pkt.has_value());
+ EXPECT_EQ(Code::PAIRING_RESPONSE, pairing_response_pkt->GetCode());
// Phase 1 finished.
// We don't care for the rest of the flow, it's handled in in other tests. let it die.