From 63c8486a417881ad2a1e670056522bc6a707f946 Mon Sep 17 00:00:00 2001 From: Anay Wadhera Date: Fri, 8 Nov 2024 14:13:50 -0800 Subject: [PATCH] Plumb vendor ID in certificate metadata and only set it in advertisement when advertising in everyone mode. PiperOrigin-RevId: 694636952 --- .../fake_nearby_share_certificate_manager.h | 1 + .../nearby_share_certificate_manager.h | 3 + .../nearby_share_certificate_manager_impl.cc | 27 ++++++++- .../nearby_share_certificate_manager_impl.h | 5 +- ...rby_share_certificate_manager_impl_test.cc | 14 +++++ sharing/certificates/test_util.cc | 59 ++++++++++++++----- sharing/certificates/test_util.h | 9 ++- sharing/nearby_sharing_service.h | 2 +- sharing/nearby_sharing_service_impl_test.cc | 20 ++++--- 9 files changed, 109 insertions(+), 31 deletions(-) diff --git a/sharing/certificates/fake_nearby_share_certificate_manager.h b/sharing/certificates/fake_nearby_share_certificate_manager.h index 1cafbd26..c3feab73 100644 --- a/sharing/certificates/fake_nearby_share_certificate_manager.h +++ b/sharing/certificates/fake_nearby_share_certificate_manager.h @@ -99,6 +99,7 @@ class FakeNearbyShareCertificateManager : public NearbyShareCertificateManager { CertDecryptedCallback callback) override; void DownloadPublicCertificates() override; void ClearPublicCertificates(std::function callback) override; + void SetVendorId(int32_t vendor_id) override {} std::string Dump() const override { return ""; } // Make protected methods from base class public in this fake class. diff --git a/sharing/certificates/nearby_share_certificate_manager.h b/sharing/certificates/nearby_share_certificate_manager.h index 81c6fdad..0d5c6ef5 100644 --- a/sharing/certificates/nearby_share_certificate_manager.h +++ b/sharing/certificates/nearby_share_certificate_manager.h @@ -123,6 +123,9 @@ class NearbyShareCertificateManager { // should be cleared. virtual void ClearPublicCertificates(std::function callback) = 0; + // Sets the vendor ID to generate certificates for. + virtual void SetVendorId(int32_t vendor_id) = 0; + // Dump certificates ID information for troubleshooting. virtual std::string Dump() const = 0; diff --git a/sharing/certificates/nearby_share_certificate_manager_impl.cc b/sharing/certificates/nearby_share_certificate_manager_impl.cc index e31e3805..686b51cd 100644 --- a/sharing/certificates/nearby_share_certificate_manager_impl.cc +++ b/sharing/certificates/nearby_share_certificate_manager_impl.cc @@ -105,7 +105,8 @@ size_t NumExpectedPrivateCertificates() { std::optional BuildMetadata( std::string device_name, std::optional full_name, std::optional icon_url, - std::optional account_name, Context* context) { + std::optional account_name, int32_t vendor_id, + Context* context) { EncryptedMetadata metadata; if (device_name.empty()) { NL_LOG(WARNING) << __func__ @@ -124,6 +125,7 @@ std::optional BuildMetadata( if (account_name.has_value()) { metadata.set_account_name(*account_name); } + metadata.set_vendor_id(vendor_id); auto bluetooth_mac_address = context->GetBluetoothAdapter().GetAddress(); if (!bluetooth_mac_address) return std::nullopt; @@ -544,6 +546,27 @@ void NearbyShareCertificateManagerImpl::OnLocalDeviceDataChanged( }); } +void NearbyShareCertificateManagerImpl::SetVendorId(int32_t vendor_id) { + LOG(INFO) << "Setting certificate vendor ID to " << vendor_id; + vendor_id_ = vendor_id; + + auto certificate = GetValidPrivateCertificate( + proto::DeviceVisibility::DEVICE_VISIBILITY_ALL_CONTACTS); + auto self_certificate = GetValidPrivateCertificate( + proto::DeviceVisibility::DEVICE_VISIBILITY_SELF_SHARE); + if (certificate.has_value() && self_certificate.has_value()) { + if (certificate->unencrypted_metadata().vendor_id() == vendor_id_ && + self_certificate->unencrypted_metadata().vendor_id() == vendor_id_) { + LOG(INFO) << "Requested vendor ID is already set in latest valid private " + "certificates. Skipping certificate refresh."; + return; + } + } + // Recreate all private certificates to ensure up-to-date metadata. + certificate_storage_->ClearPrivateCertificates(); + private_certificate_expiration_scheduler_->MakeImmediateRequest(); +} + std::string NearbyShareCertificateManagerImpl::Dump() const { std::stringstream sstream; sstream << "Public Certificates" << std::endl; @@ -650,7 +673,7 @@ void NearbyShareCertificateManagerImpl::FinishPrivateCertificateRefresh() { std::optional metadata = BuildMetadata(local_device_data_manager_->GetDeviceName(), full_name, - icon_url, email, context_); + icon_url, email, vendor_id_, context_); if (!metadata.has_value()) { NL_LOG(WARNING) diff --git a/sharing/certificates/nearby_share_certificate_manager_impl.h b/sharing/certificates/nearby_share_certificate_manager_impl.h index fadfcc14..67baf99a 100644 --- a/sharing/certificates/nearby_share_certificate_manager_impl.h +++ b/sharing/certificates/nearby_share_certificate_manager_impl.h @@ -88,6 +88,8 @@ class NearbyShareCertificateManagerImpl ~NearbyShareCertificateManagerImpl() override; + void SetVendorId(int32_t vendor_id) override; + private: // Class for maintaining a single instance of public certificate download // request. It is responsible for downloading all available pages and making @@ -114,7 +116,7 @@ class NearbyShareCertificateManagerImpl void FetchNextPage(); private: - nearby::sharing::api::SharingRpcClient* const nearby_share_client_; + nearby::sharing::api::SharingRpcClient* const nearby_share_client_; std::string device_id_; std::optional next_page_token_; int page_number_ = 1; @@ -198,6 +200,7 @@ class NearbyShareCertificateManagerImpl AccountManager& account_manager_; NearbyShareLocalDeviceDataManager* const local_device_data_manager_; NearbyShareContactManager* const contact_manager_; + int32_t vendor_id_ = 0; // Defaults to GOOGLE. std::unique_ptr< nearby::sharing::api::SharingRpcClient> nearby_client_; std::shared_ptr certificate_storage_; diff --git a/sharing/certificates/nearby_share_certificate_manager_impl_test.cc b/sharing/certificates/nearby_share_certificate_manager_impl_test.cc index 510cb1d1..ca12e6ff 100644 --- a/sharing/certificates/nearby_share_certificate_manager_impl_test.cc +++ b/sharing/certificates/nearby_share_certificate_manager_impl_test.cc @@ -765,6 +765,20 @@ TEST_F(NearbyShareCertificateManagerImplTest, } } +TEST_F(NearbyShareCertificateManagerImplTest, + RefreshPrivateCertificates_OnVendorIdChanged) { + cert_store_->ReplacePrivateCertificates({}); + cert_manager_->Start(); + + cert_manager_->SetVendorId(12345); + HandlePrivateCertificateRefresh(/*expect_private_cert_refresh=*/true, + /*expected_success=*/true); + RunUpload(/*success=*/true); + auto metadata = GetNearbyShareTestMetadata(); + metadata.set_vendor_id(12345); + VerifyPrivateCertificates(/*expected_metadata=*/metadata); +} + TEST_F(NearbyShareCertificateManagerImplTest, RefreshPrivateCertificates_ExpiredCertificate) { // First certificates are expired; diff --git a/sharing/certificates/test_util.cc b/sharing/certificates/test_util.cc index 8b5f98bc..c85568a1 100644 --- a/sharing/certificates/test_util.cc +++ b/sharing/certificates/test_util.cc @@ -109,12 +109,22 @@ constexpr uint8_t kTestEncryptedMetadataKey[] = {0x52, 0x0e, 0x7e, 0x6b, 0x8e, 0xa0, 0xee, 0x9d, 0x7b}; constexpr uint8_t kTestEncryptedMetadata[] = { - 0x4d, 0x59, 0x5d, 0xb6, 0xac, 0x70, 0x00, 0x8f, 0x32, 0x9d, 0x0d, 0xcf, - 0xc3, 0x8b, 0x01, 0x19, 0x1d, 0xad, 0x2e, 0xb4, 0x62, 0xec, 0xf3, 0xa5, - 0xe4, 0x89, 0x51, 0x37, 0x0d, 0x78, 0xad, 0x9d, 0x2e, 0xe5, 0x99, 0xd5, - 0xf7, 0x1d, 0x71, 0x47, 0xef, 0x33, 0xae, 0x4b, 0xe2, 0xda, 0x57, 0xfb, - 0x3c, 0xa9, 0x1b, 0xbb, 0x00, 0x67, 0x99, 0xf3, 0xa4, 0x03, 0xab, 0x73, - 0xe5, 0x1a, 0xf6, 0x5c, 0x5f, 0x15, 0xa0, 0x00, 0xa5, 0x41, 0xf9}; + 0x4d, 0x59, 0x5d, 0xb6, 0xac, 0x70, 0x00, 0x8f, 0x32, 0x9d, 0x0d, + 0xcf, 0xc3, 0x8b, 0x01, 0x19, 0x1d, 0xad, 0x2e, 0xb4, 0x62, 0xec, + 0xf3, 0xa5, 0xe4, 0x89, 0x51, 0x37, 0x0d, 0x78, 0xad, 0x9d, 0x2e, + 0xe5, 0x99, 0xd5, 0xf7, 0x1d, 0x71, 0x47, 0xef, 0x33, 0xae, 0x4b, + 0xe2, 0xda, 0x57, 0xfb, 0x3c, 0xa9, 0x1b, 0xbb, 0x00, 0x67, 0x99, + 0x18, 0x27, 0xf2, 0xea, 0x1a, 0x3d, 0xd6, 0xa4, 0x4a, 0xba, 0x0d, + 0xff, 0xac, 0xe8, 0x84, 0x33, 0xd1, 0xd0}; + +constexpr uint8_t kTestEncryptedMetadataVendorIdOne[] = { + 0x4d, 0x59, 0x5d, 0xb6, 0xac, 0x70, 0x00, 0x8f, 0x32, 0x9d, 0x0d, + 0xcf, 0xc3, 0x8b, 0x01, 0x19, 0x1d, 0xad, 0x2e, 0xb4, 0x62, 0xec, + 0xf3, 0xa5, 0xe4, 0x89, 0x51, 0x37, 0x0d, 0x78, 0xad, 0x9d, 0x2e, + 0xe5, 0x99, 0xd5, 0xf7, 0x1d, 0x71, 0x47, 0xef, 0x33, 0xae, 0x4b, + 0xe2, 0xda, 0x57, 0xfb, 0x3c, 0xa9, 0x1b, 0xbb, 0x00, 0x67, 0x99, + 0x18, 0x26, 0x42, 0xe5, 0x35, 0x5b, 0x75, 0xd5, 0x7d, 0x92, 0xeb, + 0xda, 0xea, 0x54, 0xd3, 0xa5, 0x28, 0xc2}; // Plaintext "sample" (from RFC 6979 A.2.5). constexpr uint8_t kTestPayloadToSign[] = {0x73, 0x61, 0x6d, 0x70, 0x6c, 0x65}; @@ -223,9 +233,10 @@ absl::Duration GetNearbyShareTestValidityOffset() { return offset; } -const nearby::sharing::proto::EncryptedMetadata& GetNearbyShareTestMetadata() { +const nearby::sharing::proto::EncryptedMetadata& GetNearbyShareTestMetadata( + uint8_t vendor_id) { static const nearby::sharing::proto::EncryptedMetadata* metadata = - new nearby::sharing::proto::EncryptedMetadata([] { + new nearby::sharing::proto::EncryptedMetadata([vendor_id] { std::array bytes; nearby::device::ParseBluetoothAddress(kTestUnparsedBluetoothMacAddress, absl::MakeSpan(bytes.data(), 6)); @@ -235,6 +246,7 @@ const nearby::sharing::proto::EncryptedMetadata& GetNearbyShareTestMetadata() { metadata.set_full_name(kTestMetadataFullName); metadata.set_icon_url(kTestMetadataIconUrl); metadata.set_account_name(kTestMetadataAccountName); + metadata.set_vendor_id(vendor_id); metadata.set_bluetooth_mac_address(bytes.data(), 6u); return metadata; @@ -248,6 +260,13 @@ const std::vector& GetNearbyShareTestEncryptedMetadata() { return *bytes; } +const std::vector& GetNearbyShareTestEncryptedMetadataVendorIdOne() { + static const std::vector* bytes = + new std::vector(std::begin(kTestEncryptedMetadataVendorIdOne), + std::end(kTestEncryptedMetadataVendorIdOne)); + return *bytes; +} + const std::vector& GetNearbyShareTestPayloadToSign() { static const std::vector* payload = new std::vector( std::begin(kTestPayloadToSign), std::end(kTestPayloadToSign)); @@ -268,20 +287,20 @@ const std::vector& GetNearbyShareTestPayloadHashUsingSecretKey() { } NearbySharePrivateCertificate GetNearbyShareTestPrivateCertificate( - DeviceVisibility visibility, absl::Time not_before) { + DeviceVisibility visibility, absl::Time not_before, uint8_t vendor_id) { NearbySharePrivateCertificate cert( visibility, not_before, not_before + kNearbyShareCertificateValidityPeriod, GetNearbyShareTestP256KeyPair(), GetNearbyShareTestSecretKey(), GetNearbyShareTestMetadataEncryptionKey(), - GetNearbyShareTestCertificateId(), GetNearbyShareTestMetadata(), + GetNearbyShareTestCertificateId(), GetNearbyShareTestMetadata(vendor_id), /*consumed_salts=*/std::set>()); cert.next_salts_for_testing().push(GetNearbyShareTestSalt()); return cert; } nearby::sharing::proto::PublicCertificate GetNearbyShareTestPublicCertificate( - DeviceVisibility visibility, absl::Time not_before) { + DeviceVisibility visibility, absl::Time not_before, uint8_t vendor_id) { nearby::sharing::proto::PublicCertificate cert; cert.set_secret_id(std::string(GetNearbyShareTestCertificateId().begin(), GetNearbyShareTestCertificateId().end())); @@ -299,9 +318,15 @@ nearby::sharing::proto::PublicCertificate GetNearbyShareTestPublicCertificate( cert.set_metadata_encryption_key( std::string(GetNearbyShareTestMetadataEncryptionKey().begin(), GetNearbyShareTestMetadataEncryptionKey().end())); - cert.set_encrypted_metadata_bytes( - std::string(GetNearbyShareTestEncryptedMetadata().begin(), - GetNearbyShareTestEncryptedMetadata().end())); + if (vendor_id == 1) { + cert.set_encrypted_metadata_bytes( + std::string(GetNearbyShareTestEncryptedMetadataVendorIdOne().begin(), + GetNearbyShareTestEncryptedMetadataVendorIdOne().end())); + } else { + cert.set_encrypted_metadata_bytes( + std::string(GetNearbyShareTestEncryptedMetadata().begin(), + GetNearbyShareTestEncryptedMetadata().end())); + } cert.set_metadata_encryption_key_tag( std::string(GetNearbyShareTestMetadataEncryptionKeyTag().begin(), GetNearbyShareTestMetadataEncryptionKeyTag().end())); @@ -314,8 +339,10 @@ GetNearbyShareTestPrivateCertificateList(DeviceVisibility visibility) { list.reserve(kNearbyShareNumPrivateCertificates); for (size_t i = 0; i < kNearbyShareNumPrivateCertificates; ++i) { list.push_back(GetNearbyShareTestPrivateCertificate( - visibility, GetNearbyShareTestNotBefore() + - i * kNearbyShareCertificateValidityPeriod)); + visibility, + GetNearbyShareTestNotBefore() + + i * kNearbyShareCertificateValidityPeriod, + 0)); } return list; } diff --git a/sharing/certificates/test_util.h b/sharing/certificates/test_util.h index bbb230eb..d70f3f73 100644 --- a/sharing/certificates/test_util.h +++ b/sharing/certificates/test_util.h @@ -54,7 +54,8 @@ const NearbyShareEncryptedMetadataKey& GetNearbyShareTestEncryptedMetadataKey(); absl::Time GetNearbyShareTestNotBefore(); absl::Duration GetNearbyShareTestValidityOffset(); -const nearby::sharing::proto::EncryptedMetadata& GetNearbyShareTestMetadata(); +const nearby::sharing::proto::EncryptedMetadata& GetNearbyShareTestMetadata( + uint8_t vendor_id = 0); const std::vector& GetNearbyShareTestEncryptedMetadata(); const std::vector& GetNearbyShareTestPayloadToSign(); @@ -63,10 +64,12 @@ const std::vector& GetNearbyShareTestPayloadHashUsingSecretKey(); NearbySharePrivateCertificate GetNearbyShareTestPrivateCertificate( proto::DeviceVisibility visibility, - absl::Time not_before = GetNearbyShareTestNotBefore()); + absl::Time not_before = GetNearbyShareTestNotBefore(), + uint8_t vendor_id = 0); nearby::sharing::proto::PublicCertificate GetNearbyShareTestPublicCertificate( proto::DeviceVisibility visibility, - absl::Time not_before = GetNearbyShareTestNotBefore()); + absl::Time not_before = GetNearbyShareTestNotBefore(), + uint8_t vendor_id = 0); // Returns a list of |kNearbyShareNumPrivateCertificates| private/public // certificates, spanning contiguous validity periods. diff --git a/sharing/nearby_sharing_service.h b/sharing/nearby_sharing_service.h index 2454bc70..899c2643 100644 --- a/sharing/nearby_sharing_service.h +++ b/sharing/nearby_sharing_service.h @@ -26,6 +26,7 @@ #include "internal/platform/clock.h" #include "sharing/advertisement.h" #include "sharing/attachment_container.h" +#include "sharing/certificates/nearby_share_certificate_manager.h" #include "sharing/internal/api/sharing_rpc_notifier.h" #include "sharing/local_device_data/nearby_share_local_device_data_manager.h" #include "sharing/nearby_sharing_settings.h" @@ -39,7 +40,6 @@ class AccountManager; namespace sharing { class NearbyNotificationDelegate; -class NearbyShareCertificateManager; class NearbyShareContactManager; class NearbyShareHttpNotifier; diff --git a/sharing/nearby_sharing_service_impl_test.cc b/sharing/nearby_sharing_service_impl_test.cc index 35f9b54f..7723668f 100644 --- a/sharing/nearby_sharing_service_impl_test.cc +++ b/sharing/nearby_sharing_service_impl_test.cc @@ -590,7 +590,8 @@ class NearbySharingServiceImplTest : public testing::Test { void ProcessLatestPublicCertificateDecryption(size_t expected_num_calls, bool success, - bool for_self_share = false) { + bool for_self_share = false, + uint8_t vendor_id = 0) { // Ensure that all pending mojo messages are processed and the certificate // manager state is as expected up to this point. std::vector< @@ -607,7 +608,8 @@ class NearbySharingServiceImplTest : public testing::Test { if (success) { nearby::sharing::proto::PublicCertificate cert = GetNearbyShareTestPublicCertificate( - DeviceVisibility::DEVICE_VISIBILITY_ALL_CONTACTS); + DeviceVisibility::DEVICE_VISIBILITY_ALL_CONTACTS, + GetNearbyShareTestNotBefore(), vendor_id); cert.set_for_self_share(for_self_share); std::move(calls.back().callback)( NearbyShareDecryptedPublicCertificate::DecryptPublicCertificate( @@ -4115,9 +4117,9 @@ TEST_F(NearbySharingServiceImplTest, DedupSameEndpointId) { }); ProcessLatestPublicCertificateDecryption(/*expected_num_calls=*/1, - /*success=*/true); + /*success=*/false); ProcessLatestPublicCertificateDecryption(/*expected_num_calls=*/2, - /*success=*/true); + /*success=*/false); EXPECT_EQ(share_target_1.id, share_target_2.id); // Vendor_id updated. EXPECT_EQ(share_target_1.vendor_id, 0); @@ -4176,7 +4178,7 @@ TEST_F(NearbySharingServiceImplTest, }); ProcessLatestPublicCertificateDecryption(/*expected_num_calls=*/2, - /*success=*/true); + /*success=*/false); EXPECT_EQ(share_target_1.id, share_target_2.id); // Vendor_id updated. EXPECT_EQ(share_target_1.vendor_id, 0); @@ -4212,7 +4214,7 @@ TEST_F(NearbySharingServiceImplTest, OnLostDedupSameEndpointIdAfterExpiry) { // vendor_id is default to 0. FindEndpoint(/*endpoint_id=*/"1"); ProcessLatestPublicCertificateDecryption(/*expected_num_calls=*/1, - /*success=*/true); + /*success=*/false); // Finish processing all the HandleEndpointDiscovered related events before // fast forwarding to avoid race condition. FlushTesting(); @@ -4239,7 +4241,7 @@ TEST_F(NearbySharingServiceImplTest, OnLostDedupSameEndpointIdAfterExpiry) { }); ProcessLatestPublicCertificateDecryption(/*expected_num_calls=*/2, - /*success=*/true); + /*success=*/false); EXPECT_EQ(share_target_1_lost.id, share_target_1.id); // Cache entry expires and the share_target ID is not preserved. EXPECT_NE(share_target_1.id, share_target_2.id); @@ -4382,7 +4384,9 @@ TEST_F(NearbySharingServiceImplTest, EndpointDedupBasedOnDeviceId) { }); ProcessLatestPublicCertificateDecryption(/*expected_num_calls=*/3, - /*success=*/true); + /*success=*/true, + /*for_self_share=*/false, + /*vendor_id*/ 1); FlushTesting(); FindInvalidEndpoint(/*endpoint_id=*/"4");