// Copyright 2022 Google LLC // // 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 // // https://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. #include #include #include #include #include #include #include "fakes.h" #include "gmock/gmock.h" #include "gtest/gtest.h" #include "nearby.h" #include "nearby_event.h" #include "nearby_fp_client.h" #include "nearby_fp_library.h" #include "nearby_platform_ble.h" #include "nearby_platform_persistence.h" #include "nearby_utils.h" #pragma GCC diagnostic push #pragma GCC diagnostic ignored "-Wunused-const-variable" constexpr uint8_t kBobPrivateKey[32] = { 0x02, 0xB4, 0x37, 0xB0, 0xED, 0xD6, 0xBB, 0xD4, 0x29, 0x06, 0x4A, 0x4E, 0x52, 0x9F, 0xCB, 0xF1, 0xC4, 0x8D, 0x0D, 0x62, 0x49, 0x24, 0xD5, 0x92, 0x27, 0x4B, 0x7E, 0xD8, 0x11, 0x93, 0xD7, 0x63}; constexpr uint8_t kBobPublicKey[64] = { 0xF7, 0xD4, 0x96, 0xA6, 0x2E, 0xCA, 0x41, 0x63, 0x51, 0x54, 0x0A, 0xA3, 0x43, 0xBC, 0x69, 0x0A, 0x61, 0x09, 0xF5, 0x51, 0x50, 0x06, 0x66, 0xB8, 0x3B, 0x12, 0x51, 0xFB, 0x84, 0xFA, 0x28, 0x60, 0x79, 0x5E, 0xBD, 0x63, 0xD3, 0xB8, 0x83, 0x6F, 0x44, 0xA9, 0xA3, 0xE2, 0x8B, 0xB3, 0x40, 0x17, 0xE0, 0x15, 0xF5, 0x97, 0x93, 0x05, 0xD8, 0x49, 0xFD, 0xF8, 0xDE, 0x10, 0x12, 0x3B, 0x61, 0xD2}; constexpr uint8_t kAlicePrivateKey[32] = { 0xD7, 0x5E, 0x54, 0xC7, 0x7D, 0x76, 0x24, 0x89, 0xE5, 0x7C, 0xFA, 0x92, 0x37, 0x43, 0xF1, 0x67, 0x77, 0xA4, 0x28, 0x3D, 0x99, 0x80, 0x0B, 0xAC, 0x55, 0x58, 0x48, 0x38, 0x93, 0xE5, 0xB0, 0x6D}; constexpr uint8_t kAlicePublicKey[64] = { 0x36, 0xAC, 0x68, 0x2C, 0x50, 0x82, 0x15, 0x66, 0x8F, 0xBE, 0xFE, 0x24, 0x7D, 0x01, 0xD5, 0xEB, 0x96, 0xE6, 0x31, 0x8E, 0x85, 0x5B, 0x2D, 0x64, 0xB5, 0x19, 0x5D, 0x38, 0xEE, 0x7E, 0x37, 0xBE, 0x18, 0x38, 0xC0, 0xB9, 0x48, 0xC3, 0xF7, 0x55, 0x20, 0xE0, 0x7E, 0x70, 0xF0, 0x72, 0x91, 0x41, 0x9A, 0xCE, 0x2D, 0x28, 0x14, 0x3C, 0x5A, 0xDB, 0x2D, 0xBD, 0x98, 0xEE, 0x3C, 0x8E, 0x4F, 0xBF}; constexpr uint8_t kExpectedSharedSecret[32] = { 0x9D, 0xAD, 0xE4, 0xF8, 0x6A, 0xC3, 0x48, 0x8B, 0xBA, 0xC2, 0xAC, 0x34, 0xB5, 0xFE, 0x68, 0xA0, 0xEE, 0x5A, 0x67, 0x06, 0xF5, 0x43, 0xD9, 0x06, 0x1A, 0xD5, 0x78, 0x89, 0x49, 0x8A, 0xE6, 0xBA}; constexpr uint8_t kExpectedAesKey[16] = {0xB0, 0x7F, 0x1F, 0x17, 0xC2, 0x36, 0xCB, 0xD3, 0x35, 0x23, 0xC5, 0x15, 0xF3, 0x50, 0xAE, 0x57}; constexpr uint64_t kRemoteDevice = 0xB0B1B2B3B4B5; constexpr uint8_t kTxPower = 33; constexpr uint8_t kDiscoverableAdvertisement[] = { 6, 0x16, 0x2C, 0xFE, 0x10, 0x11, 0x12, 2, 0x0A, kTxPower}; constexpr uint8_t kSeekerAccountKey[16] = {0x04, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34}; constexpr uint8_t kSeekerAccountKey2[16] = {0x04, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64}; using ::testing::ElementsAreArray; static std::string VecToString(std::vector data) { std::stringstream output; output << "0x" << std::hex; for (int i = 0; i < data.size(); i++) { output << std::setfill('0') << std::setw(2) << (unsigned)data[i]; } return output.str(); } // static std::string VecToString(uint8_t* start, uint8_t* end) { // return VecToString(std::vector(start, end)); // } class Event { public: explicit Event(nearby_event_Type type) : type_(type) {} explicit Event(const nearby_event_Event* event) : Event(event->event_type) {} nearby_event_Type GetType() const { return type_; } virtual bool operator==(const Event& b) const { return type_ == b.type_; } virtual ~Event() {} protected: virtual std::string ToString() const { std::stringstream output; output << "Event type: " << type_; return output.str(); } nearby_event_Type type_; friend std::ostream& operator<<(std::ostream& os, const Event& event); }; class MessageStreamConnectedEvent : public Event { public: explicit MessageStreamConnectedEvent(uint64_t peer_address) : Event(kNearbyEventMessageStreamConnected), peer_address_(peer_address) {} explicit MessageStreamConnectedEvent( const nearby_event_MessageStreamConnected* payload) : Event(kNearbyEventMessageStreamConnected), peer_address_(payload->peer_address) { EXPECT_NE(nullptr, payload); } explicit MessageStreamConnectedEvent(const nearby_event_Event* event) : MessageStreamConnectedEvent( (const nearby_event_MessageStreamConnected*)event->payload) { EXPECT_EQ(kNearbyEventMessageStreamConnected, type_); } virtual bool operator==(const Event& b) const override { if (type_ != b.GetType()) return false; const MessageStreamConnectedEvent* event = (const MessageStreamConnectedEvent*)&b; return peer_address_ == event->peer_address_; } std::string ToString() const override { std::stringstream output; output << "Event type: " << type_ << " peer_address: " << peer_address_; return output.str(); } private: uint64_t peer_address_; }; class MessageStreamDisconnectedEvent : public Event { public: explicit MessageStreamDisconnectedEvent(uint64_t peer_address) : Event(kNearbyEventMessageStreamDisconnected), peer_address_(peer_address) {} explicit MessageStreamDisconnectedEvent( const nearby_event_MessageStreamDisconnected* payload) : Event(kNearbyEventMessageStreamDisconnected), peer_address_(payload->peer_address) { EXPECT_NE(nullptr, payload); } explicit MessageStreamDisconnectedEvent(const nearby_event_Event* event) : MessageStreamDisconnectedEvent( (const nearby_event_MessageStreamDisconnected*)event->payload) { EXPECT_EQ(kNearbyEventMessageStreamDisconnected, type_); } virtual bool operator==(const Event& b) const override { if (type_ != b.GetType()) return false; const MessageStreamDisconnectedEvent* event = (const MessageStreamDisconnectedEvent*)&b; return peer_address_ == event->peer_address_; } std::string ToString() const override { std::stringstream output; output << "Event type: " << type_ << " peer_address: " << peer_address_; return output.str(); } private: uint64_t peer_address_; }; class MessageStreamReceivedEvent : public Event { public: explicit MessageStreamReceivedEvent( const nearby_event_MessageStreamReceived* payload) : Event(kNearbyEventMessageStreamReceived) { EXPECT_NE(nullptr, payload); peer_address_ = payload->peer_address; group_ = payload->message_group; code_ = payload->message_code; if (payload->length > 0) { data_ = std::vector(payload->data, payload->data + payload->length); } } explicit MessageStreamReceivedEvent(const nearby_event_Event* event) : MessageStreamReceivedEvent( (const nearby_event_MessageStreamReceived*)event->payload) { EXPECT_EQ(kNearbyEventMessageStreamReceived, event->event_type); } virtual bool operator==(const Event& b) const override { if (type_ != b.GetType()) return false; const MessageStreamReceivedEvent* event = (const MessageStreamReceivedEvent*)&b; return peer_address_ == event->peer_address_ && group_ == event->group_ && code_ == event->code_ && data_ == event->data_; } std::string ToString() const override { std::stringstream output; output << "Event type: " << type_ << " peer_address: " << peer_address_ << " group: " << (int)group_ << " code: " << (int)code_ << " length: " << data_.size(); if (data_.size() > 0) { output << " data: " << VecToString(data_); } return output.str(); } private: uint64_t peer_address_; uint8_t group_; uint8_t code_; std::vector data_; }; std::ostream& operator<<(std::ostream& os, const Event& event) { os << event.ToString(); return os; } static std::unique_ptr GetEvent(const nearby_event_Event* event) { switch (event->event_type) { case kNearbyEventMessageStreamConnected: return std::make_unique(event); case kNearbyEventMessageStreamDisconnected: return std::make_unique(event); case kNearbyEventMessageStreamReceived: return std::make_unique(event); } return std::make_unique(event); } std::vector> message_stream_events; static void OnEventCallback(nearby_event_Event* event) { message_stream_events.push_back(GetEvent(event)); } constexpr nearby_fp_client_Callbacks kClientCallbacks = {.on_event = OnEventCallback}; static void WriteToAccountKey() { uint8_t encrypted_account_key_write_request[16]; nearby_test_fakes_Aes128Encrypt( kSeekerAccountKey, encrypted_account_key_write_request, kExpectedAesKey); nearby_fp_fakes_ReceiveAccountKeyWrite( encrypted_account_key_write_request, sizeof(encrypted_account_key_write_request)); } int GetCapability(uint64_t peer_address) { nearby_fp_client_SeekerInfo seeker_infos[NEARBY_MAX_RFCOMM_CONNECTIONS]; size_t sl = NEARBY_MAX_RFCOMM_CONNECTIONS; nearby_fp_client_GetSeekerInfo(seeker_infos, &sl); for (int i = 0; i < sl; i++) { if (seeker_infos[i].peer_address == peer_address) { return seeker_infos[i].capabilities; } } return -1; } // |flags| from Table 1.2.1: Raw Request (type 0x00) in FP specification static void Pair(uint8_t flags) { uint8_t salt = 0xAB; nearby_test_fakes_SetAntiSpoofingKey(kBobPrivateKey, kBobPublicKey); nearby_test_fakes_SetRandomNumber(salt); nearby_fp_client_SetAdvertisement(NEARBY_FP_ADVERTISEMENT_DISCOVERABLE); uint8_t request[16]; request[0] = 0x00; // key-based pairing request request[1] = flags; // Provider's public address request[2] = 0xA0; request[3] = 0xA1; request[4] = 0xA2; request[5] = 0xA3; request[6] = 0xA4; request[7] = 0xA5; // Seeker's address request[8] = 0xB0; request[9] = 0xB1; request[10] = 0xB2; request[11] = 0xB3; request[12] = 0xB4; request[13] = 0xB5; // salt request[14] = 0xCD; request[15] = 0xEF; uint8_t encrypted[16 + 64]; nearby_test_fakes_Aes128Encrypt(request, encrypted, kExpectedAesKey); memcpy(encrypted + 16, kAlicePublicKey, 64); // Seeker responds ASSERT_EQ(kNearbyStatusOK, nearby_fp_fakes_ReceiveKeyBasedPairingRequest( encrypted, sizeof(encrypted))); // BT negotatiates passkey 123456 (0x01E240) uint8_t raw_passkey_block[16] = {0x02, 0x01, 0xE2, 0x40}; uint8_t encrypted_passkey_block[16]; nearby_test_fakes_Aes128Encrypt(raw_passkey_block, encrypted_passkey_block, kExpectedAesKey); // Seeker sends the passkey to provider nearby_fp_fakes_ReceivePasskey(encrypted_passkey_block, sizeof(encrypted_passkey_block)); // Seeker sends their account key WriteToAccountKey(); } TEST(NearbyFpClient, Init) { ASSERT_EQ(kNearbyStatusOK, nearby_fp_client_Init(NULL)); } TEST(NearbyFpClient, AccountKeyListIsEmpty) { ASSERT_EQ(kNearbyStatusOK, nearby_fp_client_Init(NULL)); auto keys = nearby_test_fakes_GetAccountKeys(); ASSERT_EQ(0, keys.size()); } TEST(NearbyFpClient, CopyBigEndian_4bytes) { uint8_t buffer[4]; uint32_t value = 0x01020304; nearby_utils_CopyBigEndian(buffer, value, 4); ASSERT_EQ(1, buffer[0]); ASSERT_EQ(2, buffer[1]); ASSERT_EQ(3, buffer[2]); ASSERT_EQ(4, buffer[3]); } TEST(NearbyFpClient, CopyBigEndian_3bytes) { uint8_t buffer[3]; uint32_t value = 0x00010203; nearby_utils_CopyBigEndian(buffer, value, 3); ASSERT_EQ(1, buffer[0]); ASSERT_EQ(2, buffer[1]); ASSERT_EQ(3, buffer[2]); } TEST(NearbyFpClient, AdvertisementDiscoverable) { const int kBufferSize = DISCOVERABLE_ADV_SIZE_BYTES; uint8_t buffer[kBufferSize]; nearby_fp_client_Init(NULL); size_t written = nearby_fp_CreateDiscoverableAdvertisement(buffer, kBufferSize); written += nearby_fp_AppendTxPower(buffer + written, kBufferSize - written, kTxPower); ASSERT_EQ(kBufferSize, written); ASSERT_THAT(std::vector(buffer, buffer + kBufferSize), ElementsAreArray(kDiscoverableAdvertisement)); } TEST(NearbyFpClient, AdvertisementNondiscoverable_noKeys) { const int kBufferSize = 9; uint8_t buffer[kBufferSize]; const uint8_t kExpectedResult[] = {5, 0x16, 0x2C, 0xFE, 0x00, 0x00, 2, 0x0A, kTxPower}; nearby_fp_client_Init(NULL); size_t written = nearby_fp_CreateNondiscoverableAdvertisement(buffer, kBufferSize, false); written += nearby_fp_AppendTxPower(buffer + written, kBufferSize - written, kTxPower); ASSERT_EQ(kBufferSize, written); ASSERT_THAT(std::vector(buffer, buffer + kBufferSize), ElementsAreArray(kExpectedResult)); } TEST(NearbyFpClient, AdvertisementNondiscoverable_oneKey) { const int kBufferSize = 15; uint8_t buffer[kBufferSize]; uint8_t salt = 0xC7; uint8_t account_keys[] = {1, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99, 0x00, 0xAA, 0xBB, 0xCC, 0xDD, 0xEE, 0xFF}; const uint8_t kExpectedResult[] = {11, 0x16, 0x2C, 0xFE, 0x00, 0x42, 0x0A, 0x42, 0x88, 0x10, 0x11, salt, 2, 0x0A, kTxPower}; nearby_fp_client_Init(NULL); nearby_test_fakes_SetAccountKeys(account_keys, sizeof(account_keys)); nearby_test_fakes_SetRandomNumber(salt); nearby_fp_LoadAccountKeys(); size_t written = nearby_fp_CreateNondiscoverableAdvertisement(buffer, kBufferSize, false); written += nearby_fp_AppendTxPower(buffer + written, kBufferSize - written, kTxPower); ASSERT_EQ(kBufferSize, written); ASSERT_THAT(std::vector(buffer, buffer + kBufferSize), ElementsAreArray(kExpectedResult)); } TEST(NearbyFpClient, AdvertisementNondiscoverable_twoKeys) { const int kBufferSize = 16; uint8_t buffer[kBufferSize]; uint8_t salt = 0xC7; uint8_t account_keys[] = { 2, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99, 0x00, 0xAA, 0xBB, 0xCC, 0xDD, 0xEE, 0xFF, 0x11, 0x11, 0x22, 0x22, 0x33, 0x33, 0x44, 0x44, 0x55, 0x55, 0x66, 0x66, 0x77, 0x77, 0x88, 0x88}; const uint8_t kExpectedResult[] = {12, 0x16, 0x2C, 0xFE, 0x00, 0x52, 0x2F, 0xBA, 0x06, 0x42, 0x00, 0x11, salt, 2, 0x0A, kTxPower}; nearby_fp_client_Init(NULL); nearby_test_fakes_SetAccountKeys(account_keys, sizeof(account_keys)); nearby_test_fakes_SetRandomNumber(salt); nearby_fp_LoadAccountKeys(); size_t written = nearby_fp_CreateNondiscoverableAdvertisement(buffer, kBufferSize, false); written += nearby_fp_AppendTxPower(buffer + written, kBufferSize - written, kTxPower); ASSERT_EQ(kBufferSize, written); ASSERT_THAT(std::vector(buffer, buffer + kBufferSize), ElementsAreArray(kExpectedResult)); } TEST(NearbyFpClient, GattReadModelId) { uint8_t buffer[3]; size_t length = sizeof(buffer); nearby_fp_client_Init(NULL); ASSERT_EQ(kNearbyStatusOK, nearby_test_fakes_GattReadModelId(buffer, &length)); ASSERT_EQ(sizeof(buffer), length); ASSERT_EQ(0x10, buffer[0]); ASSERT_EQ(0x11, buffer[1]); ASSERT_EQ(0x12, buffer[2]); } TEST(NearbyFpClient, SetAntiSpoofingKey) { nearby_fp_client_Init(NULL); ASSERT_EQ(kNearbyStatusOK, nearby_test_fakes_SetAntiSpoofingKey( kBobPrivateKey, kBobPublicKey)); } TEST(NearbyFpClient, GenSec256r1Secret_bobAlice) { uint8_t secret[32]; nearby_fp_client_Init(NULL); ASSERT_EQ(kNearbyStatusOK, nearby_test_fakes_SetAntiSpoofingKey( kBobPrivateKey, kBobPublicKey)); ASSERT_EQ(kNearbyStatusOK, nearby_test_fakes_GenSec256r1Secret(kAlicePublicKey, secret)); for (int i = 0; i < sizeof(secret); i++) { ASSERT_EQ(kExpectedSharedSecret[i], secret[i]) << "Difference at position: " << i; } } TEST(NearbyFpClient, GenSec256r1Secret_aliceBob) { uint8_t secret[32]; nearby_fp_client_Init(NULL); ASSERT_EQ(kNearbyStatusOK, nearby_test_fakes_SetAntiSpoofingKey( kAlicePrivateKey, kAlicePublicKey)); ASSERT_EQ(kNearbyStatusOK, nearby_test_fakes_GenSec256r1Secret(kBobPublicKey, secret)); for (int i = 0; i < sizeof(secret); i++) { ASSERT_EQ(kExpectedSharedSecret[i], secret[i]) << "Difference at position: " << i; } } TEST(NearbyFpClient, CreateSharedSecret_aliceBob) { uint8_t secret[16]; nearby_fp_client_Init(NULL); ASSERT_EQ(kNearbyStatusOK, nearby_test_fakes_SetAntiSpoofingKey( kAlicePrivateKey, kAlicePublicKey)); ASSERT_EQ(kNearbyStatusOK, nearby_fp_CreateSharedSecret(kBobPublicKey, secret)); for (int i = 0; i < sizeof(secret); i++) { ASSERT_EQ(kExpectedAesKey[i], secret[i]) << "Difference at position: " << i; } } TEST(NearbyFpClient, CreateSharedSecret_bobAlice) { uint8_t secret[16]; nearby_fp_client_Init(NULL); ASSERT_EQ(kNearbyStatusOK, nearby_test_fakes_SetAntiSpoofingKey( kBobPrivateKey, kBobPublicKey)); ASSERT_EQ(kNearbyStatusOK, nearby_fp_CreateSharedSecret(kAlicePublicKey, secret)); for (int i = 0; i < sizeof(secret); i++) { ASSERT_EQ(kExpectedAesKey[i], secret[i]) << "Difference at position: " << i; } } #ifdef NEARBY_FP_ENABLE_BATTERY_NOTIFICATION TEST(NearbyFpClient, SetAdvertisementWithBatteryNotification_AdvertisementWithPairingUI) { uint8_t salt = 0xC7; uint8_t account_keys[] = { 5, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99, 0x00, 0xAA, 0xBB, 0xCC, 0xDD, 0xEE, 0xFF, 0x11, 0x11, 0x22, 0x22, 0x33, 0x33, 0x44, 0x44, 0x55, 0x55, 0x66, 0x66, 0x77, 0x77, 0x88, 0x88, 0x03, 0x13, 0x23, 0x33, 0x43, 0x53, 0x63, 0x73, 0x83, 0x93, 0xA3, 0xB3, 0xC3, 0xD3, 0xE3, 0xF3, 0x04, 0x14, 0x24, 0x34, 0x44, 0x54, 0x64, 0x74, 0x84, 0x94, 0xA4, 0xB4, 0xC4, 0xD4, 0xE4, 0xF4, 0x05, 0x15, 0x25, 0x35, 0x45, 0x55, 0x65, 0x75, 0x85, 0x95, 0xA5, 0xB5, 0xC5, 0xD5, 0xE5, 0xF5, }; const uint8_t kExpectedResult[] = { 0x10, 0x16, 0x2c, 0xfe, 0x00, 0x90, 0x03, 0x78, 0x95, 0x67, 0x0c, 0xc3, 0x0a, 0xcc, 0x56, 0x11, salt, 0x02, 0x0a, kTxPower}; nearby_fp_client_Init(NULL); nearby_test_fakes_SetAntiSpoofingKey(kBobPrivateKey, kBobPublicKey); nearby_test_fakes_SetAccountKeys(account_keys, sizeof(account_keys)); nearby_test_fakes_SetRandomNumber(salt); nearby_fp_LoadAccountKeys(); ASSERT_EQ(kNearbyStatusOK, nearby_fp_client_SetAdvertisement( NEARBY_FP_ADVERTISEMENT_NON_DISCOVERABLE | NEARBY_FP_ADVERTISEMENT_PAIRING_UI_INDICATOR)); ASSERT_THAT(nearby_test_fakes_GetAdvertisement(), ElementsAreArray(kExpectedResult)); } TEST( NearbyFpClient, SetAdvertisementWithBatteryNotification_AdvertisementNoPairingUIWithBatteryUI) { uint8_t salt = 0xC7; uint8_t account_keys[] = { 5, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99, 0x00, 0xAA, 0xBB, 0xCC, 0xDD, 0xEE, 0xFF, 0x11, 0x11, 0x22, 0x22, 0x33, 0x33, 0x44, 0x44, 0x55, 0x55, 0x66, 0x66, 0x77, 0x77, 0x88, 0x88, 0x03, 0x13, 0x23, 0x33, 0x43, 0x53, 0x63, 0x73, 0x83, 0x93, 0xA3, 0xB3, 0xC3, 0xD3, 0xE3, 0xF3, 0x04, 0x14, 0x24, 0x34, 0x44, 0x54, 0x64, 0x74, 0x84, 0x94, 0xA4, 0xB4, 0xC4, 0xD4, 0xE4, 0xF4, 0x05, 0x15, 0x25, 0x35, 0x45, 0x55, 0x65, 0x75, 0x85, 0x95, 0xA5, 0xB5, 0xC5, 0xD5, 0xE5, 0xF5, }; const uint8_t kExpectedResult[] = {0x14, 0x16, 0x2c, 0xfe, 0x00, 0x92, 0x30, 0xa6, 0x17, 0x10, 0x0c, 0x6c, 0xa9, 0xea, 0xf7, 0x11, salt, 0x33, 0xd5, 0xd0, 0xda, 2, 0x0a, kTxPower}; nearby_fp_client_Init(NULL); nearby_test_fakes_SetAntiSpoofingKey(kBobPrivateKey, kBobPublicKey); nearby_test_fakes_SetAccountKeys(account_keys, sizeof(account_keys)); nearby_test_fakes_SetRandomNumber(salt); nearby_fp_LoadAccountKeys(); ASSERT_EQ(kNearbyStatusOK, nearby_fp_client_SetAdvertisement( NEARBY_FP_ADVERTISEMENT_NON_DISCOVERABLE | NEARBY_FP_ADVERTISEMENT_BATTERY_UI_INDICATOR | NEARBY_FP_ADVERTISEMENT_INCLUDE_BATTERY_INFO)); ASSERT_THAT(nearby_test_fakes_GetAdvertisement(), ElementsAreArray(kExpectedResult)); } TEST( NearbyFpClient, SetAdvertisementWithBatteryNotification_Charging_AdvertisementContainsBatteryInfo) { uint8_t salt = 0xC7; uint8_t account_keys[] = { 5, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99, 0x00, 0xAA, 0xBB, 0xCC, 0xDD, 0xEE, 0xFF, 0x11, 0x11, 0x22, 0x22, 0x33, 0x33, 0x44, 0x44, 0x55, 0x55, 0x66, 0x66, 0x77, 0x77, 0x88, 0x88, 0x03, 0x13, 0x23, 0x33, 0x43, 0x53, 0x63, 0x73, 0x83, 0x93, 0xA3, 0xB3, 0xC3, 0xD3, 0xE3, 0xF3, 0x04, 0x14, 0x24, 0x34, 0x44, 0x54, 0x64, 0x74, 0x84, 0x94, 0xA4, 0xB4, 0xC4, 0xD4, 0xE4, 0xF4, 0x05, 0x15, 0x25, 0x35, 0x45, 0x55, 0x65, 0x75, 0x85, 0x95, 0xA5, 0xB5, 0xC5, 0xD5, 0xE5, 0xF5, }; const uint8_t kExpectedResult[] = {0x14, 0x16, 0x2c, 0xfe, 0x00, 0x90, 0x30, 0xa6, 0x17, 0x10, 0x0c, 0x6c, 0xa9, 0xea, 0xf7, 0x11, salt, 0x33, 0xd5, 0xd0, 0xda, 2, 0x0a, kTxPower}; nearby_fp_client_Init(NULL); nearby_test_fakes_SetAntiSpoofingKey(kBobPrivateKey, kBobPublicKey); nearby_test_fakes_SetAccountKeys(account_keys, sizeof(account_keys)); nearby_test_fakes_SetRandomNumber(salt); nearby_fp_LoadAccountKeys(); nearby_test_fakes_SetIsCharging(true); ASSERT_EQ(kNearbyStatusOK, nearby_fp_client_SetAdvertisement( NEARBY_FP_ADVERTISEMENT_NON_DISCOVERABLE | NEARBY_FP_ADVERTISEMENT_PAIRING_UI_INDICATOR | NEARBY_FP_ADVERTISEMENT_BATTERY_UI_INDICATOR | NEARBY_FP_ADVERTISEMENT_INCLUDE_BATTERY_INFO)); ASSERT_THAT(nearby_test_fakes_GetAdvertisement(), ElementsAreArray(kExpectedResult)); } TEST( NearbyFpClient, SetAdvertisementWithBatteryNotification_NotCharging_AdvertisementContainsBatteryInfo) { uint8_t salt = 0xC7; uint8_t account_keys[] = { 5, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99, 0x00, 0xAA, 0xBB, 0xCC, 0xDD, 0xEE, 0xFF, 0x11, 0x11, 0x22, 0x22, 0x33, 0x33, 0x44, 0x44, 0x55, 0x55, 0x66, 0x66, 0x77, 0x77, 0x88, 0x88, 0x03, 0x13, 0x23, 0x33, 0x43, 0x53, 0x63, 0x73, 0x83, 0x93, 0xA3, 0xB3, 0xC3, 0xD3, 0xE3, 0xF3, 0x04, 0x14, 0x24, 0x34, 0x44, 0x54, 0x64, 0x74, 0x84, 0x94, 0xA4, 0xB4, 0xC4, 0xD4, 0xE4, 0xF4, 0x05, 0x15, 0x25, 0x35, 0x45, 0x55, 0x65, 0x75, 0x85, 0x95, 0xA5, 0xB5, 0xC5, 0xD5, 0xE5, 0xF5, }; const uint8_t kExpectedResult[] = {0x14, 0x16, 0x2c, 0xfe, 0x00, 0x90, 0x46, 0x84, 0x1e, 0x84, 0x2e, 0x27, 0x05, 0x92, 0xcc, 0x11, salt, 0x33, 0x55, 0x50, 0x5a, 2, 0x0a, kTxPower}; nearby_fp_client_Init(NULL); nearby_test_fakes_SetAntiSpoofingKey(kBobPrivateKey, kBobPublicKey); nearby_test_fakes_SetAccountKeys(account_keys, sizeof(account_keys)); nearby_test_fakes_SetRandomNumber(salt); nearby_fp_LoadAccountKeys(); nearby_test_fakes_SetIsCharging(false); ASSERT_EQ(kNearbyStatusOK, nearby_fp_client_SetAdvertisement( NEARBY_FP_ADVERTISEMENT_NON_DISCOVERABLE | NEARBY_FP_ADVERTISEMENT_PAIRING_UI_INDICATOR | NEARBY_FP_ADVERTISEMENT_BATTERY_UI_INDICATOR | NEARBY_FP_ADVERTISEMENT_INCLUDE_BATTERY_INFO)); ASSERT_THAT(nearby_test_fakes_GetAdvertisement(), ElementsAreArray(kExpectedResult)); } TEST( NearbyFpClient, SetAdvertisementWithBatteryNotification_GetBatteryInfoFails_AdvertismentIsValid) { uint8_t salt = 0xC7; uint8_t account_keys[] = { 5, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99, 0x00, 0xAA, 0xBB, 0xCC, 0xDD, 0xEE, 0xFF, 0x11, 0x11, 0x22, 0x22, 0x33, 0x33, 0x44, 0x44, 0x55, 0x55, 0x66, 0x66, 0x77, 0x77, 0x88, 0x88, 0x03, 0x13, 0x23, 0x33, 0x43, 0x53, 0x63, 0x73, 0x83, 0x93, 0xA3, 0xB3, 0xC3, 0xD3, 0xE3, 0xF3, 0x04, 0x14, 0x24, 0x34, 0x44, 0x54, 0x64, 0x74, 0x84, 0x94, 0xA4, 0xB4, 0xC4, 0xD4, 0xE4, 0xF4, 0x05, 0x15, 0x25, 0x35, 0x45, 0x55, 0x65, 0x75, 0x85, 0x95, 0xA5, 0xB5, 0xC5, 0xD5, 0xE5, 0xF5, }; const uint8_t kExpectedResult[] = { 0x10, 0x16, 0x2c, 0xfe, 0x00, 0x90, 0x03, 0x78, 0x95, 0x67, 0x0c, 0xc3, 0x0a, 0xcc, 0x56, 0x11, salt, 2, 0x0a, kTxPower}; nearby_fp_client_Init(NULL); nearby_test_fakes_SetAntiSpoofingKey(kBobPrivateKey, kBobPublicKey); nearby_test_fakes_SetAccountKeys(account_keys, sizeof(account_keys)); nearby_test_fakes_SetRandomNumber(salt); nearby_fp_LoadAccountKeys(); nearby_test_fakes_SetGetBatteryInfoResult(kNearbyStatusUnsupported); ASSERT_EQ(kNearbyStatusOK, nearby_fp_client_SetAdvertisement( NEARBY_FP_ADVERTISEMENT_NON_DISCOVERABLE | NEARBY_FP_ADVERTISEMENT_PAIRING_UI_INDICATOR | NEARBY_FP_ADVERTISEMENT_BATTERY_UI_INDICATOR | NEARBY_FP_ADVERTISEMENT_INCLUDE_BATTERY_INFO)); ASSERT_THAT(nearby_test_fakes_GetAdvertisement(), ElementsAreArray(kExpectedResult)); } #ifdef NEARBY_FP_MESSAGE_STREAM TEST(NearbyFpClient, RfcommConnected_HasBatteryInfo_SendsModelIdBleAddressAndBatteryInfo) { constexpr uint64_t kPeerAddress = 0x123456; constexpr uint8_t kExpectedRfcommOutput[] = {// Model Id 3, 1, 0, 3, 0x10, 0x11, 0x12, // Ble Address 3, 2, 0, 6, 0x6b, 0xab, 0xab, 0xab, 0xab, 0xab, // Battery level 3, 3, 0, 3, 0xd5, 0xd0, 0xda, // Battery remaining time 3, 4, 0, 1, 100}; nearby_fp_client_Init(&kClientCallbacks); Pair(0x40); message_stream_events.clear(); nearby_test_fakes_BatteryTime(100); nearby_test_fakes_GetRfcommOutput().clear(); nearby_test_fakes_SetIsCharging(true); nearby_test_fakes_SetGetBatteryInfoResult(kNearbyStatusOK); nearby_test_fakes_MessageStreamConnected(kPeerAddress); ASSERT_EQ(1, message_stream_events.size()); ASSERT_EQ(MessageStreamConnectedEvent(kPeerAddress), *message_stream_events[0]); ASSERT_THAT(kExpectedRfcommOutput, ElementsAreArray(nearby_test_fakes_GetRfcommOutput())); } #endif /* NEARBY_FP_MESSAGE_STREAM */ #endif /* NEARBY_FP_ENABLE_BATTERY_NOTIFICATION */ #ifdef NEARBY_FP_MESSAGE_STREAM TEST(NearbyFpClient, EnableSilenceMode_RfcommConnected) { constexpr uint64_t kPeerAddress = 0x123456; constexpr uint8_t kExpectedRfcommOutput[] = {// Model Id 3, 1, 0, 3, 0x10, 0x11, 0x12, // Ble Address 3, 2, 0, 6, 0x6b, 0xab, 0xab, 0xab, 0xab, 0xab, // Battery level 3, 3, 0, 3, 0xd5, 0xd0, 0xda, // Battery remaining time 3, 4, 0, 1, 100, // Enable silence mode 1, 1, 0, 0}; nearby_fp_client_Init(&kClientCallbacks); Pair(0x40); message_stream_events.clear(); nearby_test_fakes_BatteryTime(100); nearby_test_fakes_GetRfcommOutput().clear(); nearby_test_fakes_MessageStreamConnected(kPeerAddress); nearby_fp_client_SetSilenceMode(kPeerAddress, true); ASSERT_THAT(kExpectedRfcommOutput, ElementsAreArray(nearby_test_fakes_GetRfcommOutput())); } #endif /* NEARBY_FP_MESSAGE_STREAM */ #ifdef NEARBY_FP_MESSAGE_STREAM TEST(NearbyFpClient, DisableSilenceMode_RfcommConnected) { constexpr uint64_t kPeerAddress = 0x123456; constexpr uint8_t kExpectedRfcommOutput[] = {// Model Id 3, 1, 0, 3, 0x10, 0x11, 0x12, // Ble Address 3, 2, 0, 6, 0x6b, 0xab, 0xab, 0xab, 0xab, 0xab, // Battery level 3, 3, 0, 3, 0xd5, 0xd0, 0xda, // Battery remaining time 3, 4, 0, 1, 100, // Disable silence mode 1, 2, 0, 0}; nearby_fp_client_Init(&kClientCallbacks); Pair(0x40); message_stream_events.clear(); nearby_test_fakes_BatteryTime(100); nearby_test_fakes_GetRfcommOutput().clear(); nearby_test_fakes_MessageStreamConnected(kPeerAddress); nearby_fp_client_SetSilenceMode(kPeerAddress, false); ASSERT_THAT(kExpectedRfcommOutput, ElementsAreArray(nearby_test_fakes_GetRfcommOutput())); } #endif /* NEARBY_FP_MESSAGE_STREAM */ #ifdef NEARBY_FP_MESSAGE_STREAM TEST(NearbyFpClient, BatteryLevelLongForm_RfcommConnected) { constexpr uint64_t kPeerAddress = 0x123456; constexpr uint8_t kExpectedRfcommOutput[] = {// Model Id 3, 1, 0, 3, 0x10, 0x11, 0x12, // Ble Address 3, 2, 0, 6, 0x6b, 0xab, 0xab, 0xab, 0xab, 0xab, // Battery level 3, 3, 0, 3, 0xd5, 0xd0, 0xda, // Battery remaining time (256) 3, 4, 0, 2, 1, 0, // Disable silence mode 1, 2, 0, 0}; nearby_fp_client_Init(&kClientCallbacks); Pair(0x40); message_stream_events.clear(); nearby_test_fakes_BatteryTime(0x100); nearby_test_fakes_GetRfcommOutput().clear(); nearby_test_fakes_MessageStreamConnected(kPeerAddress); nearby_fp_client_SetSilenceMode(kPeerAddress, false); ASSERT_THAT(kExpectedRfcommOutput, ElementsAreArray(nearby_test_fakes_GetRfcommOutput())); } #endif /* NEARBY_FP_MESSAGE_STREAM */ #ifdef NEARBY_FP_MESSAGE_STREAM TEST(NearbyFpClient, EnableSilenceMode_NoRfcommConnection_ReturnsError) { constexpr uint64_t kPeerAddress = 0x123456; nearby_fp_client_Init(&kClientCallbacks); Pair(0x40); message_stream_events.clear(); nearby_test_fakes_GetRfcommOutput().clear(); ASSERT_EQ(kNearbyStatusError, nearby_fp_client_SetSilenceMode(kPeerAddress, true)); } #endif /* NEARBY_FP_MESSAGE_STREAM */ #ifdef NEARBY_FP_MESSAGE_STREAM TEST(NearbyFpClient, SignalLogBufferFull_RfcommConnected) { constexpr uint64_t kPeerAddress = 0x123456; constexpr uint8_t kExpectedRfcommOutput[] = {// Model Id 3, 1, 0, 3, 0x10, 0x11, 0x12, // Ble Address 3, 2, 0, 6, 0x6b, 0xab, 0xab, 0xab, 0xab, 0xab, // Battery level 3, 3, 0, 3, 0xd5, 0xd0, 0xda, // Battery remaining time 3, 4, 0, 1, 100, // Signal log buffer full 2, 1, 0, 0}; nearby_fp_client_Init(&kClientCallbacks); Pair(0x40); message_stream_events.clear(); nearby_test_fakes_BatteryTime(100); nearby_test_fakes_GetRfcommOutput().clear(); nearby_test_fakes_MessageStreamConnected(kPeerAddress); nearby_fp_client_SignalLogBufferFull(kPeerAddress); ASSERT_THAT(kExpectedRfcommOutput, ElementsAreArray(nearby_test_fakes_GetRfcommOutput())); } #endif /* NEARBY_FP_MESSAGE_STREAM */ #ifdef NEARBY_FP_MESSAGE_STREAM TEST(NearbyFpClient, ReceiveActiveComponentsRequest_SendsActiveComponentResponse) { constexpr uint64_t kPeerAddress = 0x123456; constexpr uint8_t kPeerMessage[] = {// active components request 3, 5, 0, 0}; const nearby_event_MessageStreamReceived kExpectedMessage = { .peer_address = kPeerAddress, .message_group = kPeerMessage[0], .message_code = kPeerMessage[1], .length = kPeerMessage[2] * 256 + kPeerMessage[3], .data = NULL}; constexpr uint8_t kExpectedRfcommOutput[] = {// Model Id 3, 1, 0, 3, 0x10, 0x11, 0x12, // Ble Address 3, 2, 0, 6, 0x6b, 0xab, 0xab, 0xab, 0xab, 0xab, // Battery level 3, 3, 0, 3, 0xd5, 0xd0, 0xda, // Battery remaining time 3, 4, 0, 1, 100, // Active component response 3, 6, 0, 1, 0x00}; nearby_fp_client_Init(&kClientCallbacks); Pair(0x40); message_stream_events.clear(); nearby_test_fakes_BatteryTime(100); nearby_test_fakes_GetRfcommOutput().clear(); nearby_test_fakes_MessageStreamConnected(kPeerAddress); nearby_test_fakes_MessageStreamReceived(kPeerAddress, kPeerMessage, sizeof(kPeerMessage)); ASSERT_EQ(MessageStreamReceivedEvent(&kExpectedMessage), *message_stream_events[1]); ASSERT_THAT(kExpectedRfcommOutput, ElementsAreArray(nearby_test_fakes_GetRfcommOutput())); } #endif /* NEARBY_FP_MESSAGE_STREAM */ #ifdef NEARBY_FP_MESSAGE_STREAM TEST(NearbyFpClient, ReceiveCapabilities) { constexpr uint64_t kPeerAddress = 0x123456; constexpr uint8_t kCapabilities = 0x11; constexpr uint8_t kPeerMessage[] = {// Seeker capabilities request, // Companion app, silence mode. 3, 7, 0, 1, kCapabilities}; const nearby_event_MessageStreamReceived kExpectedMessage = { .peer_address = kPeerAddress, .message_group = kPeerMessage[0], .message_code = kPeerMessage[1], .length = kPeerMessage[2] * 256 + kPeerMessage[3], .data = (uint8_t*)kPeerMessage + 4}; nearby_fp_client_Init(&kClientCallbacks); Pair(0x40); message_stream_events.clear(); nearby_test_fakes_GetRfcommOutput().clear(); nearby_test_fakes_MessageStreamConnected(kPeerAddress); nearby_test_fakes_MessageStreamReceived(kPeerAddress, kPeerMessage, sizeof(kPeerMessage)); ASSERT_EQ(MessageStreamReceivedEvent(&kExpectedMessage), *message_stream_events[1]); ASSERT_EQ(kCapabilities, GetCapability(kPeerAddress)); } #endif /* NEARBY_FP_MESSAGE_STREAM */ #ifdef NEARBY_FP_MESSAGE_STREAM TEST(NearbyFpClient, ReceivePlatformType) { constexpr uint64_t kPeerAddress = 0x123456; constexpr uint8_t kPeerMessage[] = {// platform type request, // Android, Pie SDK 3, 8, 0, 2, 0x01, 0x1c}; const nearby_event_MessageStreamReceived kExpectedMessage = { .peer_address = kPeerAddress, .message_group = kPeerMessage[0], .message_code = kPeerMessage[1], .length = kPeerMessage[2] * 256 + kPeerMessage[3], .data = (uint8_t*)kPeerMessage + 4}; nearby_fp_client_Init(&kClientCallbacks); Pair(0x40); message_stream_events.clear(); nearby_test_fakes_GetRfcommOutput().clear(); nearby_test_fakes_MessageStreamConnected(kPeerAddress); nearby_test_fakes_MessageStreamReceived(kPeerAddress, kPeerMessage, sizeof(kPeerMessage)); ASSERT_EQ(MessageStreamReceivedEvent(&kExpectedMessage), *message_stream_events[1]); } #endif /* NEARBY_FP_MESSAGE_STREAM */ #ifdef NEARBY_FP_MESSAGE_STREAM TEST(NearbyFpClient, ReceiveRingRequest) { constexpr uint64_t kPeerAddress = 0x123456; constexpr uint8_t kRingTimeSeconds = 100; constexpr uint16_t kRingTimeDeciseconds = 10 * kRingTimeSeconds; constexpr uint8_t kPeerMessage[] = { // Ring request, both buds, // 100 seconds. 4, 1, 0, 2, MESSAGE_CODE_RING_LEFT | MESSAGE_CODE_RING_RIGHT, kRingTimeSeconds}; const nearby_event_MessageStreamReceived kExpectedMessage = { .peer_address = kPeerAddress, .message_group = kPeerMessage[0], .message_code = kPeerMessage[1], .length = kPeerMessage[2] * 256 + kPeerMessage[3], .data = (uint8_t*)kPeerMessage + 4}; nearby_fp_client_Init(&kClientCallbacks); Pair(0x40); message_stream_events.clear(); nearby_test_fakes_GetRfcommOutput().clear(); nearby_test_fakes_MessageStreamConnected(kPeerAddress); nearby_test_fakes_MessageStreamReceived(kPeerAddress, kPeerMessage, sizeof(kPeerMessage)); ASSERT_EQ(MessageStreamReceivedEvent(&kExpectedMessage), *message_stream_events[1]); ASSERT_EQ(nearby_test_fakes_GetRingCommand(), MESSAGE_CODE_RING_LEFT | MESSAGE_CODE_RING_RIGHT); ASSERT_EQ(nearby_test_fakes_GetRingTimeout(), kRingTimeDeciseconds); } #endif /* NEARBY_FP_MESSAGE_STREAM */ TEST(NearbyFpClient, Pairing_ProviderInitiated) { uint8_t salt = 0xAB; ASSERT_EQ(kNearbyStatusOK, nearby_fp_client_Init(NULL)); ASSERT_EQ(kNearbyStatusOK, nearby_test_fakes_SetAntiSpoofingKey( kBobPrivateKey, kBobPublicKey)); ASSERT_EQ(kNearbyStatusOK, nearby_fp_client_SetAdvertisement( NEARBY_FP_ADVERTISEMENT_DISCOVERABLE)); nearby_test_fakes_SetRandomNumber(salt); // Provider sets the advertisement ASSERT_THAT(nearby_test_fakes_GetAdvertisement(), ElementsAreArray(kDiscoverableAdvertisement)); uint8_t request[16]; request[0] = 0x00; // key-based pairing request request[1] = 0x40; // bit 1 (msb) set // Provider's public address request[2] = 0xA0; request[3] = 0xA1; request[4] = 0xA2; request[5] = 0xA3; request[6] = 0xA4; request[7] = 0xA5; // Seeker's address request[8] = 0xB0; request[9] = 0xB1; request[10] = 0xB2; request[11] = 0xB3; request[12] = 0xB4; request[13] = 0xB5; // salt request[14] = 0xCD; request[15] = 0xEF; uint8_t encrypted[16 + 64]; nearby_test_fakes_Aes128Encrypt(request, encrypted, kExpectedAesKey); memcpy(encrypted + 16, kAlicePublicKey, 64); // Seeker responds ASSERT_EQ(kNearbyStatusOK, nearby_fp_fakes_ReceiveKeyBasedPairingRequest( encrypted, sizeof(encrypted))); auto response = nearby_test_fakes_GetGattNotifications().at(kKeyBasedPairing); std::cout << VecToString(response) << std::endl; uint8_t decrypted_response[16]; uint8_t expected_decrypted_response[16] = {0x01, 0xA0, 0xA1, 0xA2, 0xA3, 0xA4, 0xA5, salt, salt, salt, salt, salt, salt, salt, salt, salt}; nearby_test_fakes_Aes128Decrypt(response.data(), decrypted_response, kExpectedAesKey); for (int i = 0; i < sizeof(expected_decrypted_response); i++) { ASSERT_EQ(expected_decrypted_response[i], decrypted_response[i]) << "Difference at position: " << i; } // Provider sends pairing request ASSERT_EQ(kRemoteDevice, nearby_test_fakes_GetPairingRequestAddress()); // BT negotatiates passkey 123456 (0x01E240) uint8_t raw_passkey_block[16] = {0x02, 0x01, 0xE2, 0x40}; uint8_t encrypted_passkey_block[16]; nearby_test_fakes_Aes128Encrypt(raw_passkey_block, encrypted_passkey_block, kExpectedAesKey); // Seeker sends the passkey to provider nearby_fp_fakes_ReceivePasskey(encrypted_passkey_block, sizeof(encrypted_passkey_block)); // Provider sends the passkey to seeker response = nearby_test_fakes_GetGattNotifications().at(kPasskey); nearby_test_fakes_Aes128Decrypt(response.data(), decrypted_response, kExpectedAesKey); uint8_t expected_passkey_block[16] = {0x03, 0x01, 0xE2, 0x40, salt, salt, salt, salt, salt, salt, salt, salt, salt, salt, salt, salt}; for (int i = 0; i < sizeof(expected_decrypted_response); i++) { ASSERT_EQ(expected_passkey_block[i], decrypted_response[i]) << "Difference at position: " << i; } ASSERT_EQ(123456, nearby_test_fakes_GetRemotePasskey()); ASSERT_EQ(kRemoteDevice, nearby_test_fakes_GetPairedDevice()); // Seeker sends their account key WriteToAccountKey(); std::cout << "Account keys: " << VecToString(nearby_test_fakes_GetRawAccountKeys()) << std::endl; auto keys = nearby_test_fakes_GetAccountKeys(); ASSERT_EQ(1, keys.size()); ASSERT_EQ(std::vector(kSeekerAccountKey, kSeekerAccountKey + sizeof(kExpectedAesKey)), keys.GetKeys()[0]); } // Pairing flow where the Seeker writes to the account key a little bit too // early - while the BT bonding is still in progress TEST(NearbyFpClient, Pairing_WriteKeyBeforePaired_PairingSuccessful) { uint8_t salt = 0xAB; ASSERT_EQ(kNearbyStatusOK, nearby_fp_client_Init(NULL)); ASSERT_EQ(kNearbyStatusOK, nearby_test_fakes_SetAntiSpoofingKey( kBobPrivateKey, kBobPublicKey)); ASSERT_EQ(kNearbyStatusOK, nearby_fp_client_SetAdvertisement( NEARBY_FP_ADVERTISEMENT_DISCOVERABLE)); nearby_test_fakes_SetRandomNumber(salt); // Provider sets the advertisement ASSERT_THAT(nearby_test_fakes_GetAdvertisement(), ElementsAreArray(kDiscoverableAdvertisement)); uint8_t request[16]; request[0] = 0x00; // key-based pairing request request[1] = 0x40; // bit 1 (msb) set // Provider's public address request[2] = 0xA0; request[3] = 0xA1; request[4] = 0xA2; request[5] = 0xA3; request[6] = 0xA4; request[7] = 0xA5; // Seeker's address request[8] = 0xB0; request[9] = 0xB1; request[10] = 0xB2; request[11] = 0xB3; request[12] = 0xB4; request[13] = 0xB5; // salt request[14] = 0xCD; request[15] = 0xEF; uint8_t encrypted[16 + 64]; nearby_test_fakes_Aes128Encrypt(request, encrypted, kExpectedAesKey); memcpy(encrypted + 16, kAlicePublicKey, 64); // Seeker responds ASSERT_EQ(kNearbyStatusOK, nearby_fp_fakes_ReceiveKeyBasedPairingRequest( encrypted, sizeof(encrypted))); auto response = nearby_test_fakes_GetGattNotifications().at(kKeyBasedPairing); std::cout << VecToString(response) << std::endl; uint8_t decrypted_response[16]; uint8_t expected_decrypted_response[16] = {0x01, 0xA0, 0xA1, 0xA2, 0xA3, 0xA4, 0xA5, salt, salt, salt, salt, salt, salt, salt, salt, salt}; nearby_test_fakes_Aes128Decrypt(response.data(), decrypted_response, kExpectedAesKey); for (int i = 0; i < sizeof(expected_decrypted_response); i++) { ASSERT_EQ(expected_decrypted_response[i], decrypted_response[i]) << "Difference at position: " << i; } // Provider sends pairing request ASSERT_EQ(kRemoteDevice, nearby_test_fakes_GetPairingRequestAddress()); // Seeker sends their account key WriteToAccountKey(); // BT negotatiates passkey 123456 (0x01E240) uint8_t raw_passkey_block[16] = {0x02, 0x01, 0xE2, 0x40}; uint8_t encrypted_passkey_block[16]; nearby_test_fakes_Aes128Encrypt(raw_passkey_block, encrypted_passkey_block, kExpectedAesKey); // Seeker sends the passkey to provider nearby_fp_fakes_ReceivePasskey(encrypted_passkey_block, sizeof(encrypted_passkey_block)); // Provider sends the passkey to seeker response = nearby_test_fakes_GetGattNotifications().at(kPasskey); nearby_test_fakes_Aes128Decrypt(response.data(), decrypted_response, kExpectedAesKey); uint8_t expected_passkey_block[16] = {0x03, 0x01, 0xE2, 0x40, salt, salt, salt, salt, salt, salt, salt, salt, salt, salt, salt, salt}; for (int i = 0; i < sizeof(expected_decrypted_response); i++) { ASSERT_EQ(expected_passkey_block[i], decrypted_response[i]) << "Difference at position: " << i; } ASSERT_EQ(123456, nearby_test_fakes_GetRemotePasskey()); ASSERT_EQ(kRemoteDevice, nearby_test_fakes_GetPairedDevice()); std::cout << "Account keys: " << VecToString(nearby_test_fakes_GetRawAccountKeys()) << std::endl; auto keys = nearby_test_fakes_GetAccountKeys(); ASSERT_EQ(1, keys.size()); ASSERT_EQ(std::vector(kSeekerAccountKey, kSeekerAccountKey + sizeof(kExpectedAesKey)), keys.GetKeys()[0]); } TEST(NearbyFpClient, Pairing_SeekerInitiated_PairingSuccessful) { uint8_t salt = 0xAB; ASSERT_EQ(kNearbyStatusOK, nearby_fp_client_Init(NULL)); ASSERT_EQ(kNearbyStatusOK, nearby_test_fakes_SetAntiSpoofingKey( kBobPrivateKey, kBobPublicKey)); ASSERT_EQ(kNearbyStatusOK, nearby_fp_client_SetAdvertisement( NEARBY_FP_ADVERTISEMENT_DISCOVERABLE)); nearby_test_fakes_SetRandomNumber(salt); // Provider sets the advertisement ASSERT_THAT(nearby_test_fakes_GetAdvertisement(), ElementsAreArray(kDiscoverableAdvertisement)); uint8_t request[16]; request[0] = 0x00; // key-based pairing request request[1] = 0x00; // bit 1 (msb) cleared // Provider's public address request[2] = 0xA0; request[3] = 0xA1; request[4] = 0xA2; request[5] = 0xA3; request[6] = 0xA4; request[7] = 0xA5; // salt for (int i = 8; i < 16; i++) { request[i] = 0xCD + i; } uint8_t encrypted[16 + 64]; nearby_test_fakes_Aes128Encrypt(request, encrypted, kExpectedAesKey); memcpy(encrypted + 16, kAlicePublicKey, 64); // Seeker responds ASSERT_EQ(kNearbyStatusOK, nearby_fp_fakes_ReceiveKeyBasedPairingRequest( encrypted, sizeof(encrypted))); auto response = nearby_test_fakes_GetGattNotifications().at(kKeyBasedPairing); std::cout << VecToString(response) << std::endl; uint8_t decrypted_response[16]; uint8_t expected_decrypted_response[16] = {0x01, 0xA0, 0xA1, 0xA2, 0xA3, 0xA4, 0xA5, salt, salt, salt, salt, salt, salt, salt, salt, salt}; nearby_test_fakes_Aes128Decrypt(response.data(), decrypted_response, kExpectedAesKey); for (int i = 0; i < sizeof(expected_decrypted_response); i++) { ASSERT_EQ(expected_decrypted_response[i], decrypted_response[i]) << "Difference at position: " << i; } // Seeker sends pairing request nearby_test_fakes_SimulatePairing(kRemoteDevice); // BT negotatiates passkey 123456 (0x01E240) uint8_t raw_passkey_block[16] = {0x02, 0x01, 0xE2, 0x40}; uint8_t encrypted_passkey_block[16]; nearby_test_fakes_Aes128Encrypt(raw_passkey_block, encrypted_passkey_block, kExpectedAesKey); // Seeker sends the passkey to provider nearby_fp_fakes_ReceivePasskey(encrypted_passkey_block, sizeof(encrypted_passkey_block)); // Provider sends the passkey to seeker response = nearby_test_fakes_GetGattNotifications().at(kPasskey); nearby_test_fakes_Aes128Decrypt(response.data(), decrypted_response, kExpectedAesKey); uint8_t expected_passkey_block[16] = {0x03, 0x01, 0xE2, 0x40, salt, salt, salt, salt, salt, salt, salt, salt, salt, salt, salt, salt}; for (int i = 0; i < sizeof(expected_decrypted_response); i++) { ASSERT_EQ(expected_passkey_block[i], decrypted_response[i]) << "Difference at position: " << i; } ASSERT_EQ(123456, nearby_test_fakes_GetRemotePasskey()); ASSERT_EQ(kRemoteDevice, nearby_test_fakes_GetPairedDevice()); // Seeker sends their account key WriteToAccountKey(); std::cout << "Account keys: " << VecToString(nearby_test_fakes_GetRawAccountKeys()) << std::endl; auto keys = nearby_test_fakes_GetAccountKeys(); ASSERT_EQ(1, keys.size()); ASSERT_EQ(std::vector(kSeekerAccountKey, kSeekerAccountKey + sizeof(kExpectedAesKey)), keys.GetKeys()[0]); } TEST(NearbyFpClient, Pairing_SeekerInitiatedWriteKeyEarly_PairingSuccessful) { uint8_t salt = 0xAB; ASSERT_EQ(kNearbyStatusOK, nearby_fp_client_Init(NULL)); ASSERT_EQ(kNearbyStatusOK, nearby_test_fakes_SetAntiSpoofingKey( kBobPrivateKey, kBobPublicKey)); ASSERT_EQ(kNearbyStatusOK, nearby_fp_client_SetAdvertisement( NEARBY_FP_ADVERTISEMENT_DISCOVERABLE)); nearby_test_fakes_SetRandomNumber(salt); // Provider sets the advertisement ASSERT_THAT(nearby_test_fakes_GetAdvertisement(), ElementsAreArray(kDiscoverableAdvertisement)); uint8_t request[16]; request[0] = 0x00; // key-based pairing request request[1] = 0x00; // bit 1 (msb) cleared // Provider's public address request[2] = 0xA0; request[3] = 0xA1; request[4] = 0xA2; request[5] = 0xA3; request[6] = 0xA4; request[7] = 0xA5; // salt for (int i = 8; i < 16; i++) { request[i] = 0xCD + i; } uint8_t encrypted[16 + 64]; nearby_test_fakes_Aes128Encrypt(request, encrypted, kExpectedAesKey); memcpy(encrypted + 16, kAlicePublicKey, 64); // Seeker responds ASSERT_EQ(kNearbyStatusOK, nearby_fp_fakes_ReceiveKeyBasedPairingRequest( encrypted, sizeof(encrypted))); auto response = nearby_test_fakes_GetGattNotifications().at(kKeyBasedPairing); std::cout << VecToString(response) << std::endl; uint8_t decrypted_response[16]; uint8_t expected_decrypted_response[16] = {0x01, 0xA0, 0xA1, 0xA2, 0xA3, 0xA4, 0xA5, salt, salt, salt, salt, salt, salt, salt, salt, salt}; nearby_test_fakes_Aes128Decrypt(response.data(), decrypted_response, kExpectedAesKey); for (int i = 0; i < sizeof(expected_decrypted_response); i++) { ASSERT_EQ(expected_decrypted_response[i], decrypted_response[i]) << "Difference at position: " << i; } // Seeker sends pairing request nearby_test_fakes_SimulatePairing(kRemoteDevice); // Seeker sends their account key WriteToAccountKey(); // BT negotatiates passkey 123456 (0x01E240) uint8_t raw_passkey_block[16] = {0x02, 0x01, 0xE2, 0x40}; uint8_t encrypted_passkey_block[16]; nearby_test_fakes_Aes128Encrypt(raw_passkey_block, encrypted_passkey_block, kExpectedAesKey); // Seeker sends the passkey to provider nearby_fp_fakes_ReceivePasskey(encrypted_passkey_block, sizeof(encrypted_passkey_block)); // Provider sends the passkey to seeker response = nearby_test_fakes_GetGattNotifications().at(kPasskey); nearby_test_fakes_Aes128Decrypt(response.data(), decrypted_response, kExpectedAesKey); uint8_t expected_passkey_block[16] = {0x03, 0x01, 0xE2, 0x40, salt, salt, salt, salt, salt, salt, salt, salt, salt, salt, salt, salt}; for (int i = 0; i < sizeof(expected_decrypted_response); i++) { ASSERT_EQ(expected_passkey_block[i], decrypted_response[i]) << "Difference at position: " << i; } ASSERT_EQ(123456, nearby_test_fakes_GetRemotePasskey()); ASSERT_EQ(kRemoteDevice, nearby_test_fakes_GetPairedDevice()); std::cout << "Account keys: " << VecToString(nearby_test_fakes_GetRawAccountKeys()) << std::endl; auto keys = nearby_test_fakes_GetAccountKeys(); ASSERT_EQ(1, keys.size()); ASSERT_EQ(std::vector(kSeekerAccountKey, kSeekerAccountKey + sizeof(kExpectedAesKey)), keys.GetKeys()[0]); } TEST(NearbyFpClient, Pair_AccountKeyStorageFull_AddsNewKey) { uint8_t account_keys[] = { 5, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99, 0x00, 0xAA, 0xBB, 0xCC, 0xDD, 0xEE, 0xFF, 0x11, 0x11, 0x22, 0x22, 0x33, 0x33, 0x44, 0x44, 0x55, 0x55, 0x66, 0x66, 0x77, 0x77, 0x88, 0x88, 0x03, 0x13, 0x23, 0x33, 0x43, 0x53, 0x63, 0x73, 0x83, 0x93, 0xA3, 0xB3, 0xC3, 0xD3, 0xE3, 0xF3, 0x04, 0x14, 0x24, 0x34, 0x44, 0x54, 0x64, 0x74, 0x84, 0x94, 0xA4, 0xB4, 0xC4, 0xD4, 0xE4, 0xF4, 0x05, 0x15, 0x25, 0x35, 0x45, 0x55, 0x65, 0x75, 0x85, 0x95, 0xA5, 0xB5, 0xC5, 0xD5, 0xE5, 0xF5, }; nearby_fp_client_Init(NULL); nearby_test_fakes_SetAccountKeys(account_keys, sizeof(account_keys)); nearby_fp_LoadAccountKeys(); Pair(0x40); auto keys = nearby_test_fakes_GetAccountKeys(); ASSERT_EQ(5, keys.size()); ASSERT_EQ(std::vector(kSeekerAccountKey, kSeekerAccountKey + sizeof(kExpectedAesKey)), keys.GetKeys()[0]); } TEST(NearbyFpClient, ReadModelId) { std::vector expected_model = {0x10, 0x11, 0x12}; uint8_t model[3]; size_t length = sizeof(model); ASSERT_EQ(kNearbyStatusOK, nearby_fp_client_Init(NULL)); ASSERT_EQ(kNearbyStatusOK, nearby_test_fakes_GattReadModelId(model, &length)); ASSERT_EQ(sizeof(model), length); ASSERT_EQ(expected_model, std::vector(model, model + length)); } TEST(NearbyFpClient, Aes128Encrypt) { uint8_t input[16] = {0xF3, 0x0F, 0x4E, 0x78, 0x6C, 0x59, 0xA7, 0xBB, 0xF3, 0x87, 0x3B, 0x5A, 0x49, 0xBA, 0x97, 0xEA}; uint8_t key[16] = {0xA0, 0xBA, 0xF0, 0xBB, 0x95, 0x1F, 0xF7, 0xB6, 0xCF, 0x5E, 0x3F, 0x45, 0x61, 0xC3, 0x32, 0x1D}; uint8_t expected_output[16] = {0xAC, 0x9A, 0x16, 0xF0, 0x95, 0x3A, 0x3F, 0x22, 0x3D, 0xD1, 0x0C, 0xF5, 0x36, 0xE0, 0x9E, 0x9C}; uint8_t output[16]; ASSERT_EQ(kNearbyStatusOK, nearby_test_fakes_Aes128Encrypt(input, output, key)); for (int i = 0; i < sizeof(expected_output); i++) { ASSERT_EQ(expected_output[i], output[i]) << "Difference at position: " << i; } } #ifdef NEARBY_FP_ENABLE_ADDITIONAL_DATA TEST(NearbyFpClient, HmacSha256) { const uint8_t kData[] = {0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0xEE, 0x4A, 0x24, 0x83, 0x73, 0x80, 0x52, 0xE4, 0x4E, 0x9B, 0x2A, 0x14, 0x5E, 0x5D, 0xDF, 0xAA, 0x44, 0xB9, 0xE5, 0x53, 0x6A, 0xF4, 0x38, 0xE1, 0xE5, 0xC6}; const uint8_t kKey[] = {0x01, 0x23, 0x45, 0x67, 0x89, 0xAB, 0xCD, 0xEF, 0x01, 0x23, 0x45, 0x67, 0x89, 0xAB, 0xCD, 0xEF}; const uint8_t kExpectedResult[] = { 0x55, 0xEC, 0x5E, 0x60, 0x55, 0xAF, 0x6E, 0x92, 0x61, 0x8B, 0x7D, 0x87, 0x10, 0xD4, 0x41, 0x37, 0x09, 0xAB, 0x5D, 0xA2, 0x7C, 0xA2, 0x6A, 0x66, 0xF5, 0x2E, 0x5A, 0xD4, 0xE8, 0x20, 0x90, 0x52}; uint8_t result[32]; ASSERT_EQ(kNearbyStatusOK, nearby_fp_HmacSha256(result, kKey, sizeof(kKey), kData, sizeof(kData))); ASSERT_THAT(result, ElementsAreArray(kExpectedResult)); } TEST(NearbyFpClient, AesCtr) { uint8_t message[] = {0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0xEE, 0x4A, 0x24, 0x83, 0x73, 0x80, 0x52, 0xE4, 0x4E, 0x9B, 0x2A, 0x14, 0x5E, 0x5D, 0xDF, 0xAA, 0x44, 0xB9, 0xE5, 0x53, 0x6A, 0xF4, 0x38, 0xE1, 0xE5, 0xC6}; const uint8_t kKey[] = {0x01, 0x23, 0x45, 0x67, 0x89, 0xAB, 0xCD, 0xEF, 0x01, 0x23, 0x45, 0x67, 0x89, 0xAB, 0xCD, 0xEF}; const uint8_t kExpectedResult[] = { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x53, 0x6F, 0x6D, 0x65, 0x6F, 0x6E, 0x65, 0x27, 0x73, 0x20, 0x47, 0x6F, 0x6F, 0x67, 0x6C, 0x65, 0x20, 0x48, 0x65, 0x61, 0x64, 0x70, 0x68, 0x6F, 0x6E, 0x65}; ASSERT_EQ(kNearbyStatusOK, nearby_fp_AesCtr(message, sizeof(message), kKey)); ASSERT_THAT(message, ElementsAreArray(kExpectedResult)); } TEST(NearbyFpClient, DecodeAdditionalData) { uint8_t message[] = {0x55, 0xEC, 0x5E, 0x60, 0x55, 0xAF, 0x6E, 0x92, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0xEE, 0x4A, 0x24, 0x83, 0x73, 0x80, 0x52, 0xE4, 0x4E, 0x9B, 0x2A, 0x14, 0x5E, 0x5D, 0xDF, 0xAA, 0x44, 0xB9, 0xE5, 0x53, 0x6A, 0xF4, 0x38, 0xE1, 0xE5, 0xC6}; const uint8_t kKey[] = {0x01, 0x23, 0x45, 0x67, 0x89, 0xAB, 0xCD, 0xEF, 0x01, 0x23, 0x45, 0x67, 0x89, 0xAB, 0xCD, 0xEF}; const uint8_t kExpectedResult[] = { 0x55, 0xEC, 0x5E, 0x60, 0x55, 0xAF, 0x6E, 0x92, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x53, 0x6F, 0x6D, 0x65, 0x6F, 0x6E, 0x65, 0x27, 0x73, 0x20, 0x47, 0x6F, 0x6F, 0x67, 0x6C, 0x65, 0x20, 0x48, 0x65, 0x61, 0x64, 0x70, 0x68, 0x6F, 0x6E, 0x65}; ASSERT_EQ(kNearbyStatusOK, nearby_fp_DecodeAdditionalData(message, sizeof(message), kKey)); ASSERT_THAT(message, ElementsAreArray(kExpectedResult)); } TEST(NearbyFpClient, EncodeAdditionalData) { uint8_t message[] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x53, 0x6F, 0x6D, 0x65, 0x6F, 0x6E, 0x65, 0x27, 0x73, 0x20, 0x47, 0x6F, 0x6F, 0x67, 0x6C, 0x65, 0x20, 0x48, 0x65, 0x61, 0x64, 0x70, 0x68, 0x6F, 0x6E, 0x65}; std::vector random_numbers = {0, 1, 2, 3, 4, 5, 6, 7}; const uint8_t kKey[] = {0x01, 0x23, 0x45, 0x67, 0x89, 0xAB, 0xCD, 0xEF, 0x01, 0x23, 0x45, 0x67, 0x89, 0xAB, 0xCD, 0xEF}; const uint8_t kExpectedResult[] = { 0x55, 0xEC, 0x5E, 0x60, 0x55, 0xAF, 0x6E, 0x92, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0xEE, 0x4A, 0x24, 0x83, 0x73, 0x80, 0x52, 0xE4, 0x4E, 0x9B, 0x2A, 0x14, 0x5E, 0x5D, 0xDF, 0xAA, 0x44, 0xB9, 0xE5, 0x53, 0x6A, 0xF4, 0x38, 0xE1, 0xE5, 0xC6}; nearby_test_fakes_SetRandomNumberSequence(random_numbers); ASSERT_EQ(kNearbyStatusOK, nearby_fp_EncodeAdditionalData(message, sizeof(message), kKey)); ASSERT_THAT(message, ElementsAreArray(kExpectedResult)); } TEST(NearbyFpClient, PairAndGetPersonalizedName) { uint8_t name[] = {0x53, 0x6F, 0x6D, 0x65, 0x6F, 0x6E, 0x65, 0x27, 0x73, 0x20, 0x47, 0x6F, 0x6F, 0x67, 0x6C, 0x65, 0x20, 0x48, 0x65, 0x61, 0x64, 0x70, 0x68, 0x6F, 0x6E, 0x65}; nearby_fp_client_Init(NULL); ASSERT_EQ(kNearbyStatusOK, nearby_platform_SaveValue(kStoredKeyPersonalizedName, name, sizeof(name))); Pair(0x60); auto additional_data = nearby_test_fakes_GetGattNotifications().at(kAdditionalData); ASSERT_EQ(kNearbyStatusOK, nearby_fp_DecodeAdditionalData( additional_data.data(), additional_data.size(), kExpectedAesKey)); ASSERT_THAT(std::vector( additional_data.begin() + ADDITIONAL_DATA_HEADER_SIZE, additional_data.end()), ElementsAreArray(name)); } TEST(NearbyFpClient, PairAndSetPersonalizedName) { uint8_t name[] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x53, 0x6F, 0x6D, 0x65, 0x6F, 0x6E, 0x65, 0x27, 0x73, 0x20, 0x47, 0x6F, 0x6F, 0x67, 0x6C, 0x65, 0x20, 0x48, 0x65, 0x61, 0x64, 0x70, 0x68, 0x6F, 0x6E, 0x65}; nearby_fp_EncodeAdditionalData(name, sizeof(name), kSeekerAccountKey); uint8_t request[16]; request[0] = 0x10; // action request request[1] = 0x40; // additional data characteristic // Provider's public address request[2] = 0xA0; request[3] = 0xA1; request[4] = 0xA2; request[5] = 0xA3; request[6] = 0xA4; request[7] = 0xA5; request[8] = 0; // message group, ignored request[9] = 0; // message code, ignored request[10] = 1; // data ID, personalized name // salt request[11] = 0x67; request[12] = 0x89; request[13] = 0xAB; request[14] = 0xCD; request[15] = 0xEF; uint8_t encrypted[16]; nearby_test_fakes_Aes128Encrypt(request, encrypted, kSeekerAccountKey); nearby_fp_client_Init(NULL); Pair(0x40); // Seeker wants to set personalized name ASSERT_EQ(kNearbyStatusOK, nearby_fp_fakes_ReceiveKeyBasedPairingRequest( encrypted, sizeof(encrypted))); nearby_fp_fakes_ReceiveAdditionalData(name, sizeof(name)); uint8_t result[sizeof(name) - ADDITIONAL_DATA_HEADER_SIZE]; size_t length = sizeof(result); ASSERT_EQ(kNearbyStatusOK, nearby_platform_LoadValue( kStoredKeyPersonalizedName, result, &length)); ASSERT_EQ(length, sizeof(result)); ASSERT_THAT(std::vector(name + ADDITIONAL_DATA_HEADER_SIZE, name + sizeof(name)), ElementsAreArray(result)); } #endif /* NEARBY_FP_ENABLE_ADDITIONAL_DATA */ #ifdef NEARBY_FP_MESSAGE_STREAM TEST(NearbyFpClient, RfcommConnected_NoBatteryInfo_SendsModelIdAndBleAddress) { constexpr uint64_t kPeerAddress = 0x123456; constexpr uint8_t kExpectedRfcommOutput[] = {// Model Id 3, 1, 0, 3, 0x10, 0x11, 0x12, // Ble Address 3, 2, 0, 6, 0x6b, 0xab, 0xab, 0xab, 0xab, 0xab}; nearby_fp_client_Init(&kClientCallbacks); Pair(0x40); message_stream_events.clear(); nearby_test_fakes_GetRfcommOutput().clear(); nearby_test_fakes_SetGetBatteryInfoResult(kNearbyStatusUnimplemented); nearby_test_fakes_MessageStreamConnected(kPeerAddress); ASSERT_EQ(1, message_stream_events.size()); ASSERT_EQ(MessageStreamConnectedEvent(kPeerAddress), *message_stream_events[0]); ASSERT_THAT(kExpectedRfcommOutput, ElementsAreArray(nearby_test_fakes_GetRfcommOutput())); } #ifdef NEARBY_FP_RETROACTIVE_PAIRING TEST(NearbyFpClient, RetroactivePair) { nearby_fp_client_Init(NULL); constexpr uint64_t kPeerAddress = 0xB0B1B2B3B4B5; nearby_test_fakes_DevicePaired(kPeerAddress); message_stream_events.clear(); nearby_test_fakes_GetRfcommOutput().clear(); nearby_test_fakes_SetGetBatteryInfoResult(kNearbyStatusOK); nearby_test_fakes_MessageStreamConnected(kPeerAddress); uint8_t salt = 0xAB; nearby_test_fakes_SetAntiSpoofingKey(kBobPrivateKey, kBobPublicKey); nearby_test_fakes_SetRandomNumber(salt); uint8_t request[16]; request[0] = 0x00; // key-based pairing request request[1] = 1 << 4; // Provider's public address request[2] = 0xA0; request[3] = 0xA1; request[4] = 0xA2; request[5] = 0xA3; request[6] = 0xA4; request[7] = 0xA5; // Seeker's address request[8] = 0xB0; request[9] = 0xB1; request[10] = 0xB2; request[11] = 0xB3; request[12] = 0xB4; request[13] = 0xB5; // salt request[14] = 0xCD; request[15] = 0xEF; uint8_t encrypted[16 + 64]; nearby_test_fakes_Aes128Encrypt(request, encrypted, kExpectedAesKey); memcpy(encrypted + 16, kAlicePublicKey, 64); // Seeker responds ASSERT_EQ(kNearbyStatusOK, nearby_fp_fakes_ReceiveKeyBasedPairingRequest( encrypted, sizeof(encrypted))); // Seeker sends their account key uint8_t encrypted_account_key_write_request[16]; nearby_test_fakes_Aes128Encrypt( kSeekerAccountKey, encrypted_account_key_write_request, kExpectedAesKey); nearby_fp_fakes_ReceiveAccountKeyWrite( encrypted_account_key_write_request, sizeof(encrypted_account_key_write_request)); std::cout << "Account keys: " << VecToString(nearby_test_fakes_GetRawAccountKeys()) << std::endl; auto keys = nearby_test_fakes_GetAccountKeys(); ASSERT_EQ(1, keys.size()); ASSERT_EQ(std::vector(kSeekerAccountKey, kSeekerAccountKey + sizeof(kExpectedAesKey)), keys.GetKeys()[0]); } TEST(NearbyFpClient, RetroactivePairAfterInitialPair) { constexpr uint64_t kPeerAddress = 0xB0B1B2B3B4B5; uint8_t salt = 0xAB; ASSERT_EQ(kNearbyStatusOK, nearby_fp_client_Init(NULL)); ASSERT_EQ(kNearbyStatusOK, nearby_test_fakes_SetAntiSpoofingKey( kBobPrivateKey, kBobPublicKey)); ASSERT_EQ(kNearbyStatusOK, nearby_fp_client_SetAdvertisement( NEARBY_FP_ADVERTISEMENT_DISCOVERABLE)); nearby_test_fakes_SetRandomNumber(salt); // Provider sets the advertisement ASSERT_THAT(nearby_test_fakes_GetAdvertisement(), ElementsAreArray(kDiscoverableAdvertisement)); uint8_t request[16]; request[0] = 0x00; // key-based pairing request request[1] = 0x40; // bit 1 (msb) set // Provider's public address request[2] = 0xA0; request[3] = 0xA1; request[4] = 0xA2; request[5] = 0xA3; request[6] = 0xA4; request[7] = 0xA5; // Seeker's address request[8] = 0xB0; request[9] = 0xB1; request[10] = 0xB2; request[11] = 0xB3; request[12] = 0xB4; request[13] = 0xB5; // salt request[14] = 0xCD; request[15] = 0xEF; uint8_t encrypted[16 + 64]; nearby_test_fakes_Aes128Encrypt(request, encrypted, kExpectedAesKey); memcpy(encrypted + 16, kAlicePublicKey, 64); // Seeker responds ASSERT_EQ(kNearbyStatusOK, nearby_fp_fakes_ReceiveKeyBasedPairingRequest( encrypted, sizeof(encrypted))); auto response = nearby_test_fakes_GetGattNotifications().at(kKeyBasedPairing); std::cout << VecToString(response) << std::endl; uint8_t decrypted_response[16]; uint8_t expected_decrypted_response[16] = {0x01, 0xA0, 0xA1, 0xA2, 0xA3, 0xA4, 0xA5, salt, salt, salt, salt, salt, salt, salt, salt, salt}; nearby_test_fakes_Aes128Decrypt(response.data(), decrypted_response, kExpectedAesKey); for (int i = 0; i < sizeof(expected_decrypted_response); i++) { ASSERT_EQ(expected_decrypted_response[i], decrypted_response[i]) << "Difference at position: " << i; } // Provider sends pairing request ASSERT_EQ(kRemoteDevice, nearby_test_fakes_GetPairingRequestAddress()); // BT negotatiates passkey 123456 (0x01E240) uint8_t raw_passkey_block[16] = {0x02, 0x01, 0xE2, 0x40}; uint8_t encrypted_passkey_block[16]; nearby_test_fakes_Aes128Encrypt(raw_passkey_block, encrypted_passkey_block, kExpectedAesKey); // Seeker sends the passkey to provider nearby_fp_fakes_ReceivePasskey(encrypted_passkey_block, sizeof(encrypted_passkey_block)); // Provider sends the passkey to seeker response = nearby_test_fakes_GetGattNotifications().at(kPasskey); nearby_test_fakes_Aes128Decrypt(response.data(), decrypted_response, kExpectedAesKey); uint8_t expected_passkey_block[16] = {0x03, 0x01, 0xE2, 0x40, salt, salt, salt, salt, salt, salt, salt, salt, salt, salt, salt, salt}; for (int i = 0; i < sizeof(expected_decrypted_response); i++) { ASSERT_EQ(expected_passkey_block[i], decrypted_response[i]) << "Difference at position: " << i; } ASSERT_EQ(123456, nearby_test_fakes_GetRemotePasskey()); ASSERT_EQ(kRemoteDevice, nearby_test_fakes_GetPairedDevice()); // Seeker sends their account key WriteToAccountKey(); std::cout << "Account keys: " << VecToString(nearby_test_fakes_GetRawAccountKeys()) << std::endl; auto keys = nearby_test_fakes_GetAccountKeys(); ASSERT_EQ(1, keys.size()); ASSERT_EQ(std::vector(kSeekerAccountKey, kSeekerAccountKey + sizeof(kExpectedAesKey)), keys.GetKeys()[0]); message_stream_events.clear(); nearby_test_fakes_GetRfcommOutput().clear(); nearby_test_fakes_SetGetBatteryInfoResult(kNearbyStatusOK); nearby_test_fakes_MessageStreamConnected(kPeerAddress); // Retroactive pairing request[0] = 0x00; // key-based pairing request request[1] = 1 << 4; // Provider's public address request[2] = 0xA0; request[3] = 0xA1; request[4] = 0xA2; request[5] = 0xA3; request[6] = 0xA4; request[7] = 0xA5; // Seeker's address request[8] = 0xB0; request[9] = 0xB1; request[10] = 0xB2; request[11] = 0xB3; request[12] = 0xB4; request[13] = 0xB5; // salt request[14] = 0xCD; request[15] = 0xEF; nearby_test_fakes_Aes128Encrypt(request, encrypted, kExpectedAesKey); memcpy(encrypted + 16, kAlicePublicKey, 64); // Seeker responds ASSERT_NE(kNearbyStatusOK, nearby_fp_fakes_ReceiveKeyBasedPairingRequest( encrypted, sizeof(encrypted))); // Seeker sends their account key uint8_t encrypted_account_key_write_request[16]; nearby_test_fakes_Aes128Encrypt( kSeekerAccountKey2, encrypted_account_key_write_request, kExpectedAesKey); ASSERT_NE(kNearbyStatusOK, nearby_fp_fakes_ReceiveAccountKeyWrite( encrypted_account_key_write_request, sizeof(encrypted_account_key_write_request))); keys = nearby_test_fakes_GetAccountKeys(); ASSERT_EQ(1, keys.size()); ASSERT_EQ(std::vector(kSeekerAccountKey, kSeekerAccountKey + sizeof(kExpectedAesKey)), keys.GetKeys()[0]); } TEST(NearbyFpClient, RetroactivePairTwice) { nearby_fp_client_Init(NULL); constexpr uint64_t kPeerAddress = 0xB0B1B2B3B4B5; nearby_test_fakes_DevicePaired(kPeerAddress); message_stream_events.clear(); nearby_test_fakes_GetRfcommOutput().clear(); nearby_test_fakes_SetGetBatteryInfoResult(kNearbyStatusOK); nearby_test_fakes_MessageStreamConnected(kPeerAddress); uint8_t salt = 0xAB; nearby_test_fakes_SetAntiSpoofingKey(kBobPrivateKey, kBobPublicKey); nearby_test_fakes_SetRandomNumber(salt); uint8_t request[16]; request[0] = 0x00; // key-based pairing request request[1] = 1 << 4; // Provider's public address request[2] = 0xA0; request[3] = 0xA1; request[4] = 0xA2; request[5] = 0xA3; request[6] = 0xA4; request[7] = 0xA5; // Seeker's address request[8] = 0xB0; request[9] = 0xB1; request[10] = 0xB2; request[11] = 0xB3; request[12] = 0xB4; request[13] = 0xB5; // salt request[14] = 0xCD; request[15] = 0xEF; uint8_t encrypted[16 + 64]; nearby_test_fakes_Aes128Encrypt(request, encrypted, kExpectedAesKey); memcpy(encrypted + 16, kAlicePublicKey, 64); // Seeker responds ASSERT_EQ(kNearbyStatusOK, nearby_fp_fakes_ReceiveKeyBasedPairingRequest( encrypted, sizeof(encrypted))); // Seeker sends their account key uint8_t encrypted_account_key_write_request[16]; nearby_test_fakes_Aes128Encrypt( kSeekerAccountKey, encrypted_account_key_write_request, kExpectedAesKey); ASSERT_EQ(kNearbyStatusOK, nearby_fp_fakes_ReceiveAccountKeyWrite( encrypted_account_key_write_request, sizeof(encrypted_account_key_write_request))); std::cout << "Account keys: " << VecToString(nearby_test_fakes_GetRawAccountKeys()) << std::endl; auto keys = nearby_test_fakes_GetAccountKeys(); ASSERT_EQ(1, keys.size()); ASSERT_EQ(std::vector(kSeekerAccountKey, kSeekerAccountKey + sizeof(kExpectedAesKey)), keys.GetKeys()[0]); nearby_test_fakes_SetRandomNumber(salt); request[0] = 0x00; // key-based pairing request request[1] = 1 << 4; // Provider's public address request[2] = 0xA0; request[3] = 0xA1; request[4] = 0xA2; request[5] = 0xA3; request[6] = 0xA4; request[7] = 0xA5; // Seeker's address request[8] = 0xB0; request[9] = 0xB1; request[10] = 0xB2; request[11] = 0xB3; request[12] = 0xB4; request[13] = 0xB5; // salt request[14] = 0xCD; request[15] = 0xEF; nearby_test_fakes_Aes128Encrypt(request, encrypted, kExpectedAesKey); memcpy(encrypted + 16, kAlicePublicKey, 64); // Seeker responds ASSERT_NE(kNearbyStatusOK, nearby_fp_fakes_ReceiveKeyBasedPairingRequest( encrypted, sizeof(encrypted))); // Seeker sends their account key nearby_test_fakes_Aes128Encrypt( kSeekerAccountKey2, encrypted_account_key_write_request, kExpectedAesKey); ASSERT_NE(kNearbyStatusOK, nearby_fp_fakes_ReceiveAccountKeyWrite( encrypted_account_key_write_request, sizeof(encrypted_account_key_write_request))); keys = nearby_test_fakes_GetAccountKeys(); ASSERT_EQ(1, keys.size()); ASSERT_EQ(std::vector(kSeekerAccountKey, kSeekerAccountKey + sizeof(kExpectedAesKey)), keys.GetKeys()[0]); } TEST(NearbyFpClient, RetroactivePairWrongBtAddress) { nearby_fp_client_Init(NULL); constexpr uint64_t kPeerAddress = 0xB0B1B2B3B4B5; nearby_test_fakes_DevicePaired(kPeerAddress); message_stream_events.clear(); nearby_test_fakes_GetRfcommOutput().clear(); nearby_test_fakes_SetGetBatteryInfoResult(kNearbyStatusOK); nearby_test_fakes_MessageStreamConnected(kPeerAddress); uint8_t salt = 0xAB; nearby_test_fakes_SetAntiSpoofingKey(kBobPrivateKey, kBobPublicKey); nearby_test_fakes_SetRandomNumber(salt); uint8_t request[16]; request[0] = 0x00; // key-based pairing request request[1] = 1 << 4; // Provider's public address request[2] = 0xA0; request[3] = 0xA1; request[4] = 0xA2; request[5] = 0xA3; request[6] = 0xA4; request[7] = 0xA5; // Seeker's address request[8] = 0xC0; request[9] = 0xC1; request[10] = 0xC2; request[11] = 0xC3; request[12] = 0xC4; request[13] = 0xC5; // salt request[14] = 0xCD; request[15] = 0xEF; uint8_t encrypted[16 + 64]; nearby_test_fakes_Aes128Encrypt(request, encrypted, kExpectedAesKey); memcpy(encrypted + 16, kAlicePublicKey, 64); // Seeker responds ASSERT_NE(kNearbyStatusOK, nearby_fp_fakes_ReceiveKeyBasedPairingRequest( encrypted, sizeof(encrypted))); // Seeker sends their account key uint8_t encrypted_account_key_write_request[16]; nearby_test_fakes_Aes128Encrypt( kSeekerAccountKey, encrypted_account_key_write_request, kExpectedAesKey); ASSERT_NE(kNearbyStatusOK, nearby_fp_fakes_ReceiveAccountKeyWrite( encrypted_account_key_write_request, sizeof(encrypted_account_key_write_request))); auto keys = nearby_test_fakes_GetAccountKeys(); ASSERT_EQ(0, keys.size()); } #endif /* NEARBY_FP_RETROACTIVE_PAIRING */ TEST(NearbyFpClient, RfcommConnected_ClientDisconnects_EmitsDisconnectEvent) { constexpr uint64_t kPeerAddress = 0x123456; nearby_fp_client_Init(&kClientCallbacks); Pair(0x40); message_stream_events.clear(); nearby_test_fakes_GetRfcommOutput().clear(); nearby_test_fakes_SetGetBatteryInfoResult(kNearbyStatusUnimplemented); nearby_test_fakes_MessageStreamConnected(kPeerAddress); nearby_test_fakes_MessageStreamDisconnected(kPeerAddress); ASSERT_EQ(2, message_stream_events.size()); ASSERT_EQ(MessageStreamConnectedEvent(kPeerAddress), *message_stream_events[0]); ASSERT_EQ(MessageStreamDisconnectedEvent(kPeerAddress), *message_stream_events[1]); } TEST(NearbyFpClient, RfcommConnected_PeerSendsMessage_PassMessageToClientApp) { constexpr uint64_t kPeerAddress = 0x123456; constexpr uint8_t kPeerMessage[] = {101, 102, 0, 4, 81, 82, 83, 84}; const nearby_event_MessageStreamReceived kExpectedMessage = { .peer_address = kPeerAddress, .message_group = kPeerMessage[0], .message_code = kPeerMessage[1], .length = kPeerMessage[2] * 256 + kPeerMessage[3], .data = (uint8_t*)kPeerMessage + 4, }; nearby_fp_client_Init(&kClientCallbacks); Pair(0x40); message_stream_events.clear(); nearby_test_fakes_GetRfcommOutput().clear(); nearby_test_fakes_SetGetBatteryInfoResult(kNearbyStatusUnimplemented); nearby_test_fakes_MessageStreamConnected(kPeerAddress); nearby_test_fakes_MessageStreamReceived(kPeerAddress, kPeerMessage, sizeof(kPeerMessage)); ASSERT_EQ(2, message_stream_events.size()); ASSERT_EQ(MessageStreamConnectedEvent(kPeerAddress), *message_stream_events[0]); ASSERT_EQ(MessageStreamReceivedEvent(&kExpectedMessage), *message_stream_events[1]); } TEST(NearbyFpClient, RfcommConnected_ConnectAndDisconnect_CanHandleManySessions) { constexpr uint64_t kPeerAddress = 0x123456; constexpr uint8_t kPeerMessage[] = {101, 102, 0, 4, 81, 82, 83, 84}; const nearby_event_MessageStreamReceived kExpectedMessage = { .peer_address = kPeerAddress, .message_group = kPeerMessage[0], .message_code = kPeerMessage[1], .length = kPeerMessage[2] * 256 + kPeerMessage[3], .data = (uint8_t*)kPeerMessage + 4, }; nearby_fp_client_Init(&kClientCallbacks); Pair(0x40); message_stream_events.clear(); nearby_test_fakes_GetRfcommOutput().clear(); nearby_test_fakes_SetGetBatteryInfoResult(kNearbyStatusUnimplemented); for (int i = 1; i < NEARBY_MAX_RFCOMM_CONNECTIONS + 10; i++) { nearby_test_fakes_MessageStreamConnected(kPeerAddress + i); nearby_test_fakes_MessageStreamDisconnected(kPeerAddress + i); } nearby_test_fakes_MessageStreamConnected(kPeerAddress); nearby_test_fakes_MessageStreamReceived(kPeerAddress, kPeerMessage, sizeof(kPeerMessage)); int events = message_stream_events.size(); ASSERT_EQ(MessageStreamConnectedEvent(kPeerAddress), *message_stream_events[events - 2]); ASSERT_EQ(MessageStreamReceivedEvent(&kExpectedMessage), *message_stream_events[events - 1]); } #if NEARBY_MAX_RFCOMM_CONNECTIONS > 1 TEST(NearbyFpClient, RfcommConnected_TwoInterleavedConnections_ParsesMessages) { constexpr uint64_t kPeerAddress1 = 0x123456; constexpr uint8_t kPeerMessage1[] = {101, 102, 0, 4, 81, 82, 83, 84}; const nearby_event_MessageStreamReceived kExpectedMessage1 = { .peer_address = kPeerAddress1, .message_group = kPeerMessage1[0], .message_code = kPeerMessage1[1], .length = kPeerMessage1[2] * 256 + kPeerMessage1[3], .data = (uint8_t*)kPeerMessage1 + 4, }; constexpr uint64_t kPeerAddress2 = 0x7890ab; constexpr uint8_t kPeerMessage2[] = {201, 202, 0, 5, 91, 92, 93, 94, 95}; const nearby_event_MessageStreamReceived kExpectedMessage2 = { .peer_address = kPeerAddress2, .message_group = kPeerMessage2[0], .message_code = kPeerMessage2[1], .length = kPeerMessage2[2] * 256 + kPeerMessage2[3], .data = (uint8_t*)kPeerMessage2 + 4, }; nearby_fp_client_Init(&kClientCallbacks); Pair(0x40); message_stream_events.clear(); nearby_test_fakes_GetRfcommOutput().clear(); nearby_test_fakes_SetGetBatteryInfoResult(kNearbyStatusUnimplemented); nearby_test_fakes_MessageStreamConnected(kPeerAddress1); nearby_test_fakes_MessageStreamConnected(kPeerAddress2); // Send the messages byte by byte, interleaving bytes from both connections // to verify that the parses handles the streams separately for (int i = 0; i < std::max(sizeof(kPeerMessage1), sizeof(kPeerMessage2)); i++) { if (i < sizeof(kPeerMessage1)) { nearby_test_fakes_MessageStreamReceived(kPeerAddress1, kPeerMessage1 + i, 1); } if (i < sizeof(kPeerMessage2)) { nearby_test_fakes_MessageStreamReceived(kPeerAddress2, kPeerMessage2 + i, 1); } } ASSERT_EQ(4, message_stream_events.size()); ASSERT_EQ(MessageStreamConnectedEvent(kPeerAddress1), *message_stream_events[0]); ASSERT_EQ(MessageStreamConnectedEvent(kPeerAddress2), *message_stream_events[1]); ASSERT_EQ(MessageStreamReceivedEvent(&kExpectedMessage1), *message_stream_events[2]); ASSERT_EQ(MessageStreamReceivedEvent(&kExpectedMessage2), *message_stream_events[3]); } #endif /* NEARBY_MAX_RFCOMM_CONNECTIONS > 1 */ TEST(NearbyFpClient, SendMessageStreamMessage) { constexpr nearby_message_stream_Message kMessage{ .message_group = 20, .message_code = 10, }; constexpr uint8_t kExpectedRfcommOutput[] = {20, 10, 0, 0}; nearby_fp_client_Init(&kClientCallbacks); nearby_test_fakes_GetRfcommOutput().clear(); nearby_fp_client_SendMessage(0x123456, &kMessage); ASSERT_THAT(kExpectedRfcommOutput, ElementsAreArray(nearby_test_fakes_GetRfcommOutput())); } TEST(NearbyFpClient, SendAck) { constexpr uint64_t kPeerAddress = 0x123456; constexpr nearby_event_MessageStreamReceived kMessage{ .peer_address = kPeerAddress, .message_group = 20, .message_code = 10, }; constexpr uint8_t kExpectedRfcommOutput[] = {0xFF, 1, 0, 2, 20, 10}; nearby_fp_client_Init(&kClientCallbacks); nearby_test_fakes_GetRfcommOutput().clear(); nearby_fp_client_SendAck(&kMessage); ASSERT_THAT(kExpectedRfcommOutput, ElementsAreArray(nearby_test_fakes_GetRfcommOutput())); } TEST(NearbyFpClient, SendNack) { constexpr uint64_t kPeerAddress = 0x123456; constexpr uint8_t kFailReason = 30; constexpr nearby_event_MessageStreamReceived kMessage{ .peer_address = kPeerAddress, .message_group = 20, .message_code = 10, }; constexpr uint8_t kExpectedRfcommOutput[] = {0xFF, 2, 0, 3, kFailReason, 20, 10}; nearby_fp_client_Init(&kClientCallbacks); nearby_test_fakes_GetRfcommOutput().clear(); nearby_fp_client_SendNack(&kMessage, kFailReason); ASSERT_THAT(kExpectedRfcommOutput, ElementsAreArray(nearby_test_fakes_GetRfcommOutput())); } #endif /* NEARBY_FP_MESSAGE_STREAM */ TEST(NearbyFpClient, TimerTriggered_RotatesBleAddress) { uint64_t firstAddress, secondAddress, thirdAddress; nearby_fp_client_Init(NULL); nearby_test_fakes_SetInPairingMode(false); nearby_fp_client_SetAdvertisement(NEARBY_FP_ADVERTISEMENT_DISCOVERABLE); firstAddress = nearby_platform_GetBleAddress(); nearby_test_fakes_SetRandomNumber(30); nearby_test_fakes_SetCurrentTimeMs(nearby_test_fakes_GetNextTimerMs()); secondAddress = nearby_platform_GetBleAddress(); nearby_test_fakes_SetRandomNumber(31); nearby_test_fakes_SetCurrentTimeMs(nearby_test_fakes_GetNextTimerMs()); thirdAddress = nearby_platform_GetBleAddress(); ASSERT_NE(firstAddress, secondAddress); ASSERT_NE(secondAddress, thirdAddress); } TEST(NearbyFpClient, TimerTriggered_InPairingMode_DoesntRotateBleAddress) { uint64_t firstAddress, secondAddress, thirdAddress; nearby_fp_client_Init(NULL); nearby_test_fakes_SetInPairingMode(false); nearby_fp_client_SetAdvertisement(NEARBY_FP_ADVERTISEMENT_NON_DISCOVERABLE); firstAddress = nearby_platform_GetBleAddress(); nearby_test_fakes_SetInPairingMode(true); nearby_test_fakes_SetRandomNumber(30); nearby_test_fakes_SetCurrentTimeMs(nearby_test_fakes_GetNextTimerMs()); secondAddress = nearby_platform_GetBleAddress(); nearby_test_fakes_SetInPairingMode(false); nearby_test_fakes_SetRandomNumber(31); nearby_test_fakes_SetCurrentTimeMs(nearby_test_fakes_GetNextTimerMs()); thirdAddress = nearby_platform_GetBleAddress(); ASSERT_EQ(firstAddress, secondAddress); ASSERT_NE(secondAddress, thirdAddress); } TEST(NearbyFpClient, AdvertiseDisoverable_RotatesBleAddress) { uint64_t firstAddress; nearby_fp_client_Init(NULL); nearby_test_fakes_SetInPairingMode(false); firstAddress = nearby_platform_GetBleAddress(); nearby_test_fakes_SetRandomNumber(32); nearby_fp_client_SetAdvertisement(NEARBY_FP_ADVERTISEMENT_DISCOVERABLE); ASSERT_NE(firstAddress, nearby_platform_GetBleAddress()); } TEST(NearbyFpClient, AdvertiseDisoverable_InPairingMode_DoesntRotatesBleAddress) { uint64_t firstAddress; nearby_fp_client_Init(NULL); nearby_test_fakes_SetInPairingMode(true); firstAddress = nearby_platform_GetBleAddress(); nearby_test_fakes_SetRandomNumber(32); nearby_fp_client_SetAdvertisement(NEARBY_FP_ADVERTISEMENT_DISCOVERABLE); ASSERT_EQ(firstAddress, nearby_platform_GetBleAddress()); } TEST(NearbyFpClient, ChangeAdvertisementType_InPairingMode_DoesntRotateBleAddress) { uint64_t firstAddress; nearby_fp_client_Init(NULL); nearby_test_fakes_SetInPairingMode(true); nearby_fp_client_SetAdvertisement(NEARBY_FP_ADVERTISEMENT_NON_DISCOVERABLE); firstAddress = nearby_platform_GetBleAddress(); nearby_test_fakes_SetRandomNumber(34); nearby_fp_client_SetAdvertisement(NEARBY_FP_ADVERTISEMENT_DISCOVERABLE); ASSERT_EQ(firstAddress, nearby_platform_GetBleAddress()); } TEST(NearbyFpClient, ChangeAdvertisementFlags_DoesntRotateBleAddress) { uint64_t firstAddress; nearby_fp_client_Init(NULL); nearby_test_fakes_SetInPairingMode(false); nearby_fp_client_SetAdvertisement(NEARBY_FP_ADVERTISEMENT_NON_DISCOVERABLE); firstAddress = nearby_platform_GetBleAddress(); nearby_test_fakes_SetRandomNumber(36); nearby_fp_client_SetAdvertisement( NEARBY_FP_ADVERTISEMENT_NON_DISCOVERABLE | NEARBY_FP_ADVERTISEMENT_PAIRING_UI_INDICATOR); ASSERT_EQ(firstAddress, nearby_platform_GetBleAddress()); } #pragma GCC diagnostic pop int main(int argc, char** argv) { ::testing::InitGoogleTest(&argc, argv); return RUN_ALL_TESTS(); }