diff --git a/fastpair/handshake/fast_pair_data_encryptor_impl.cc b/fastpair/handshake/fast_pair_data_encryptor_impl.cc index 09d107d9..1cac8f12 100644 --- a/fastpair/handshake/fast_pair_data_encryptor_impl.cc +++ b/fastpair/handshake/fast_pair_data_encryptor_impl.cc @@ -26,6 +26,8 @@ #include #include +#include "absl/strings/string_view.h" +#include "fastpair/common/account_key.h" #include "fastpair/common/constant.h" #include "fastpair/common/protocol.h" #include "fastpair/crypto/decrypted_passkey.h" @@ -78,9 +80,7 @@ void FastPairDataEncryptorImpl::Factory::CreateAsync( device.GetProtocol() == Protocol::kFastPairRetroactivePairing) { CreateAsyncWithKeyExchange(device, std::move(on_get_instance_callback)); } else { - NEARBY_LOGS(INFO) << __func__ - << ": Can't create FP encryptor. Invalid protocol."; - on_get_instance_callback(nullptr); + CreateAsyncWithAccountKey(device, std::move(on_get_instance_callback)); } } @@ -104,19 +104,36 @@ void FastPairDataEncryptorImpl::Factory::DeviceMetadataRetrieved( absl::AnyInvocable)> on_get_instance_callback, DeviceMetadata& device_metadata) { + NEARBY_LOGS(INFO) << __func__; DCHECK(&device_metadata); std::optional 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); + std::move(on_get_instance_callback)(nullptr); return; } - std::unique_ptr data_encryptor = + auto data_encryptor = std::make_unique(key_pair.value()); - on_get_instance_callback(std::move(data_encryptor)); + std::move(on_get_instance_callback)(std::move(data_encryptor)); +} + +void FastPairDataEncryptorImpl::Factory::CreateAsyncWithAccountKey( + const FastPairDevice& device, + absl::AnyInvocable)> + on_get_instance_callback) { + NEARBY_LOGS(INFO) << __func__; + absl::string_view account_key = device.GetAccountKey().GetAsBytes(); + CHECK_EQ(account_key.size(), static_cast(kSharedSecretKeyByteSize)); + std::array shared_secret_key; + std::copy_n(account_key.begin(), kSharedSecretKeyByteSize, + shared_secret_key.begin()); + + std::move(on_get_instance_callback)( + std::make_unique( + std::move(shared_secret_key))); } // FastPairDataEncryptorImpl diff --git a/fastpair/handshake/fast_pair_data_encryptor_impl.h b/fastpair/handshake/fast_pair_data_encryptor_impl.h index de567900..64db1bd5 100644 --- a/fastpair/handshake/fast_pair_data_encryptor_impl.h +++ b/fastpair/handshake/fast_pair_data_encryptor_impl.h @@ -64,6 +64,11 @@ class FastPairDataEncryptorImpl : public FastPairDataEncryptor { absl::AnyInvocable)> on_get_instance_callback, DeviceMetadata& device_metadata); + + static void CreateAsyncWithAccountKey( + const FastPairDevice& device, + absl::AnyInvocable)> + on_get_instance_callback); }; std::array EncryptBytes( diff --git a/fastpair/handshake/fast_pair_data_encryptor_impl_test.cc b/fastpair/handshake/fast_pair_data_encryptor_impl_test.cc index 0137c776..854c8b84 100644 --- a/fastpair/handshake/fast_pair_data_encryptor_impl_test.cc +++ b/fastpair/handshake/fast_pair_data_encryptor_impl_test.cc @@ -24,9 +24,12 @@ #include "gtest/gtest.h" #include "absl/functional/bind_front.h" #include "absl/strings/escaping.h" +#include "fastpair/common/account_key.h" #include "fastpair/common/constant.h" #include "fastpair/common/protocol.h" +#include "fastpair/crypto/fast_pair_encryption.h" #include "fastpair/dataparser/fast_pair_data_parser.h" +#include "fastpair/handshake/fast_pair_data_encryptor.h" #include "fastpair/server_access/fake_fast_pair_repository.h" #include "internal/platform/count_down_latch.h" @@ -54,7 +57,7 @@ class FastPairDataEncryptorImplTest : public testing::Test { public: void TearDown() override { data_encryptor_.reset(); } - void FailedSetUpNoMetadata() { + void FailedSetUpRepositoryWithNoDeviceMetadata() { CountDownLatch latch(1); repository_ = std::make_unique(); FastPairDevice device(kValidModelId, kTestAddress, @@ -66,7 +69,7 @@ class FastPairDataEncryptorImplTest : public testing::Test { EXPECT_FALSE(latch.Await(kWaitTimeout).GetResult()); } - void FailedSetUpNoKeyPair() { + void FailedSetUpRepositoryWithNoPublicKey() { repository_ = std::make_unique(); proto::Device metadata; std::string decoded_key; @@ -83,7 +86,7 @@ class FastPairDataEncryptorImplTest : public testing::Test { latch.Await(); } - void SuccessfulSetUp() { + void SuccessCreateFastPairDataEncryptorWithKeyExchange() { repository_ = std::make_unique(); proto::Device metadata; std::string decoded_key; @@ -100,6 +103,22 @@ class FastPairDataEncryptorImplTest : public testing::Test { latch.Await(); } + void SuccessCreateFastPairDataEncryptorWithAccountKey() { + FastPairDevice device(kValidModelId, kTestAddress, + Protocol::kFastPairSubsequentPairing); + const std::vector kAccountKey{0x11, 0x22, 0x33, 0x44, 0x55, 0x66, + 0x77, 0x88, 0x99, 0x00, 0xAA, 0xBB, + 0xCC, 0xDD, 0xEE, 0xFF}; + device.SetAccountKey( + AccountKey(std::string(kAccountKey.begin(), kAccountKey.end()))); + CountDownLatch latch(1); + FastPairDataEncryptorImpl::Factory::CreateAsync( + device, absl::bind_front( + &FastPairDataEncryptorImplTest::OnDataEncryptorCreateAsync, + this, latch)); + latch.Await(); + } + void OnDataEncryptorCreateAsync( CountDownLatch latch, std::unique_ptr fast_pair_data_encryptor) { @@ -153,6 +172,21 @@ class FastPairDataEncryptorImplTest : public testing::Test { latch.Await(); } + void ParseDecryptedPasskeyWithAccountKey() { + const std::array kAccountKey{ + 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, + 0x99, 0x00, 0xAA, 0xBB, 0xCC, 0xDD, 0xEE, 0xFF}; + + auto bytes = FastPairEncryption::EncryptBytes(kAccountKey, kPasskeyBytes); + CountDownLatch latch(1); + data_encryptor_->ParseDecryptPasskey( + std::vector(bytes.begin(), bytes.end()), + absl::bind_front( + &FastPairDataEncryptorImplTest::ParseDecryptPasskeyCallback, this, + latch)); + latch.Await(); + } + void ParseDecryptedPasskeyInvalidBytes() { const std::array bytes = data_encryptor_->EncryptBytes(kPasskeyBytes); @@ -189,36 +223,55 @@ class FastPairDataEncryptorImplTest : public testing::Test { TEST_F(FastPairDataEncryptorImplTest, FailedSetUpNoMetadata) { EXPECT_FALSE(data_encryptor_); - FailedSetUpNoMetadata(); + FailedSetUpRepositoryWithNoDeviceMetadata(); EXPECT_FALSE(data_encryptor_); } TEST_F(FastPairDataEncryptorImplTest, NoKeyPair) { - FailedSetUpNoKeyPair(); + FailedSetUpRepositoryWithNoPublicKey(); EXPECT_FALSE(data_encryptor_); } -TEST_F(FastPairDataEncryptorImplTest, SuccessfulSetUp) { +TEST_F(FastPairDataEncryptorImplTest, + SuccessCreateFastPairDataEncryptorWithKeyExchange) { EXPECT_FALSE(data_encryptor_); - SuccessfulSetUp(); + SuccessCreateFastPairDataEncryptorWithKeyExchange(); + EXPECT_TRUE(data_encryptor_); +} + +TEST_F(FastPairDataEncryptorImplTest, + SuccessCreateFastPairDataEncryptorWithAccountKey) { + EXPECT_FALSE(data_encryptor_); + SuccessCreateFastPairDataEncryptorWithAccountKey(); EXPECT_TRUE(data_encryptor_); } TEST_F(FastPairDataEncryptorImplTest, GetPublicKey) { - SuccessfulSetUp(); + SuccessCreateFastPairDataEncryptorWithKeyExchange(); EXPECT_TRUE(data_encryptor_); - ParseDecryptedPasskey(); EXPECT_NE(data_encryptor_->GetPublicKey(), std::nullopt); } -TEST_F(FastPairDataEncryptorImplTest, EncryptBytes) { - SuccessfulSetUp(); +TEST_F(FastPairDataEncryptorImplTest, GetNoPublicKey) { + SuccessCreateFastPairDataEncryptorWithAccountKey(); + EXPECT_TRUE(data_encryptor_); + EXPECT_EQ(data_encryptor_->GetPublicKey(), std::nullopt); +} + +TEST_F(FastPairDataEncryptorImplTest, EncryptBytesWithKeyExchange) { + SuccessCreateFastPairDataEncryptorWithKeyExchange(); EXPECT_TRUE(data_encryptor_); EXPECT_FALSE(EncryptBytes().empty()); } -TEST_F(FastPairDataEncryptorImplTest, ParseDecryptedResponse) { - SuccessfulSetUp(); +TEST_F(FastPairDataEncryptorImplTest, EncryptBytesWithAccountKey) { + SuccessCreateFastPairDataEncryptorWithAccountKey(); + EXPECT_TRUE(data_encryptor_); + EXPECT_FALSE(EncryptBytes().empty()); +} + +TEST_F(FastPairDataEncryptorImplTest, ParseDecryptedResponseWithKeyExchange) { + SuccessCreateFastPairDataEncryptorWithKeyExchange(); EXPECT_TRUE(data_encryptor_); ParseDecryptedResponse(); EXPECT_TRUE(response_); @@ -229,15 +282,27 @@ TEST_F(FastPairDataEncryptorImplTest, ParseDecryptedResponse) { FastPairMessageType::kKeyBasedPairingResponse); } -TEST_F(FastPairDataEncryptorImplTest, ParseDecryptedResponse_InvalidInputSize) { - SuccessfulSetUp(); +TEST_F(FastPairDataEncryptorImplTest, ParseDecryptedResponseWithAccountKey) { + SuccessCreateFastPairDataEncryptorWithAccountKey(); + EXPECT_TRUE(data_encryptor_); + ParseDecryptedResponse(); + EXPECT_TRUE(response_); + const std::array kAddressBytes = { + 0x5E, 0x3F, 0x45, 0x61, 0xC3, 0x32}; + EXPECT_EQ(response_->address_bytes, kAddressBytes); + EXPECT_EQ(response_->message_type, + FastPairMessageType::kKeyBasedPairingResponse); +} + +TEST_F(FastPairDataEncryptorImplTest, ParseDecryptedResponseInvalidInputSize) { + SuccessCreateFastPairDataEncryptorWithKeyExchange(); EXPECT_TRUE(data_encryptor_); ParseDecryptedResponseInvalidBytes(); EXPECT_FALSE(response_); } -TEST_F(FastPairDataEncryptorImplTest, ParseDecryptedPasskey) { - SuccessfulSetUp(); +TEST_F(FastPairDataEncryptorImplTest, ParseDecryptedPasskeyWithKeyExchange) { + SuccessCreateFastPairDataEncryptorWithKeyExchange(); EXPECT_TRUE(data_encryptor_); ParseDecryptedPasskey(); EXPECT_TRUE(passkey_); @@ -251,8 +316,23 @@ TEST_F(FastPairDataEncryptorImplTest, ParseDecryptedPasskey) { EXPECT_EQ(passkey_->message_type, FastPairMessageType::kSeekersPasskey); } -TEST_F(FastPairDataEncryptorImplTest, ParseDecryptedPasskey_InvalidInputSize) { - SuccessfulSetUp(); +TEST_F(FastPairDataEncryptorImplTest, ParseDecryptedPasskeyWithAccountKey) { + SuccessCreateFastPairDataEncryptorWithAccountKey(); + EXPECT_TRUE(data_encryptor_); + ParseDecryptedPasskeyWithAccountKey(); + EXPECT_TRUE(passkey_); + // Passkey bytes. + std::array 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, ParseDecryptedPasskeyInvalidInputSize) { + SuccessCreateFastPairDataEncryptorWithKeyExchange(); EXPECT_TRUE(data_encryptor_); ParseDecryptedPasskeyInvalidBytes(); EXPECT_FALSE(passkey_);