mirror of
https://github.com/kidfromjupiter/nearby.git
synced 2026-09-14 14:46:12 -04:00
Implement FastPairDataEncryptor for Fast Pair Windows
PiperOrigin-RevId: 508492184
This commit is contained in:
committed by
Copybara-Service
parent
5cb25a1a70
commit
eaf46568a4
@@ -0,0 +1,71 @@
|
||||
# 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.
|
||||
|
||||
licenses(["notice"])
|
||||
|
||||
cc_library(
|
||||
name = "handshake",
|
||||
srcs = [
|
||||
"fast_pair_data_encryptor_impl.cc",
|
||||
],
|
||||
hdrs = [
|
||||
"fast_pair_data_encryptor.h",
|
||||
"fast_pair_data_encryptor_impl.h",
|
||||
],
|
||||
visibility = [
|
||||
"//:__subpackages__",
|
||||
"//fastpair:__subpackages__",
|
||||
],
|
||||
deps = [
|
||||
"//fastpair/common",
|
||||
"//fastpair/crypto",
|
||||
"//fastpair/dataparser",
|
||||
"//fastpair/repository",
|
||||
"//fastpair/server_access",
|
||||
"//internal/base:bluetooth_address",
|
||||
"//internal/platform:base",
|
||||
"//internal/platform:logging",
|
||||
"@boringssl//:crypto",
|
||||
"@com_google_absl//absl/functional:any_invocable",
|
||||
"@com_google_absl//absl/functional:bind_front",
|
||||
"@com_google_absl//absl/log:check",
|
||||
"@com_google_absl//absl/strings",
|
||||
"@com_google_absl//absl/types:optional",
|
||||
],
|
||||
)
|
||||
|
||||
cc_test(
|
||||
name = "fast_pair_data_encryptor_impl_test",
|
||||
size = "small",
|
||||
srcs = [
|
||||
"fast_pair_data_encryptor_impl_test.cc",
|
||||
],
|
||||
shard_count = 16,
|
||||
deps = [
|
||||
":handshake",
|
||||
"//fastpair/common",
|
||||
"//fastpair/crypto",
|
||||
"//fastpair/dataparser",
|
||||
"//fastpair/server_access:test_support",
|
||||
"//fastpair/testing",
|
||||
"//internal/platform:logging",
|
||||
"//internal/platform:types",
|
||||
"//internal/platform/implementation/g3", # build_cleaner: keep
|
||||
"@com_github_protobuf_matchers//protobuf-matchers",
|
||||
"@com_google_absl//absl/functional:bind_front",
|
||||
"@com_google_absl//absl/strings",
|
||||
"@com_google_absl//absl/time",
|
||||
"@com_google_googletest//:gtest_main",
|
||||
],
|
||||
)
|
||||
@@ -0,0 +1,63 @@
|
||||
// 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.
|
||||
|
||||
#ifndef THIRD_PARTY_NEARBY_FASTPAIR_HANDSHAKE_FAST_PAIR_DATA_ENCRYPTOR_H_
|
||||
#define THIRD_PARTY_NEARBY_FASTPAIR_HANDSHAKE_FAST_PAIR_DATA_ENCRYPTOR_H_
|
||||
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#include <array>
|
||||
#include <functional>
|
||||
#include <optional>
|
||||
#include <vector>
|
||||
|
||||
#include "absl/functional/any_invocable.h"
|
||||
#include "fastpair/common/constant.h"
|
||||
#include "fastpair/crypto/decrypted_passkey.h"
|
||||
#include "fastpair/crypto/decrypted_response.h"
|
||||
|
||||
namespace nearby {
|
||||
namespace fastpair {
|
||||
|
||||
// Holds a secret key for a device and has methods to encrypt bytes, decrypt
|
||||
// response and decrypt passkey.
|
||||
class FastPairDataEncryptor {
|
||||
public:
|
||||
// Encrypts bytes with the stored secret key.
|
||||
virtual std::array<uint8_t, kAesBlockByteSize> EncryptBytes(
|
||||
const std::array<uint8_t, kAesBlockByteSize>& bytes_to_encrypt) = 0;
|
||||
|
||||
// Return stored PublicKey
|
||||
virtual std::optional<std::array<uint8_t, 64>>& GetPublicKey() = 0;
|
||||
|
||||
// Decrypt and parse decrypted response bytes with the stored secret key.
|
||||
virtual void ParseDecryptResponse(
|
||||
const std::vector<uint8_t>& encrypted_response_bytes,
|
||||
absl::AnyInvocable<void(const std::optional<DecryptedResponse>)>
|
||||
callback) = 0;
|
||||
|
||||
// Decrypt and parse decrypted passkey bytes with the stored secret key.
|
||||
virtual void ParseDecryptPasskey(
|
||||
const std::vector<uint8_t>& encrypted_passkey_bytes,
|
||||
absl::AnyInvocable<void(const std::optional<DecryptedPasskey>)>
|
||||
callback) = 0;
|
||||
|
||||
virtual ~FastPairDataEncryptor() = default;
|
||||
};
|
||||
|
||||
} // namespace fastpair
|
||||
} // namespace nearby
|
||||
|
||||
#endif // THIRD_PARTY_NEARBY_FASTPAIR_HANDSHAKE_FAST_PAIR_DATA_ENCRYPTOR_H_
|
||||
@@ -0,0 +1,169 @@
|
||||
// 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 "fastpair/handshake/fast_pair_data_encryptor_impl.h"
|
||||
|
||||
#include <algorithm>
|
||||
#include <array>
|
||||
#include <cstddef>
|
||||
#include <cstdint>
|
||||
#include <functional>
|
||||
#include <iterator>
|
||||
#include <memory>
|
||||
#include <optional>
|
||||
#include <string_view>
|
||||
#include <utility>
|
||||
#include <vector>
|
||||
|
||||
#include "fastpair/common/constant.h"
|
||||
#include "fastpair/common/protocol.h"
|
||||
#include "fastpair/crypto/decrypted_passkey.h"
|
||||
#include "fastpair/crypto/decrypted_response.h"
|
||||
#include "fastpair/crypto/fast_pair_encryption.h"
|
||||
#include "fastpair/crypto/fast_pair_key_pair.h"
|
||||
#include "fastpair/dataparser/fast_pair_data_parser.h"
|
||||
#include "fastpair/handshake/fast_pair_data_encryptor.h"
|
||||
#include "fastpair/repository/device_metadata.h"
|
||||
#include "fastpair/server_access/fast_pair_repository.h"
|
||||
#include "internal/platform/logging.h"
|
||||
|
||||
namespace nearby {
|
||||
namespace fastpair {
|
||||
|
||||
namespace {
|
||||
FastPairDataEncryptorImpl::Factory* g_test_factory_ = nullptr;
|
||||
|
||||
bool ValidateInputSize(const std::vector<uint8_t>& encrypted_bytes) {
|
||||
if (encrypted_bytes.size() != kAesBlockByteSize) {
|
||||
NEARBY_LOGS(VERBOSE) << __func__ << ": Encrypted bytes should have size = "
|
||||
<< kAesBlockByteSize
|
||||
<< ", actual = " << encrypted_bytes.size();
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
// FastPairDataEncryptorImpl::Factory
|
||||
void FastPairDataEncryptorImpl::Factory::SetFactoryForTesting(
|
||||
Factory* g_test_factory) {
|
||||
g_test_factory_ = g_test_factory;
|
||||
}
|
||||
|
||||
FastPairDataEncryptorImpl::Factory::~Factory() = default;
|
||||
|
||||
void FastPairDataEncryptorImpl::Factory::CreateAsync(
|
||||
const FastPairDevice& device,
|
||||
absl::AnyInvocable<void(std::unique_ptr<FastPairDataEncryptor>)>
|
||||
on_get_instance_callback) {
|
||||
if (g_test_factory_) {
|
||||
g_test_factory_->CreateInstance(device,
|
||||
std::move(on_get_instance_callback));
|
||||
return;
|
||||
}
|
||||
|
||||
if (device.protocol == Protocol::kFastPairInitialPairing) {
|
||||
CreateAsyncWithKeyExchange(device, std::move(on_get_instance_callback));
|
||||
}
|
||||
}
|
||||
|
||||
void FastPairDataEncryptorImpl::Factory::CreateAsyncWithKeyExchange(
|
||||
const FastPairDevice& device,
|
||||
absl::AnyInvocable<void(std::unique_ptr<FastPairDataEncryptor>)>
|
||||
on_get_instance_callback) {
|
||||
// We first have to get the metadata in order to get the public key to use
|
||||
// to generate the new secret key pair.
|
||||
FastPairRepository::Get()->GetDeviceMetadata(
|
||||
device.model_id,
|
||||
[&device, &on_get_instance_callback](DeviceMetadata& metadata) {
|
||||
FastPairDataEncryptorImpl::Factory::DeviceMetadataRetrieved(
|
||||
device, std::move(on_get_instance_callback), metadata);
|
||||
});
|
||||
}
|
||||
|
||||
void FastPairDataEncryptorImpl::Factory::DeviceMetadataRetrieved(
|
||||
const FastPairDevice& device,
|
||||
absl::AnyInvocable<void(std::unique_ptr<FastPairDataEncryptor>)>
|
||||
on_get_instance_callback,
|
||||
DeviceMetadata& device_metadata) {
|
||||
std::optional<KeyPair> key_pair =
|
||||
FastPairEncryption::GenerateKeysWithEcdhKeyAgreement(
|
||||
device_metadata.GetDetails().anti_spoofing_key_pair().public_key());
|
||||
if (!key_pair.has_value()) {
|
||||
NEARBY_LOGS(INFO) << "Fail to generate key pair";
|
||||
on_get_instance_callback(nullptr);
|
||||
return;
|
||||
}
|
||||
|
||||
std::unique_ptr<FastPairDataEncryptor> data_encryptor =
|
||||
std::make_unique<FastPairDataEncryptorImpl>(key_pair.value());
|
||||
on_get_instance_callback(std::move(data_encryptor));
|
||||
}
|
||||
|
||||
// FastPairDataEncryptorImpl
|
||||
FastPairDataEncryptorImpl::FastPairDataEncryptorImpl(const KeyPair& key_pair)
|
||||
: shared_secret_key_(key_pair.shared_secret_key),
|
||||
public_key_(key_pair.public_key) {}
|
||||
|
||||
FastPairDataEncryptorImpl::FastPairDataEncryptorImpl(
|
||||
const std::array<uint8_t, kSharedSecretKeyByteSize>& shared_secret_key)
|
||||
: shared_secret_key_(shared_secret_key) {}
|
||||
|
||||
FastPairDataEncryptorImpl::~FastPairDataEncryptorImpl() = default;
|
||||
|
||||
std::array<uint8_t, kAesBlockByteSize> FastPairDataEncryptorImpl::EncryptBytes(
|
||||
const std::array<uint8_t, kAesBlockByteSize>& bytes_to_encrypt) {
|
||||
return FastPairEncryption::EncryptBytes(shared_secret_key_, bytes_to_encrypt);
|
||||
}
|
||||
|
||||
std::optional<std::array<uint8_t, kPublicKeyByteSize>>&
|
||||
FastPairDataEncryptorImpl::GetPublicKey() {
|
||||
return public_key_;
|
||||
}
|
||||
|
||||
void FastPairDataEncryptorImpl::ParseDecryptResponse(
|
||||
const std::vector<uint8_t>& encrypted_response_bytes,
|
||||
absl::AnyInvocable<void(const std::optional<DecryptedResponse>)> callback) {
|
||||
if (!ValidateInputSize(encrypted_response_bytes)) {
|
||||
callback(std::nullopt);
|
||||
return;
|
||||
}
|
||||
|
||||
FastPairDataParser::ParseDecryptedResponse(
|
||||
std::vector<uint8_t>(shared_secret_key_.begin(),
|
||||
shared_secret_key_.end()),
|
||||
encrypted_response_bytes,
|
||||
{
|
||||
.on_decrypted_cb = std::move(callback),
|
||||
});
|
||||
}
|
||||
|
||||
void FastPairDataEncryptorImpl::ParseDecryptPasskey(
|
||||
const std::vector<uint8_t>& encrypted_passkey_bytes,
|
||||
absl::AnyInvocable<void(const std::optional<DecryptedPasskey>)> callback) {
|
||||
if (!ValidateInputSize(encrypted_passkey_bytes)) {
|
||||
callback(std::nullopt);
|
||||
return;
|
||||
}
|
||||
FastPairDataParser::ParseDecryptedPasskey(
|
||||
std::vector<uint8_t>(shared_secret_key_.begin(),
|
||||
shared_secret_key_.end()),
|
||||
encrypted_passkey_bytes,
|
||||
{
|
||||
.on_decrypted_cb = std::move(callback),
|
||||
});
|
||||
}
|
||||
} // namespace fastpair
|
||||
} // namespace nearby
|
||||
@@ -0,0 +1,104 @@
|
||||
// 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.
|
||||
|
||||
#ifndef THIRD_PARTY_NEARBY_FASTPAIR_HANDSHAKE_FAST_PAIR_DATA_ENCRYPTOR_IMPL_H_
|
||||
#define THIRD_PARTY_NEARBY_FASTPAIR_HANDSHAKE_FAST_PAIR_DATA_ENCRYPTOR_IMPL_H_
|
||||
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#include <array>
|
||||
#include <functional>
|
||||
#include <memory>
|
||||
#include <optional>
|
||||
#include <vector>
|
||||
|
||||
#include "absl/functional/any_invocable.h"
|
||||
#include "fastpair/common/constant.h"
|
||||
#include "fastpair/common/fast_pair_device.h"
|
||||
#include "fastpair/crypto/fast_pair_key_pair.h"
|
||||
#include "fastpair/handshake/fast_pair_data_encryptor.h"
|
||||
#include "fastpair/repository/device_metadata.h"
|
||||
|
||||
namespace nearby {
|
||||
namespace fastpair {
|
||||
|
||||
// Holds a secret key for a device and has methods to encrypt bytes, decrypt
|
||||
// response and decrypt passkey.
|
||||
class FastPairDataEncryptorImpl : public FastPairDataEncryptor {
|
||||
public:
|
||||
class Factory {
|
||||
public:
|
||||
static void CreateAsync(
|
||||
const FastPairDevice& device,
|
||||
absl::AnyInvocable<void(std::unique_ptr<FastPairDataEncryptor>)>
|
||||
on_get_instance_callback);
|
||||
|
||||
static void SetFactoryForTesting(Factory* test_factory);
|
||||
|
||||
protected:
|
||||
virtual ~Factory();
|
||||
|
||||
virtual void CreateInstance(
|
||||
const FastPairDevice& device,
|
||||
absl::AnyInvocable<void(std::unique_ptr<FastPairDataEncryptor>)>
|
||||
on_get_instance_callback) = 0;
|
||||
|
||||
private:
|
||||
static void CreateAsyncWithKeyExchange(
|
||||
const FastPairDevice& device,
|
||||
absl::AnyInvocable<void(std::unique_ptr<FastPairDataEncryptor>)>
|
||||
on_get_instance_callback);
|
||||
|
||||
static void DeviceMetadataRetrieved(
|
||||
const FastPairDevice& device,
|
||||
absl::AnyInvocable<void(std::unique_ptr<FastPairDataEncryptor>)>
|
||||
on_get_instance_callback,
|
||||
DeviceMetadata& device_metadata);
|
||||
};
|
||||
|
||||
std::array<uint8_t, kAesBlockByteSize> EncryptBytes(
|
||||
const std::array<uint8_t, kAesBlockByteSize>& bytes_to_encrypt) override;
|
||||
|
||||
std::optional<std::array<uint8_t, kPublicKeyByteSize>>& GetPublicKey()
|
||||
override;
|
||||
|
||||
void ParseDecryptResponse(
|
||||
const std::vector<uint8_t>& encrypted_response_bytes,
|
||||
absl::AnyInvocable<void(const std::optional<DecryptedResponse>)> callback)
|
||||
override;
|
||||
|
||||
void ParseDecryptPasskey(
|
||||
const std::vector<uint8_t>& encrypted_passkey_bytes,
|
||||
absl::AnyInvocable<void(const std::optional<DecryptedPasskey>)> callback)
|
||||
override;
|
||||
|
||||
explicit FastPairDataEncryptorImpl(const KeyPair& key_pair);
|
||||
explicit FastPairDataEncryptorImpl(
|
||||
const std::array<uint8_t, kSharedSecretKeyByteSize>& secret_key);
|
||||
~FastPairDataEncryptorImpl() override;
|
||||
|
||||
private:
|
||||
const std::array<uint8_t, kSharedSecretKeyByteSize> shared_secret_key_;
|
||||
|
||||
// The public key is only required during initial pairing and optional during
|
||||
// communication with paired devices.
|
||||
std::optional<std::array<uint8_t, kPublicKeyByteSize>> public_key_ =
|
||||
std::nullopt;
|
||||
};
|
||||
|
||||
} // namespace fastpair
|
||||
} // namespace nearby
|
||||
|
||||
#endif // THIRD_PARTY_NEARBY_FASTPAIR_HANDSHAKE_FAST_PAIR_DATA_ENCRYPTOR_IMPL_H_
|
||||
@@ -0,0 +1,243 @@
|
||||
// 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 "fastpair/handshake/fast_pair_data_encryptor_impl.h"
|
||||
|
||||
#include <array>
|
||||
#include <memory>
|
||||
#include <optional>
|
||||
#include <string>
|
||||
#include <utility>
|
||||
#include <vector>
|
||||
|
||||
#include "gmock/gmock.h"
|
||||
#include "protobuf-matchers/protocol-buffer-matchers.h"
|
||||
#include "gtest/gtest.h"
|
||||
#include "absl/functional/bind_front.h"
|
||||
#include "absl/strings/escaping.h"
|
||||
#include "absl/time/time.h"
|
||||
#include "fastpair/common/constant.h"
|
||||
#include "fastpair/common/protocol.h"
|
||||
#include "fastpair/crypto/fast_pair_message_type.h"
|
||||
#include "fastpair/dataparser/fast_pair_data_parser.h"
|
||||
#include "fastpair/server_access/fake_fast_pair_repository.h"
|
||||
|
||||
namespace nearby {
|
||||
namespace fastpair {
|
||||
namespace {
|
||||
constexpr std::array<uint8_t, kAesBlockByteSize> kResponseBytes = {
|
||||
0x01, 0x5E, 0x3F, 0x45, 0x61, 0xC3, 0x32, 0x1D,
|
||||
0xA0, 0xBA, 0xF0, 0xBB, 0x95, 0x1F, 0xF7, 0xB6};
|
||||
|
||||
constexpr std::array<uint8_t, kAesBlockByteSize> kPasskeyBytes = {
|
||||
0x02, 0x5E, 0x3F, 0x45, 0x61, 0xC3, 0x32, 0x1D,
|
||||
0xA0, 0xBA, 0xF0, 0xBB, 0x95, 0x1F, 0xF7, 0xB6};
|
||||
|
||||
constexpr char kPublicAntiSpoof[] =
|
||||
"Wuyr48lD3txnUhGiMF1IfzlTwRxxe+wMB1HLzP+"
|
||||
"0wVcljfT3XPoiy1fntlneziyLD5knDVAJSE+RM/zlPRP/Jg==";
|
||||
constexpr char kInvalidPublicAntiSpoof[] = "InvalidPublicAntiSpoof";
|
||||
|
||||
constexpr char kValidModelId[] = "718c17";
|
||||
constexpr char kTestAddress[] = "test_address";
|
||||
|
||||
class FastPairDataEncryptorImplTest : public testing::Test {
|
||||
public:
|
||||
void TearDown() override { data_encryptor_.reset(); }
|
||||
|
||||
void FailedSetUpNoMetadata() {
|
||||
repository_ = std::make_unique<FakeFastPairRepository>();
|
||||
FastPairDevice device(kValidModelId, kTestAddress,
|
||||
Protocol::kFastPairInitialPairing);
|
||||
FastPairDataEncryptorImpl::Factory::CreateAsync(
|
||||
device,
|
||||
absl::bind_front(
|
||||
&FastPairDataEncryptorImplTest::OnDataEncryptorCreateAsync, this));
|
||||
}
|
||||
|
||||
void FailedSetUpNoKeyPair() {
|
||||
repository_ = std::make_unique<FakeFastPairRepository>();
|
||||
proto::Device metadata;
|
||||
std::string decoded_key;
|
||||
absl::Base64Unescape(kInvalidPublicAntiSpoof, &decoded_key);
|
||||
metadata.mutable_anti_spoofing_key_pair()->set_public_key(decoded_key);
|
||||
repository_->SetFakeMetadata(kValidModelId, metadata);
|
||||
FastPairDevice device(kValidModelId, kTestAddress,
|
||||
Protocol::kFastPairInitialPairing);
|
||||
FastPairDataEncryptorImpl::Factory::CreateAsync(
|
||||
device,
|
||||
absl::bind_front(
|
||||
&FastPairDataEncryptorImplTest::OnDataEncryptorCreateAsync, this));
|
||||
}
|
||||
|
||||
void SuccessfulSetUp() {
|
||||
repository_ = std::make_unique<FakeFastPairRepository>();
|
||||
proto::Device metadata;
|
||||
std::string decoded_key;
|
||||
absl::Base64Unescape(kPublicAntiSpoof, &decoded_key);
|
||||
metadata.mutable_anti_spoofing_key_pair()->set_public_key(decoded_key);
|
||||
repository_->SetFakeMetadata(kValidModelId, metadata);
|
||||
FastPairDevice device(kValidModelId, kTestAddress,
|
||||
Protocol::kFastPairInitialPairing);
|
||||
FastPairDataEncryptorImpl::Factory::CreateAsync(
|
||||
device,
|
||||
absl::bind_front(
|
||||
&FastPairDataEncryptorImplTest::OnDataEncryptorCreateAsync, this));
|
||||
}
|
||||
|
||||
void OnDataEncryptorCreateAsync(
|
||||
std::unique_ptr<FastPairDataEncryptor> fast_pair_data_encryptor) {
|
||||
data_encryptor_ = std::move(fast_pair_data_encryptor);
|
||||
}
|
||||
|
||||
std::array<uint8_t, kAesBlockByteSize> EncryptBytes() {
|
||||
return data_encryptor_->EncryptBytes(kResponseBytes);
|
||||
}
|
||||
|
||||
void ParseDecryptedResponse() {
|
||||
const std::array<uint8_t, kAesBlockByteSize> bytes =
|
||||
data_encryptor_->EncryptBytes(kResponseBytes);
|
||||
|
||||
data_encryptor_->ParseDecryptResponse(
|
||||
std::vector<uint8_t>(bytes.begin(), bytes.end()),
|
||||
absl::bind_front(
|
||||
&FastPairDataEncryptorImplTest::ParseDecryptedResponseCallback,
|
||||
this));
|
||||
}
|
||||
|
||||
void ParseDecryptedResponseInvalidBytes() {
|
||||
const std::array<uint8_t, kAesBlockByteSize> bytes =
|
||||
data_encryptor_->EncryptBytes(kResponseBytes);
|
||||
|
||||
data_encryptor_->ParseDecryptResponse(
|
||||
std::vector<uint8_t>(bytes.begin() + 3, bytes.end()),
|
||||
absl::bind_front(
|
||||
&FastPairDataEncryptorImplTest::ParseDecryptedResponseCallback,
|
||||
this));
|
||||
}
|
||||
|
||||
void ParseDecryptedResponseCallback(
|
||||
const std::optional<DecryptedResponse>& response) {
|
||||
response_ = response;
|
||||
}
|
||||
|
||||
void ParseDecryptedPasskey() {
|
||||
const std::array<uint8_t, kAesBlockByteSize> bytes =
|
||||
data_encryptor_->EncryptBytes(kPasskeyBytes);
|
||||
|
||||
data_encryptor_->ParseDecryptPasskey(
|
||||
std::vector<uint8_t>(bytes.begin(), bytes.end()),
|
||||
absl::bind_front(
|
||||
&FastPairDataEncryptorImplTest::ParseDecryptPasskeyCallback, this));
|
||||
}
|
||||
|
||||
void ParseDecryptedPasskeyInvalidBytes() {
|
||||
const std::array<uint8_t, kAesBlockByteSize> bytes =
|
||||
data_encryptor_->EncryptBytes(kPasskeyBytes);
|
||||
|
||||
data_encryptor_->ParseDecryptPasskey(
|
||||
std::vector<uint8_t>(bytes.begin() + 3, bytes.end()),
|
||||
absl::bind_front(
|
||||
&FastPairDataEncryptorImplTest::ParseDecryptPasskeyCallback, this));
|
||||
}
|
||||
|
||||
void ParseDecryptPasskeyCallback(
|
||||
const std::optional<DecryptedPasskey>& passkey) {
|
||||
passkey_ = passkey;
|
||||
}
|
||||
|
||||
protected:
|
||||
std::unique_ptr<FastPairDataEncryptor> data_encryptor_;
|
||||
std::optional<DecryptedResponse> response_ = std::nullopt;
|
||||
std::optional<DecryptedPasskey> passkey_ = std::nullopt;
|
||||
std::unique_ptr<FastPairDataParser> data_parser_;
|
||||
|
||||
private:
|
||||
std::unique_ptr<FastPairDevice> device_;
|
||||
std::unique_ptr<FakeFastPairRepository> repository_;
|
||||
};
|
||||
|
||||
TEST_F(FastPairDataEncryptorImplTest, FailedSetUpNoMetadata) {
|
||||
EXPECT_FALSE(data_encryptor_);
|
||||
FailedSetUpNoMetadata();
|
||||
EXPECT_FALSE(data_encryptor_);
|
||||
}
|
||||
|
||||
TEST_F(FastPairDataEncryptorImplTest, NoKeyPair) {
|
||||
FailedSetUpNoKeyPair();
|
||||
EXPECT_FALSE(data_encryptor_);
|
||||
}
|
||||
|
||||
TEST_F(FastPairDataEncryptorImplTest, SuccessfulSetUp) {
|
||||
EXPECT_FALSE(data_encryptor_);
|
||||
SuccessfulSetUp();
|
||||
EXPECT_TRUE(data_encryptor_);
|
||||
}
|
||||
|
||||
TEST_F(FastPairDataEncryptorImplTest, GetPublicKey) {
|
||||
SuccessfulSetUp();
|
||||
EXPECT_TRUE(data_encryptor_);
|
||||
ParseDecryptedPasskey();
|
||||
EXPECT_NE(data_encryptor_->GetPublicKey(), std::nullopt);
|
||||
}
|
||||
|
||||
TEST_F(FastPairDataEncryptorImplTest, EncryptBytes) {
|
||||
SuccessfulSetUp();
|
||||
EXPECT_TRUE(data_encryptor_);
|
||||
EXPECT_FALSE(EncryptBytes().empty());
|
||||
}
|
||||
|
||||
TEST_F(FastPairDataEncryptorImplTest, ParseDecryptedResponse) {
|
||||
SuccessfulSetUp();
|
||||
EXPECT_TRUE(data_encryptor_);
|
||||
ParseDecryptedResponse();
|
||||
EXPECT_TRUE(response_);
|
||||
const std::array<uint8_t, kDecryptedResponseAddressByteSize> kAddressBytes = {
|
||||
0x5E, 0x3F, 0x45, 0x61, 0xC3, 0x32};
|
||||
EXPECT_EQ(response_->address_bytes, kAddressBytes);
|
||||
EXPECT_EQ(response_->message_type,
|
||||
FastPairMessageType::kKeyBasedPairingResponse);
|
||||
}
|
||||
|
||||
TEST_F(FastPairDataEncryptorImplTest, ParseDecryptedResponse_InvalidInputSize) {
|
||||
SuccessfulSetUp();
|
||||
EXPECT_TRUE(data_encryptor_);
|
||||
ParseDecryptedResponseInvalidBytes();
|
||||
EXPECT_FALSE(response_);
|
||||
}
|
||||
|
||||
TEST_F(FastPairDataEncryptorImplTest, ParseDecryptedPasskey) {
|
||||
SuccessfulSetUp();
|
||||
EXPECT_TRUE(data_encryptor_);
|
||||
ParseDecryptedPasskey();
|
||||
EXPECT_TRUE(passkey_);
|
||||
// Passkey bytes.
|
||||
std::array<uint8_t, 3> passkey_bytes = {0x5E, 0x3F, 0x45};
|
||||
uint32_t passkey = passkey_bytes[2];
|
||||
passkey += passkey_bytes[1] << 8;
|
||||
passkey += passkey_bytes[0] << 16;
|
||||
|
||||
EXPECT_EQ(passkey_->passkey, passkey);
|
||||
EXPECT_EQ(passkey_->message_type, FastPairMessageType::kSeekersPasskey);
|
||||
}
|
||||
|
||||
TEST_F(FastPairDataEncryptorImplTest, ParseDecryptedPasskey_InvalidInputSize) {
|
||||
SuccessfulSetUp();
|
||||
EXPECT_TRUE(data_encryptor_);
|
||||
ParseDecryptedPasskeyInvalidBytes();
|
||||
EXPECT_FALSE(passkey_);
|
||||
}
|
||||
} // namespace
|
||||
} // namespace fastpair
|
||||
} // namespace nearby
|
||||
Reference in New Issue
Block a user