Commit b77a40fb authored by Ryan Hansberry's avatar Ryan Hansberry Committed by Commit Bot

Add IdentifyRemoteDeviceByAdvertisement method to BackgroundEidGenerator.

Also add a test double for BackgroundEidGenerator.

Bug: 819279
Change-Id: I24e2352d72deb00632a4d955f17cc508f7d4cbb5
Reviewed-on: https://chromium-review.googlesource.com/952462Reviewed-by: default avatarKyle Horimoto <khorimoto@chromium.org>
Commit-Queue: Ryan Hansberry <hansberry@chromium.org>
Cr-Commit-Position: refs/heads/master@{#545117}
parent fa58702a
......@@ -118,6 +118,8 @@ static_library("test_support") {
"device_to_device_responder_operations.h",
"fake_authenticator.cc",
"fake_authenticator.h",
"fake_background_eid_generator.cc",
"fake_background_eid_generator.h",
"fake_connection.cc",
"fake_connection.h",
"fake_cryptauth_device_manager.cc",
......
......@@ -13,6 +13,8 @@
#include "components/cryptauth/proto/cryptauth_api.pb.h"
#include "components/cryptauth/raw_eid_generator.h"
#include "components/cryptauth/raw_eid_generator_impl.h"
#include "components/cryptauth/remote_beacon_seed_fetcher.h"
#include "components/cryptauth/remote_device.h"
#include "components/proximity_auth/logging/logging.h"
namespace cryptauth {
......@@ -66,7 +68,6 @@ std::vector<DataWithTimestamp> BackgroundEidGenerator::GenerateNearestEids(
eids.push_back(*eid);
}
PA_LOG(INFO) << "Generated EIDs: " << DataWithTimestamp::ToDebugString(eids);
return eids;
}
......@@ -76,7 +77,7 @@ std::unique_ptr<DataWithTimestamp> BackgroundEidGenerator::GenerateEid(
const BeaconSeed* beacon_seed =
GetBeaconSeedForTimestamp(timestamp_ms, beacon_seeds);
if (!beacon_seed) {
PA_LOG(INFO) << " " << timestamp_ms << ": outside of BeaconSeed range.";
PA_LOG(WARNING) << " " << timestamp_ms << ": outside of BeaconSeed range.";
return nullptr;
}
......@@ -92,4 +93,40 @@ std::unique_ptr<DataWithTimestamp> BackgroundEidGenerator::GenerateEid(
start_of_period_ms + kEidPeriodMs);
}
std::string BackgroundEidGenerator::IdentifyRemoteDeviceByAdvertisement(
cryptauth::RemoteBeaconSeedFetcher* remote_beacon_seed_fetcher,
const std::string& advertisement_service_data,
const std::vector<std::string>& device_ids) const {
// Resize the service data to analyze only the first |kNumBytesInEidValue|
// bytes. If there are any bytes after those first |kNumBytesInEidValue|
// bytes, they are flags, so they are not needed to identify the device which
// sent a message.
std::string service_data_without_flags = advertisement_service_data;
service_data_without_flags.resize(RawEidGenerator::kNumBytesInEidValue);
const auto device_id_it = std::find_if(
device_ids.begin(), device_ids.end(),
[this, remote_beacon_seed_fetcher,
&service_data_without_flags](auto device_id) {
std::vector<BeaconSeed> beacon_seeds;
if (!remote_beacon_seed_fetcher->FetchSeedsForDeviceId(device_id,
&beacon_seeds)) {
PA_LOG(WARNING) << "Error fetching beacon seeds for device with ID "
<< RemoteDevice::TruncateDeviceIdForLogs(device_id);
return false;
}
std::vector<DataWithTimestamp> eids = GenerateNearestEids(beacon_seeds);
const auto eid_it = std::find_if(
eids.begin(), eids.end(), [&service_data_without_flags](auto eid) {
return eid.data == service_data_without_flags;
});
return eid_it != eids.end();
});
// Return empty string if no matching device is found.
return device_id_it != device_ids.end() ? *device_id_it : std::string();
}
} // cryptauth
......@@ -17,16 +17,22 @@ namespace cryptauth {
class BeaconSeed;
class RawEidGenerator;
class RemoteBeaconSeedFetcher;
// Generates ephemeral ID (EID) values that are broadcast for background BLE
// advertisements in the ProximityAuth protocol.
//
// Background BLE advertisements, because they're generally being advertised for
// extended periods of time, use a frequently rotating EID rotation scheme, for
// privacy reasons (EIDs should rotate more frequently to prevent others from
// tracking this device or user).
//
// When advertising in background mode, we offload advertising to the hardware
// in order to conserve battery. We assume, however, that the scanning side is
// not bound by battery constraints.
//
// For the inverse of this model, in which advertising is battery-sensitive, see
// ForegroundEidGenerator.
// For the inverse of this model, in which advertising is neither privacy- nor
// battery-sensitive, see ForegroundEidGenerator.
class BackgroundEidGenerator {
public:
BackgroundEidGenerator();
......@@ -37,6 +43,15 @@ class BackgroundEidGenerator {
virtual std::vector<DataWithTimestamp> GenerateNearestEids(
const std::vector<BeaconSeed>& beacon_seed) const;
// Given an incoming background advertisement with |service_data|, identifies
// which device (if any) sent the advertisement. Returns a device ID which
// identifies the device. If no device can be identified, returns an empty
// string.
virtual std::string IdentifyRemoteDeviceByAdvertisement(
cryptauth::RemoteBeaconSeedFetcher* remote_beacon_seed_fetcher,
const std::string& advertisement_service_data,
const std::vector<std::string>& device_ids) const;
private:
friend class CryptAuthBackgroundEidGeneratorTest;
BackgroundEidGenerator(std::unique_ptr<RawEidGenerator> raw_eid_generator,
......
......@@ -11,6 +11,7 @@
#include "base/strings/string_util.h"
#include "base/test/simple_test_clock.h"
#include "base/time/time.h"
#include "components/cryptauth/mock_remote_beacon_seed_fetcher.h"
#include "components/cryptauth/proto/cryptauth_api.pb.h"
#include "components/cryptauth/raw_eid_generator_impl.h"
#include "components/cryptauth/remote_device.h"
......@@ -37,6 +38,9 @@ const std::string kSecondSeed = "secondSeed";
const std::string kThirdSeed = "thirdSeed";
const std::string kFourthSeed = "fourthSeed";
const std::string kDeviceId1 = "deviceId1";
const std::string kDeviceId2 = "deviceId2";
BeaconSeed CreateBeaconSeed(const std::string& data,
const int64_t start_timestamp_ms,
const int64_t end_timestamp_ms) {
......@@ -47,15 +51,18 @@ BeaconSeed CreateBeaconSeed(const std::string& data,
return seed;
}
DataWithTimestamp CreateEid(const std::string& eid_seed,
int64_t start_of_period_timestamp_ms) {
std::string data =
eid_seed + "|" + std::to_string(start_of_period_timestamp_ms);
DataWithTimestamp CreateDataWithTimestamp(
const std::string& eid_seed,
int64_t start_of_period_timestamp_ms) {
std::unique_ptr<RawEidGenerator> raw_eid_generator =
std::make_unique<RawEidGeneratorImpl>();
std::string data = raw_eid_generator->GenerateEid(
eid_seed, start_of_period_timestamp_ms, nullptr /* extra_entropy */);
return DataWithTimestamp(data, start_of_period_timestamp_ms,
start_of_period_timestamp_ms + kEidPeriodMs);
}
class TestRawEidGenerator : public RawEidGenerator {
class TestRawEidGenerator : public RawEidGeneratorImpl {
public:
TestRawEidGenerator() {}
~TestRawEidGenerator() override {}
......@@ -65,7 +72,8 @@ class TestRawEidGenerator : public RawEidGenerator {
int64_t start_of_period_timestamp_ms,
std::string const* extra_entropy) override {
EXPECT_FALSE(extra_entropy);
return CreateEid(eid_seed, start_of_period_timestamp_ms).data;
return RawEidGeneratorImpl::GenerateEid(
eid_seed, start_of_period_timestamp_ms, extra_entropy);
}
private:
......@@ -92,6 +100,9 @@ class CryptAuthBackgroundEidGeneratorTest : public testing::Test {
void SetUp() override {
SetTestTime(kCurrentTimeMs);
mock_seed_fetcher_ =
std::make_unique<cryptauth::MockRemoteBeaconSeedFetcher>();
eid_generator_.reset(new BackgroundEidGenerator(
std::make_unique<TestRawEidGenerator>(), &test_clock_));
}
......@@ -103,11 +114,13 @@ class CryptAuthBackgroundEidGeneratorTest : public testing::Test {
}
std::unique_ptr<BackgroundEidGenerator> eid_generator_;
std::unique_ptr<MockRemoteBeaconSeedFetcher> mock_seed_fetcher_;
base::SimpleTestClock test_clock_;
std::vector<BeaconSeed> beacon_seeds_;
};
TEST_F(CryptAuthBackgroundEidGeneratorTest, BeaconSeedsExpired) {
TEST_F(CryptAuthBackgroundEidGeneratorTest,
GenerateNearestEids_BeaconSeedsExpired) {
SetTestTime(beacon_seeds_[beacon_seeds_.size() - 1].end_time_millis() +
kEidCount * kEidPeriodMs);
std::vector<DataWithTimestamp> eids =
......@@ -115,14 +128,16 @@ TEST_F(CryptAuthBackgroundEidGeneratorTest, BeaconSeedsExpired) {
EXPECT_EQ(0u, eids.size());
}
TEST_F(CryptAuthBackgroundEidGeneratorTest, BeaconSeedsValidInFuture) {
TEST_F(CryptAuthBackgroundEidGeneratorTest,
GenerateNearestEids_BeaconSeedsValidInFuture) {
SetTestTime(beacon_seeds_[0].start_time_millis() - kEidCount * kEidPeriodMs);
std::vector<DataWithTimestamp> eids =
eid_generator_->GenerateNearestEids(beacon_seeds_);
EXPECT_EQ(0u, eids.size());
}
TEST_F(CryptAuthBackgroundEidGeneratorTest, EidsUseSameBeaconSeed) {
TEST_F(CryptAuthBackgroundEidGeneratorTest,
GenerateNearestEids_EidsUseSameBeaconSeed) {
int64_t start_period_ms =
beacon_seeds_[0].start_time_millis() + kEidCount * kEidPeriodMs;
SetTestTime(start_period_ms + kEidPeriodMs / 2);
......@@ -132,14 +147,20 @@ TEST_F(CryptAuthBackgroundEidGeneratorTest, EidsUseSameBeaconSeed) {
std::string seed = beacon_seeds_[0].data();
EXPECT_EQ(kEidCount, eids.size());
EXPECT_EQ(CreateEid(seed, start_period_ms - 2 * kEidPeriodMs), eids[0]);
EXPECT_EQ(CreateEid(seed, start_period_ms - 1 * kEidPeriodMs), eids[1]);
EXPECT_EQ(CreateEid(seed, start_period_ms + 0 * kEidPeriodMs), eids[2]);
EXPECT_EQ(CreateEid(seed, start_period_ms + 1 * kEidPeriodMs), eids[3]);
EXPECT_EQ(CreateEid(seed, start_period_ms + 2 * kEidPeriodMs), eids[4]);
EXPECT_EQ(CreateDataWithTimestamp(seed, start_period_ms - 2 * kEidPeriodMs),
eids[0]);
EXPECT_EQ(CreateDataWithTimestamp(seed, start_period_ms - 1 * kEidPeriodMs),
eids[1]);
EXPECT_EQ(CreateDataWithTimestamp(seed, start_period_ms + 0 * kEidPeriodMs),
eids[2]);
EXPECT_EQ(CreateDataWithTimestamp(seed, start_period_ms + 1 * kEidPeriodMs),
eids[3]);
EXPECT_EQ(CreateDataWithTimestamp(seed, start_period_ms + 2 * kEidPeriodMs),
eids[4]);
}
TEST_F(CryptAuthBackgroundEidGeneratorTest, EidsAcrossBeaconSeeds) {
TEST_F(CryptAuthBackgroundEidGeneratorTest,
GenerateNearestEids_EidsAcrossBeaconSeeds) {
int64_t end_period_ms = beacon_seeds_[0].end_time_millis();
int64_t start_period_ms = beacon_seeds_[1].start_time_millis();
SetTestTime(start_period_ms + kEidPeriodMs / 2);
......@@ -150,14 +171,20 @@ TEST_F(CryptAuthBackgroundEidGeneratorTest, EidsAcrossBeaconSeeds) {
std::string seed0 = beacon_seeds_[0].data();
std::string seed1 = beacon_seeds_[1].data();
EXPECT_EQ(kEidCount, eids.size());
EXPECT_EQ(CreateEid(seed0, end_period_ms - 2 * kEidPeriodMs), eids[0]);
EXPECT_EQ(CreateEid(seed0, end_period_ms - 1 * kEidPeriodMs), eids[1]);
EXPECT_EQ(CreateEid(seed1, start_period_ms + 0 * kEidPeriodMs), eids[2]);
EXPECT_EQ(CreateEid(seed1, start_period_ms + 1 * kEidPeriodMs), eids[3]);
EXPECT_EQ(CreateEid(seed1, start_period_ms + 2 * kEidPeriodMs), eids[4]);
EXPECT_EQ(CreateDataWithTimestamp(seed0, end_period_ms - 2 * kEidPeriodMs),
eids[0]);
EXPECT_EQ(CreateDataWithTimestamp(seed0, end_period_ms - 1 * kEidPeriodMs),
eids[1]);
EXPECT_EQ(CreateDataWithTimestamp(seed1, start_period_ms + 0 * kEidPeriodMs),
eids[2]);
EXPECT_EQ(CreateDataWithTimestamp(seed1, start_period_ms + 1 * kEidPeriodMs),
eids[3]);
EXPECT_EQ(CreateDataWithTimestamp(seed1, start_period_ms + 2 * kEidPeriodMs),
eids[4]);
}
TEST_F(CryptAuthBackgroundEidGeneratorTest, CurrentTimeAtStartOfRange) {
TEST_F(CryptAuthBackgroundEidGeneratorTest,
GenerateNearestEids_CurrentTimeAtStartOfRange) {
int64_t start_period_ms = beacon_seeds_[0].start_time_millis();
SetTestTime(start_period_ms + kEidPeriodMs / 2);
......@@ -166,12 +193,16 @@ TEST_F(CryptAuthBackgroundEidGeneratorTest, CurrentTimeAtStartOfRange) {
std::string seed = beacon_seeds_[0].data();
EXPECT_EQ(3u, eids.size());
EXPECT_EQ(CreateEid(seed, start_period_ms + 0 * kEidPeriodMs), eids[0]);
EXPECT_EQ(CreateEid(seed, start_period_ms + 1 * kEidPeriodMs), eids[1]);
EXPECT_EQ(CreateEid(seed, start_period_ms + 2 * kEidPeriodMs), eids[2]);
EXPECT_EQ(CreateDataWithTimestamp(seed, start_period_ms + 0 * kEidPeriodMs),
eids[0]);
EXPECT_EQ(CreateDataWithTimestamp(seed, start_period_ms + 1 * kEidPeriodMs),
eids[1]);
EXPECT_EQ(CreateDataWithTimestamp(seed, start_period_ms + 2 * kEidPeriodMs),
eids[2]);
}
TEST_F(CryptAuthBackgroundEidGeneratorTest, CurrentTimeAtEndOfRange) {
TEST_F(CryptAuthBackgroundEidGeneratorTest,
GenerateNearestEids_CurrentTimeAtEndOfRange) {
int64_t start_period_ms = beacon_seeds_[3].end_time_millis() - kEidPeriodMs;
SetTestTime(start_period_ms + kEidPeriodMs / 2);
......@@ -180,9 +211,40 @@ TEST_F(CryptAuthBackgroundEidGeneratorTest, CurrentTimeAtEndOfRange) {
std::string seed = beacon_seeds_[3].data();
EXPECT_EQ(3u, eids.size());
EXPECT_EQ(CreateEid(seed, start_period_ms - 2 * kEidPeriodMs), eids[0]);
EXPECT_EQ(CreateEid(seed, start_period_ms - 1 * kEidPeriodMs), eids[1]);
EXPECT_EQ(CreateEid(seed, start_period_ms - 0 * kEidPeriodMs), eids[2]);
EXPECT_EQ(CreateDataWithTimestamp(seed, start_period_ms - 2 * kEidPeriodMs),
eids[0]);
EXPECT_EQ(CreateDataWithTimestamp(seed, start_period_ms - 1 * kEidPeriodMs),
eids[1]);
EXPECT_EQ(CreateDataWithTimestamp(seed, start_period_ms - 0 * kEidPeriodMs),
eids[2]);
}
// Test the case where the account has other devices, but their beacon seeds
// don't match the incoming advertisement. |beacon_seeds_[0]| corresponds to
// |kDeviceId1|. Since |kDeviceId1| is not present in the device ids passed to
// IdentifyRemoteDeviceByAdvertisement(), no match is expected to be found.
TEST_F(CryptAuthBackgroundEidGeneratorTest,
IdentifyRemoteDeviceByAdvertisement_NoMatchingRemoteDevices) {
SetTestTime(kStartPeriodMs + kEidPeriodMs / 2);
DataWithTimestamp advertisement_eid = CreateDataWithTimestamp(
beacon_seeds_[0].data(), kStartPeriodMs - kEidPeriodMs);
mock_seed_fetcher_->SetSeedsForDeviceId(kDeviceId1, &beacon_seeds_);
EXPECT_EQ(std::string(), eid_generator_->IdentifyRemoteDeviceByAdvertisement(
mock_seed_fetcher_.get(), advertisement_eid.data,
{kDeviceId2}));
}
TEST_F(CryptAuthBackgroundEidGeneratorTest,
IdentifyRemoteDeviceByAdvertisement_Success) {
SetTestTime(kStartPeriodMs + kEidPeriodMs / 2);
DataWithTimestamp advertisement_eid = CreateDataWithTimestamp(
beacon_seeds_[0].data(), kStartPeriodMs - kEidPeriodMs);
mock_seed_fetcher_->SetSeedsForDeviceId(kDeviceId1, &beacon_seeds_);
EXPECT_EQ(kDeviceId1, eid_generator_->IdentifyRemoteDeviceByAdvertisement(
mock_seed_fetcher_.get(), advertisement_eid.data,
{kDeviceId1, kDeviceId2}));
}
} // namespace cryptauth
// Copyright 2018 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "components/cryptauth/fake_background_eid_generator.h"
#include <memory>
namespace cryptauth {
FakeBackgroundEidGenerator::FakeBackgroundEidGenerator() = default;
FakeBackgroundEidGenerator::~FakeBackgroundEidGenerator() = default;
std::vector<DataWithTimestamp> FakeBackgroundEidGenerator::GenerateNearestEids(
const std::vector<BeaconSeed>& beacon_seed) const {
return *nearest_eids_;
}
std::string FakeBackgroundEidGenerator::IdentifyRemoteDeviceByAdvertisement(
cryptauth::RemoteBeaconSeedFetcher* remote_beacon_seed_fetcher,
const std::string& advertisement_service_data,
const std::vector<std::string>& device_ids) const {
// Increment num_identify_calls_. Since this overrides a const method, some
// hacking is needed to modify the num_identify_calls_ instance variable.
int* num_identify_calls_ptr = const_cast<int*>(&num_identify_calls_);
*num_identify_calls_ptr = *num_identify_calls_ptr + 1;
return identified_device_id_;
}
} // namespace cryptauth
\ No newline at end of file
// Copyright 2018 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef COMPONENTS_CRYPTAUTH_FAKE_BACKGROUND_EID_GENERATOR_H_
#define COMPONENTS_CRYPTAUTH_FAKE_BACKGROUND_EID_GENERATOR_H_
#include <memory>
#include <string>
#include <vector>
#include "components/cryptauth/background_eid_generator.h"
namespace cryptauth {
class BeaconSeed;
// Test double class for BackgroundEidGenerator.
class FakeBackgroundEidGenerator : public BackgroundEidGenerator {
public:
FakeBackgroundEidGenerator();
~FakeBackgroundEidGenerator() override;
// BackgroundEidGenerator:
std::vector<DataWithTimestamp> GenerateNearestEids(
const std::vector<BeaconSeed>& beacon_seed) const override;
std::string IdentifyRemoteDeviceByAdvertisement(
cryptauth::RemoteBeaconSeedFetcher* remote_beacon_seed_fetcher,
const std::string& advertisement_service_data,
const std::vector<std::string>& device_ids) const override;
void set_nearest_eids_(
std::unique_ptr<std::vector<DataWithTimestamp>> nearest_eids) {
nearest_eids_ = std::move(nearest_eids);
}
void set_identified_device_id(const std::string& identified_device_id) {
identified_device_id_ = identified_device_id;
}
int num_identify_calls() { return num_identify_calls_; }
private:
std::unique_ptr<std::vector<DataWithTimestamp>> nearest_eids_;
std::string identified_device_id_;
int num_identify_calls_ = 0;
};
} // namespace cryptauth
#endif // COMPONENTS_CRYPTAUTH_FAKE_BACKGROUND_EID_GENERATOR_H_
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment