mirror of
https://github.com/kidfromjupiter/nearby.git
synced 2026-09-14 14:46:12 -04:00
Add initial pairing in scalable seeker
PiperOrigin-RevId: 541034178
This commit is contained in:
committed by
Copybara-Service
parent
4914cbc2f9
commit
20acd4eeb9
@@ -19,6 +19,7 @@ cc_library(
|
||||
"//fastpair/scanning:scanner",
|
||||
"//internal/platform:types",
|
||||
"@com_google_absl//absl/status",
|
||||
"@com_google_absl//absl/strings:str_format",
|
||||
],
|
||||
)
|
||||
|
||||
@@ -30,6 +31,7 @@ cc_test(
|
||||
],
|
||||
deps = [
|
||||
":internal",
|
||||
"//fastpair/message_stream:fake_gatt_callbacks",
|
||||
"//fastpair/message_stream:fake_provider",
|
||||
"//fastpair/server_access:test_support",
|
||||
"//internal/platform:test_util",
|
||||
|
||||
@@ -20,6 +20,7 @@
|
||||
#include <utility>
|
||||
|
||||
#include "absl/status/status.h"
|
||||
#include "absl/strings/str_format.h"
|
||||
#include "fastpair/fast_pair_events.h"
|
||||
#include "fastpair/pairing/pairer_broker_impl.h"
|
||||
#include "fastpair/scanning/scanner_broker_impl.h"
|
||||
@@ -36,10 +37,23 @@ FastPairSeekerImpl::FastPairSeekerImpl(ServiceCallbacks callbacks,
|
||||
pairer_broker_->AddObserver(this);
|
||||
}
|
||||
|
||||
FastPairSeekerImpl::~FastPairSeekerImpl() {
|
||||
pairer_broker_->RemoveObserver(this);
|
||||
FinishPairing(absl::AbortedError("Pairing terminated"));
|
||||
DestroyOnExecutor(std::move(pairer_broker_), executor_);
|
||||
}
|
||||
|
||||
absl::Status FastPairSeekerImpl::StartInitialPairing(
|
||||
const FastPairDevice& device, const InitialPairingParam& params,
|
||||
PairingCallback callback) {
|
||||
return absl::UnimplementedError("StartInitialPairing");
|
||||
if (pairer_broker_->IsPairing()) {
|
||||
return absl::AlreadyExistsError("Already pairing");
|
||||
}
|
||||
|
||||
pairing_callback_ = std::make_unique<PairingCallback>(std::move(callback));
|
||||
device_under_pairing_ = &const_cast<FastPairDevice&>(device);
|
||||
pairer_broker_->PairDevice(*device_under_pairing_);
|
||||
return absl::OkStatus();
|
||||
}
|
||||
|
||||
absl::Status FastPairSeekerImpl::StartSubsequentPairing(
|
||||
@@ -84,6 +98,9 @@ void FastPairSeekerImpl::OnDeviceFound(FastPairDevice& device) {
|
||||
// ScannerBroker::Observer::OnDeviceLost
|
||||
void FastPairSeekerImpl::OnDeviceLost(FastPairDevice& device) {
|
||||
NEARBY_LOGS(INFO) << "Device lost: " << device;
|
||||
if (IsDeviceUnderPairing(device)) {
|
||||
FinishPairing(absl::UnavailableError("Device lost during pairing"));
|
||||
}
|
||||
}
|
||||
|
||||
// PairerBroker:Observer::OnDevicePaired
|
||||
@@ -109,6 +126,11 @@ void FastPairSeekerImpl::OnAccountKeyWrite(FastPairDevice& device,
|
||||
// PairerBroker:Observer::OnPairingComplete
|
||||
void FastPairSeekerImpl::OnPairingComplete(FastPairDevice& device) {
|
||||
NEARBY_LOGS(INFO) << __func__ << ": " << device;
|
||||
if (!IsDeviceUnderPairing(device)) {
|
||||
NEARBY_LOGS(WARNING) << "unexpected on pair complete callback";
|
||||
return;
|
||||
}
|
||||
FinishPairing(absl::OkStatus());
|
||||
}
|
||||
|
||||
// PairerBroker:Observer::OnPairFailure
|
||||
@@ -116,6 +138,24 @@ void FastPairSeekerImpl::OnPairFailure(FastPairDevice& device,
|
||||
PairFailure failure) {
|
||||
NEARBY_LOGS(INFO) << __func__ << ": " << device
|
||||
<< " with PairFailure: " << failure;
|
||||
if (!IsDeviceUnderPairing(device)) {
|
||||
NEARBY_LOGS(WARNING) << "unexpected on pair failure callback";
|
||||
return;
|
||||
}
|
||||
FinishPairing(
|
||||
absl::InternalError(absl::StrFormat("Pairing failed with %v", failure)));
|
||||
}
|
||||
|
||||
bool FastPairSeekerImpl::IsDeviceUnderPairing(const FastPairDevice& device) {
|
||||
return device_under_pairing_ == &device;
|
||||
}
|
||||
|
||||
void FastPairSeekerImpl::FinishPairing(absl::Status result) {
|
||||
if (pairing_callback_ && device_under_pairing_ != nullptr) {
|
||||
pairing_callback_->on_pairing_result(*device_under_pairing_, result);
|
||||
}
|
||||
pairing_callback_.reset();
|
||||
device_under_pairing_ = nullptr;
|
||||
}
|
||||
|
||||
void FastPairSeekerImpl::SetIsScreenLocked(bool locked) {
|
||||
|
||||
@@ -22,7 +22,7 @@
|
||||
#include "fastpair/fast_pair_events.h"
|
||||
#include "fastpair/fast_pair_seeker.h"
|
||||
#include "fastpair/internal/mediums/mediums.h"
|
||||
#include "fastpair/pairing/pairer_broker.h"
|
||||
#include "fastpair/pairing/pairer_broker_impl.h"
|
||||
#include "fastpair/repository/fast_pair_device_repository.h"
|
||||
#include "fastpair/scanning/scanner_broker_impl.h"
|
||||
#include "internal/platform/single_thread_executor.h"
|
||||
@@ -58,6 +58,8 @@ class FastPairSeekerImpl : public FastPairSeekerExt,
|
||||
FastPairSeekerImpl(ServiceCallbacks callbacks, SingleThreadExecutor* executor,
|
||||
FastPairDeviceRepository* devices);
|
||||
|
||||
~FastPairSeekerImpl() override;
|
||||
|
||||
// From FastPairSeeker.
|
||||
absl::Status StartInitialPairing(const FastPairDevice& device,
|
||||
const InitialPairingParam& params,
|
||||
@@ -92,6 +94,8 @@ class FastPairSeekerImpl : public FastPairSeekerExt,
|
||||
void OnPairFailure(FastPairDevice& device, PairFailure failure) override;
|
||||
|
||||
void InvalidateScanningState() ABSL_EXCLUSIVE_LOCKS_REQUIRED(*executor_);
|
||||
bool IsDeviceUnderPairing(const FastPairDevice& device);
|
||||
void FinishPairing(absl::Status result);
|
||||
|
||||
ServiceCallbacks callbacks_;
|
||||
SingleThreadExecutor* executor_;
|
||||
@@ -99,7 +103,9 @@ class FastPairSeekerImpl : public FastPairSeekerExt,
|
||||
Mediums mediums_;
|
||||
std::unique_ptr<ScannerBrokerImpl> scanner_;
|
||||
std::unique_ptr<ScannerBrokerImpl::ScanningSession> scanning_session_;
|
||||
std::unique_ptr<PairerBroker> pairer_broker_;
|
||||
std::unique_ptr<PairerBrokerImpl> pairer_broker_;
|
||||
std::unique_ptr<PairingCallback> pairing_callback_;
|
||||
FastPairDevice* device_under_pairing_ = nullptr;
|
||||
FastPairDevice* test_device_ = nullptr;
|
||||
bool is_screen_locked_ = false;
|
||||
};
|
||||
|
||||
@@ -23,6 +23,8 @@
|
||||
#include "protobuf-matchers/protocol-buffer-matchers.h"
|
||||
#include "gtest/gtest.h"
|
||||
#include "absl/time/clock.h"
|
||||
#include "absl/time/time.h"
|
||||
#include "fastpair/message_stream/fake_gatt_callbacks.h"
|
||||
#include "fastpair/message_stream/fake_provider.h"
|
||||
#include "fastpair/server_access/fake_fast_pair_repository.h"
|
||||
#include "internal/platform/count_down_latch.h"
|
||||
@@ -36,9 +38,13 @@ constexpr absl::string_view kServiceID{"Fast Pair"};
|
||||
constexpr absl::string_view kFastPairServiceUuid{
|
||||
"0000FE2C-0000-1000-8000-00805F9B34FB"};
|
||||
constexpr absl::string_view kModelId{"718c17"};
|
||||
constexpr absl::string_view kPublicAntiSpoof =
|
||||
"Wuyr48lD3txnUhGiMF1IfzlTwRxxe+wMB1HLzP+"
|
||||
"0wVcljfT3XPoiy1fntlneziyLD5knDVAJSE+RM/zlPRP/Jg==";
|
||||
constexpr absl::string_view kBobPrivateKey =
|
||||
"02B437B0EDD6BBD429064A4E529FCBF1C48D0D624924D592274B7ED81193D763";
|
||||
constexpr absl::string_view kBobPublicKey =
|
||||
"F7D496A62ECA416351540AA343BC690A6109F551500666B83B1251FB84FA2860795EBD63D3"
|
||||
"B8836F44A9A3E28BB34017E015F5979305D849FDF8DE10123B61D2";
|
||||
constexpr absl::string_view kPasskey = "123456";
|
||||
|
||||
constexpr absl::Duration kTaskWaitTimeout = absl::Milliseconds(100);
|
||||
|
||||
using ::testing::status::StatusIs;
|
||||
@@ -52,7 +58,8 @@ class MediumEnvironmentStarter {
|
||||
class FastPairSeekerImplTest : public testing::Test {
|
||||
protected:
|
||||
void SetUp() override {
|
||||
repository_ = FakeFastPairRepository::Create(kModelId, kPublicAntiSpoof);
|
||||
repository_ = FakeFastPairRepository::Create(
|
||||
kModelId, absl::HexStringToBytes(kBobPublicKey));
|
||||
}
|
||||
|
||||
void TearDown() override { executor_.Shutdown(); }
|
||||
@@ -62,6 +69,7 @@ class FastPairSeekerImplTest : public testing::Test {
|
||||
FastPairDeviceRepository devices_{&executor_};
|
||||
std::unique_ptr<FakeFastPairRepository> repository_;
|
||||
std::unique_ptr<FastPairSeekerImpl> fast_pair_seeker_;
|
||||
FakeGattCallbacks fake_gatt_callbacks_;
|
||||
};
|
||||
|
||||
TEST_F(FastPairSeekerImplTest, StartAndStopFastPairScan) {
|
||||
@@ -136,6 +144,46 @@ TEST_F(FastPairSeekerImplTest, ScreenLocksDuringAdvertising) {
|
||||
EXPECT_FALSE(latch.Await(kTaskWaitTimeout).result());
|
||||
}
|
||||
|
||||
TEST_F(FastPairSeekerImplTest, InitialPairing) {
|
||||
NEARBY_LOG_SET_SEVERITY(VERBOSE);
|
||||
FakeProvider provider;
|
||||
CountDownLatch discover_latch(1);
|
||||
CountDownLatch pair_latch(1);
|
||||
fast_pair_seeker_ = std::make_unique<FastPairSeekerImpl>(
|
||||
FastPairSeekerImpl::ServiceCallbacks{
|
||||
.on_initial_discovery =
|
||||
[&](const FastPairDevice& device, InitialDiscoveryEvent event) {
|
||||
EXPECT_EQ(device.GetModelId(), kModelId);
|
||||
EXPECT_OK(fast_pair_seeker_->StartInitialPairing(
|
||||
device, {},
|
||||
{.on_pairing_result = [&](const FastPairDevice& device,
|
||||
absl::Status status) {
|
||||
EXPECT_EQ(device.GetBleAddress(),
|
||||
provider.GetMacAddress());
|
||||
EXPECT_OK(status);
|
||||
pair_latch.CountDown();
|
||||
}}));
|
||||
discover_latch.CountDown();
|
||||
}},
|
||||
&executor_, &devices_);
|
||||
|
||||
EXPECT_OK(fast_pair_seeker_->StartFastPairScan());
|
||||
provider.PrepareForInitialPairing(
|
||||
{
|
||||
.private_key = absl::HexStringToBytes(kBobPrivateKey),
|
||||
.public_key = absl::HexStringToBytes(kBobPublicKey),
|
||||
.model_id = std::string(kModelId),
|
||||
.pass_key = std::string(kPasskey),
|
||||
},
|
||||
&fake_gatt_callbacks_);
|
||||
|
||||
discover_latch.Await();
|
||||
pair_latch.Await();
|
||||
auto fp_device = devices_.FindDevice(provider.GetMacAddress());
|
||||
ASSERT_TRUE(fp_device.has_value());
|
||||
EXPECT_EQ(provider.GetAccountKey(), fp_device.value()->GetAccountKey());
|
||||
}
|
||||
|
||||
} // namespace
|
||||
} // namespace fastpair
|
||||
} // namespace nearby
|
||||
|
||||
@@ -55,6 +55,7 @@ cc_library(
|
||||
"//fastpair:__subpackages__",
|
||||
],
|
||||
deps = [
|
||||
":fake_gatt_callbacks",
|
||||
":message_stream",
|
||||
"//fastpair/common",
|
||||
"//internal/platform:base",
|
||||
@@ -87,6 +88,7 @@ cc_library(
|
||||
"@com_google_absl//absl/container:flat_hash_map",
|
||||
"@com_google_absl//absl/status",
|
||||
"@com_google_absl//absl/status:statusor",
|
||||
"@com_google_absl//absl/strings",
|
||||
],
|
||||
)
|
||||
|
||||
|
||||
@@ -21,6 +21,7 @@
|
||||
#include "absl/container/flat_hash_map.h"
|
||||
#include "absl/status/status.h"
|
||||
#include "absl/status/statusor.h"
|
||||
#include "absl/strings/escaping.h"
|
||||
#include "internal/platform/ble_v2.h"
|
||||
#include "internal/platform/future.h"
|
||||
|
||||
@@ -43,14 +44,22 @@ class FakeGattCallbacks {
|
||||
// characteristic
|
||||
absl::StatusOr<std::string> read_value =
|
||||
absl::FailedPreconditionError("characteristic not set");
|
||||
absl::AnyInvocable<absl::Status(absl::string_view)> write_callback =
|
||||
[&](absl::string_view data) {
|
||||
write_value.Set(std::string(data));
|
||||
return write_result;
|
||||
};
|
||||
absl::AnyInvocable<absl::StatusOr<std::string>()> read_callback = [&]() {
|
||||
absl::AnyInvocable<absl::Status(absl::string_view)> write_callback;
|
||||
absl::AnyInvocable<absl::StatusOr<std::string>()> read_callback;
|
||||
|
||||
absl::Status WriteCallback(absl::string_view data) {
|
||||
if (write_callback) {
|
||||
return write_callback(data);
|
||||
}
|
||||
write_value.Set(std::string(data));
|
||||
return write_result;
|
||||
}
|
||||
absl::StatusOr<std::string> ReadCallback() {
|
||||
if (read_callback) {
|
||||
return read_callback();
|
||||
}
|
||||
return read_value;
|
||||
};
|
||||
}
|
||||
};
|
||||
|
||||
BleV2Medium::ServerGattConnectionCallback GetGattCallback() {
|
||||
@@ -65,7 +74,7 @@ class FakeGattCallbacks {
|
||||
callback(absl::NotFoundError("characteristic not found"));
|
||||
return;
|
||||
}
|
||||
callback(it->second.read_callback());
|
||||
callback(it->second.ReadCallback());
|
||||
},
|
||||
.on_characteristic_write_cb =
|
||||
[&](const api::ble_v2::BlePeripheral& remote_device,
|
||||
@@ -78,7 +87,7 @@ class FakeGattCallbacks {
|
||||
callback(absl::NotFoundError("characteristic not found"));
|
||||
return;
|
||||
}
|
||||
callback(it->second.write_callback(data));
|
||||
callback(it->second.WriteCallback(data));
|
||||
}};
|
||||
}
|
||||
|
||||
|
||||
@@ -18,7 +18,9 @@
|
||||
|
||||
#include "absl/status/status.h"
|
||||
#include "absl/strings/escaping.h"
|
||||
#include "absl/strings/numbers.h"
|
||||
#include "fastpair/common/constant.h"
|
||||
#include "internal/platform/medium_environment.h"
|
||||
#include <openssl/base.h>
|
||||
#include <openssl/bn.h>
|
||||
#include <openssl/ec_key.h>
|
||||
@@ -28,6 +30,10 @@ namespace fastpair {
|
||||
|
||||
namespace {
|
||||
|
||||
constexpr uint8_t kKeyBasedPairingResponseCode = 1;
|
||||
constexpr uint8_t kSeekerPasskeyResponseCode = 2;
|
||||
constexpr uint8_t kProviderPasskeyResponseCode = 3;
|
||||
|
||||
static EC_POINT *load_public_key(absl::string_view public_key) {
|
||||
CHECK_EQ(public_key.size(), kPublicKeyByteSize);
|
||||
BN_CTX *bn_ctx;
|
||||
@@ -129,22 +135,22 @@ void FakeProvider::LoadAntiSpoofingKey(absl::string_view private_key,
|
||||
}
|
||||
|
||||
std::string FakeProvider::DecryptKbpRequest(absl::string_view request) {
|
||||
NEARBY_LOGS(INFO) << "Encrypted KBP request "
|
||||
<< absl::BytesToHexString(request);
|
||||
NEARBY_LOGS(VERBOSE) << "Encrypted KBP request "
|
||||
<< absl::BytesToHexString(request);
|
||||
CHECK_EQ(request.size(), kEncryptedDataByteSize + kPublicKeyByteSize);
|
||||
absl::string_view encrypted = request.substr(0, kEncryptedDataByteSize);
|
||||
absl::string_view remote_public_key =
|
||||
request.substr(kEncryptedDataByteSize, kPublicKeyByteSize);
|
||||
std::string shared_secret = CreateSharedSecret(remote_public_key);
|
||||
std::string decrypted = Aes128Decrypt(encrypted, shared_secret);
|
||||
NEARBY_LOGS(INFO) << "Decrypted KBP request "
|
||||
<< absl::BytesToHexString(decrypted);
|
||||
account_key_ = shared_secret;
|
||||
NEARBY_LOGS(VERBOSE) << "Decrypted KBP request "
|
||||
<< absl::BytesToHexString(decrypted);
|
||||
shared_secret_ = shared_secret;
|
||||
return decrypted;
|
||||
}
|
||||
|
||||
std::string FakeProvider::Encrypt(absl::string_view data) {
|
||||
return Aes128Encrypt(data, account_key_);
|
||||
return Aes128Encrypt(data, shared_secret_);
|
||||
}
|
||||
|
||||
std::string FakeProvider::GenSec256r1Secret(
|
||||
@@ -199,9 +205,9 @@ std::string FakeProvider::CreateSharedSecret(
|
||||
Crypto::Sha256(secret).AsStringView().substr(0, kAccountKeySize));
|
||||
}
|
||||
|
||||
void FakeProvider::StartGattServer(
|
||||
BleV2Medium::ServerGattConnectionCallback callback) {
|
||||
gatt_server_ = ble_.StartGattServer(std::move(callback));
|
||||
void FakeProvider::StartGattServer(FakeGattCallbacks *fake_gatt_callbacks) {
|
||||
fake_gatt_callbacks_ = fake_gatt_callbacks;
|
||||
gatt_server_ = ble_.StartGattServer(fake_gatt_callbacks_->GetGattCallback());
|
||||
}
|
||||
|
||||
absl::Status FakeProvider::NotifyKeyBasedPairing(ByteArray response) {
|
||||
@@ -211,8 +217,16 @@ absl::Status FakeProvider::NotifyKeyBasedPairing(ByteArray response) {
|
||||
false, response);
|
||||
}
|
||||
|
||||
absl::Status FakeProvider::NotifyPasskey(ByteArray response) {
|
||||
CHECK_NE(gatt_server_, nullptr);
|
||||
CHECK(passkey_characteristic_.has_value());
|
||||
return gatt_server_->NotifyCharacteristicChanged(*passkey_characteristic_,
|
||||
false, response);
|
||||
}
|
||||
|
||||
void FakeProvider::StartDiscoverableAdvertisement(absl::string_view model_id) {
|
||||
advertising_ = true;
|
||||
model_id_ = model_id;
|
||||
ble_v1_.StartAdvertising(std::string(kServiceID),
|
||||
ByteArray(absl::HexStringToBytes(model_id)),
|
||||
std::string(kFastPairServiceUuid));
|
||||
@@ -225,5 +239,101 @@ void FakeProvider::StopAdvertising() {
|
||||
}
|
||||
}
|
||||
|
||||
void FakeProvider::SetKeyBasedPairingCallback() {
|
||||
CHECK_NE(fake_gatt_callbacks_, nullptr);
|
||||
CHECK(key_based_characteristic_.has_value());
|
||||
fake_gatt_callbacks_->characteristics_[*key_based_characteristic_]
|
||||
.write_callback = [this](absl::string_view request) {
|
||||
NEARBY_LOGS(VERBOSE) << "Encrypted request: "
|
||||
<< absl::BytesToHexString(request);
|
||||
std::string decrypted_request = DecryptKbpRequest(request);
|
||||
NEARBY_LOGS(VERBOSE) << "KBP decrypted request "
|
||||
<< absl::BytesToHexString(decrypted_request);
|
||||
fake_gatt_callbacks_->characteristics_[*key_based_characteristic_]
|
||||
.write_value.Set(std::string(decrypted_request));
|
||||
std::string response;
|
||||
response.push_back(kKeyBasedPairingResponseCode);
|
||||
response.append(GetMacAddressAsBytes());
|
||||
response.resize(kEncryptedDataByteSize, 0);
|
||||
absl::Status status = NotifyKeyBasedPairing(ByteArray(Encrypt(response)));
|
||||
NEARBY_LOGS(VERBOSE) << "KBP notify result: " << status;
|
||||
return absl::OkStatus();
|
||||
};
|
||||
}
|
||||
|
||||
void FakeProvider::SetPasskeyCallback() {
|
||||
CHECK_NE(fake_gatt_callbacks_, nullptr);
|
||||
CHECK(passkey_characteristic_.has_value());
|
||||
fake_gatt_callbacks_->characteristics_[*passkey_characteristic_]
|
||||
.write_callback = [this](absl::string_view request) {
|
||||
NEARBY_LOGS(VERBOSE) << "Passkey Encrypted request: "
|
||||
<< absl::BytesToHexString(request);
|
||||
std::string decrypted = Aes128Decrypt(request, shared_secret_);
|
||||
NEARBY_LOGS(VERBOSE) << "Passkey decrypted request "
|
||||
<< absl::BytesToHexString(decrypted);
|
||||
fake_gatt_callbacks_->characteristics_[*passkey_characteristic_]
|
||||
.write_value.Set(std::string(decrypted));
|
||||
if (decrypted[0] != kSeekerPasskeyResponseCode) {
|
||||
return absl::InvalidArgumentError(
|
||||
absl::StrFormat("Invalid passkey response code: 0x%x", decrypted[0]));
|
||||
}
|
||||
|
||||
std::string response;
|
||||
response.push_back(kProviderPasskeyResponseCode);
|
||||
response.push_back(pass_key_ >> 16);
|
||||
response.push_back(pass_key_ >> 8);
|
||||
response.push_back(pass_key_);
|
||||
response.resize(kEncryptedDataByteSize, 0);
|
||||
absl::Status status = NotifyPasskey(ByteArray(Encrypt(response)));
|
||||
NEARBY_LOGS(VERBOSE) << "Passkey notify result: " << status;
|
||||
return absl::OkStatus();
|
||||
};
|
||||
}
|
||||
|
||||
void FakeProvider::SetAccountkeyCallback() {
|
||||
CHECK_NE(fake_gatt_callbacks_, nullptr);
|
||||
CHECK(accountkey_characteristic_.has_value());
|
||||
fake_gatt_callbacks_->characteristics_[*accountkey_characteristic_]
|
||||
.write_callback = [this](absl::string_view request) {
|
||||
NEARBY_LOGS(VERBOSE) << "Account key encrypted request: "
|
||||
<< absl::BytesToHexString(request);
|
||||
std::string decrypted = Aes128Decrypt(request, shared_secret_);
|
||||
NEARBY_LOGS(VERBOSE) << "Account key decrypted request "
|
||||
<< absl::BytesToHexString(decrypted);
|
||||
fake_gatt_callbacks_->characteristics_[*accountkey_characteristic_]
|
||||
.write_value.Set(std::string(decrypted));
|
||||
|
||||
account_key_ = AccountKey(decrypted);
|
||||
return absl::OkStatus();
|
||||
};
|
||||
}
|
||||
|
||||
void FakeProvider::ConfigurePairingContext(absl::string_view pass_key) {
|
||||
api::PairingParams pairing_params;
|
||||
pairing_params.pairing_type =
|
||||
api::PairingParams::PairingType::kConfirmPasskey;
|
||||
pairing_params.passkey = pass_key;
|
||||
auto device = MediumEnvironment::Instance().FindBluetoothDevice(
|
||||
provider_medium_.GetMacAddress());
|
||||
CHECK_NE(device, nullptr);
|
||||
MediumEnvironment::Instance().ConfigBluetoothPairingContext(device,
|
||||
pairing_params);
|
||||
CHECK(absl::SimpleAtoi(pass_key, &pass_key_));
|
||||
}
|
||||
|
||||
void FakeProvider::PrepareForInitialPairing(
|
||||
PairingConfig config, FakeGattCallbacks *fake_gatt_callbacks) {
|
||||
LoadAntiSpoofingKey(config.private_key, config.public_key);
|
||||
StartGattServer(fake_gatt_callbacks);
|
||||
InsertCorrectGattCharacteristics();
|
||||
SetKeyBasedPairingCallback();
|
||||
SetPasskeyCallback();
|
||||
SetAccountkeyCallback();
|
||||
provider_adapter_.SetScanMode(
|
||||
BluetoothAdapter::ScanMode::kConnectableDiscoverable);
|
||||
ConfigurePairingContext(config.pass_key);
|
||||
StartDiscoverableAdvertisement(config.model_id);
|
||||
}
|
||||
|
||||
} // namespace fastpair
|
||||
} // namespace nearby
|
||||
|
||||
@@ -28,8 +28,10 @@
|
||||
#include "absl/strings/escaping.h"
|
||||
#include "absl/time/clock.h"
|
||||
#include "absl/time/time.h"
|
||||
#include "fastpair/common/account_key.h"
|
||||
#include "fastpair/common/constant.h"
|
||||
#include "fastpair/common/fast_pair_device.h"
|
||||
#include "fastpair/message_stream/fake_gatt_callbacks.h"
|
||||
#include "fastpair/message_stream/message.h"
|
||||
#include "internal/platform/ble.h"
|
||||
#include "internal/platform/ble_v2.h"
|
||||
@@ -71,8 +73,18 @@ class FakeProvider {
|
||||
public:
|
||||
using KeyBasedPairingCallback =
|
||||
absl::AnyInvocable<std::string(absl::string_view)>;
|
||||
struct PairingConfig {
|
||||
std::string private_key; // binary, private Anti-Spoofing Key
|
||||
std::string public_key; // binary, public Anti-Spoofing Key
|
||||
std::string model_id;
|
||||
std::string pass_key;
|
||||
};
|
||||
~FakeProvider() { Shutdown(); }
|
||||
|
||||
// Sets the fake provider up for initial pairing
|
||||
void PrepareForInitialPairing(PairingConfig config,
|
||||
FakeGattCallbacks* fake_gatt_callbacks);
|
||||
|
||||
void Shutdown() {
|
||||
StopAdvertising();
|
||||
provider_thread_.Shutdown();
|
||||
@@ -151,25 +163,31 @@ class FakeProvider {
|
||||
BluetoothUtils::FromString(provider_adapter_.GetMacAddress()));
|
||||
}
|
||||
|
||||
void StartGattServer(BleV2Medium::ServerGattConnectionCallback callback);
|
||||
void StartGattServer(FakeGattCallbacks* fake_gatt_callbacks);
|
||||
|
||||
void InsertCorrectGattCharacteristics() {
|
||||
CHECK_NE(fake_gatt_callbacks_, nullptr);
|
||||
|
||||
key_based_characteristic_ = gatt_server_->CreateCharacteristic(
|
||||
kFastPairServiceUuid, kKeyBasedCharacteristicUuidV2, permissions_,
|
||||
properties_);
|
||||
CHECK(key_based_characteristic_.has_value());
|
||||
fake_gatt_callbacks_->characteristics_[*key_based_characteristic_]
|
||||
.write_result = absl::OkStatus();
|
||||
|
||||
passkey_characteristic_ = gatt_server_->CreateCharacteristic(
|
||||
kFastPairServiceUuid, kPasskeyCharacteristicUuidV2, permissions_,
|
||||
properties_);
|
||||
|
||||
CHECK(passkey_characteristic_.has_value());
|
||||
fake_gatt_callbacks_->characteristics_[*passkey_characteristic_]
|
||||
.write_result = absl::OkStatus();
|
||||
|
||||
accountkey_characteristic_ = gatt_server_->CreateCharacteristic(
|
||||
kFastPairServiceUuid, kAccountKeyCharacteristicUuidV2, permissions_,
|
||||
properties_);
|
||||
|
||||
CHECK(accountkey_characteristic_.has_value());
|
||||
fake_gatt_callbacks_->characteristics_[*accountkey_characteristic_]
|
||||
.write_result = absl::OkStatus();
|
||||
}
|
||||
|
||||
void LoadAntiSpoofingKey(absl::string_view private_key,
|
||||
@@ -179,14 +197,20 @@ class FakeProvider {
|
||||
std::string Encrypt(absl::string_view data);
|
||||
|
||||
absl::Status NotifyKeyBasedPairing(ByteArray response);
|
||||
absl::Status NotifyPasskey(ByteArray response);
|
||||
|
||||
void StartDiscoverableAdvertisement(absl::string_view model_id);
|
||||
void StopAdvertising();
|
||||
void ConfigurePairingContext(absl::string_view pass_key);
|
||||
AccountKey& GetAccountKey() { return account_key_; }
|
||||
std::optional<GattCharacteristic> key_based_characteristic_;
|
||||
std::optional<GattCharacteristic> passkey_characteristic_;
|
||||
std::optional<GattCharacteristic> accountkey_characteristic_;
|
||||
|
||||
private:
|
||||
void SetKeyBasedPairingCallback();
|
||||
void SetPasskeyCallback();
|
||||
void SetAccountkeyCallback();
|
||||
std::string GenSec256r1Secret(absl::string_view remote_party_public_key);
|
||||
std::string CreateSharedSecret(absl::string_view remote_public_key);
|
||||
BluetoothAdapter provider_adapter_;
|
||||
@@ -201,8 +225,12 @@ class FakeProvider {
|
||||
Permission permissions_ = Permission::kWrite;
|
||||
std::unique_ptr<EVP_PKEY, void (*)(EVP_PKEY*)> anti_spoofing_key_{
|
||||
nullptr, EVP_PKEY_free};
|
||||
std::string account_key_;
|
||||
std::string shared_secret_;
|
||||
SingleThreadExecutor provider_thread_;
|
||||
std::string model_id_;
|
||||
FakeGattCallbacks* fake_gatt_callbacks_ = nullptr;
|
||||
unsigned int pass_key_;
|
||||
AccountKey account_key_;
|
||||
};
|
||||
|
||||
} // namespace fastpair
|
||||
|
||||
@@ -55,7 +55,7 @@ class RetroactiveTest : public testing::Test {
|
||||
|
||||
provider_.DiscoverProvider(seeker_medium);
|
||||
remote_device_ = seeker_medium.GetRemoteDevice(provider_.GetMacAddress());
|
||||
provider_.StartGattServer(gatt_callbacks_.GetGattCallback());
|
||||
provider_.StartGattServer(&gatt_callbacks_);
|
||||
provider_.InsertCorrectGattCharacteristics();
|
||||
ASSERT_TRUE(remote_device_.IsValid());
|
||||
}
|
||||
|
||||
@@ -46,11 +46,17 @@ void FakeFastPairRepository::GetDeviceMetadata(
|
||||
|
||||
std::unique_ptr<FakeFastPairRepository> FakeFastPairRepository::Create(
|
||||
absl::string_view model_id, absl::string_view public_anti_spoof_key) {
|
||||
std::string decoded_key;
|
||||
absl::Base64Unescape(public_anti_spoof_key, &decoded_key);
|
||||
proto::Device metadata;
|
||||
auto repository = std::make_unique<FakeFastPairRepository>();
|
||||
metadata.mutable_anti_spoofing_key_pair()->set_public_key(decoded_key);
|
||||
if (public_anti_spoof_key.length() == kPublicKeyByteSize) {
|
||||
metadata.mutable_anti_spoofing_key_pair()->set_public_key(
|
||||
public_anti_spoof_key);
|
||||
} else {
|
||||
std::string decoded_key;
|
||||
absl::Base64Unescape(public_anti_spoof_key, &decoded_key);
|
||||
CHECK_EQ(decoded_key.length(), kPublicKeyByteSize);
|
||||
metadata.mutable_anti_spoofing_key_pair()->set_public_key(decoded_key);
|
||||
}
|
||||
repository->SetFakeMetadata(model_id, metadata);
|
||||
return repository;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user