Files
nearby/embedded/client/tests/smoke_test.cc
T
Janusz Sobczak daac1e01c8 Add embedded SDK
The first release, v1.0.0-embedded, of Nearby SDK for embedded devices.
2022-04-14 11:57:25 -07:00

2200 lines
86 KiB
C++

// 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 <cerrno>
#include <iomanip>
#include <iostream>
#include <memory>
#include <sstream>
#include <string>
#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<uint8_t> 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<uint8_t>(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<uint8_t>(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<uint8_t> data_;
};
std::ostream& operator<<(std::ostream& os, const Event& event) {
os << event.ToString();
return os;
}
static std::unique_ptr<Event> GetEvent(const nearby_event_Event* event) {
switch (event->event_type) {
case kNearbyEventMessageStreamConnected:
return std::make_unique<MessageStreamConnectedEvent>(event);
case kNearbyEventMessageStreamDisconnected:
return std::make_unique<MessageStreamDisconnectedEvent>(event);
case kNearbyEventMessageStreamReceived:
return std::make_unique<MessageStreamReceivedEvent>(event);
}
return std::make_unique<Event>(event);
}
std::vector<std::unique_ptr<Event>> 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<uint8_t>(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<uint8_t>(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<uint8_t>(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<uint8_t>(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<uint8_t>(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<uint8_t>(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<uint8_t>(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<uint8_t>(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<uint8_t>(kSeekerAccountKey,
kSeekerAccountKey + sizeof(kExpectedAesKey)),
keys.GetKeys()[0]);
}
TEST(NearbyFpClient, ReadModelId) {
std::vector<uint8_t> 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<uint8_t>(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<uint8_t> 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<uint8_t>(
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<uint8_t>(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<uint8_t>(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<uint8_t>(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<uint8_t>(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<uint8_t>(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<uint8_t>(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();
}