diff --git a/sharing/certificates/nearby_share_certificate_manager.cc b/sharing/certificates/nearby_share_certificate_manager.cc index c54f6e86..2d1cf898 100644 --- a/sharing/certificates/nearby_share_certificate_manager.cc +++ b/sharing/certificates/nearby_share_certificate_manager.cc @@ -17,6 +17,7 @@ #include #include +#include #include #include "absl/types/span.h" @@ -73,6 +74,15 @@ NearbyShareCertificateManager::EncryptPrivateCertificateMetadataKey( return encrypted_key; } +std::optional +NearbyShareCertificateManager::GetPrivateCertificateId( + DeviceVisibility visibility) { + std::optional cert = + GetValidPrivateCertificate(visibility); + if (!cert) return std::nullopt; + return std::string(cert->id().begin(), cert->id().end()); +} + std::optional> NearbyShareCertificateManager::SignWithPrivateCertificate( DeviceVisibility visibility, absl::Span payload) const { diff --git a/sharing/certificates/nearby_share_certificate_manager.h b/sharing/certificates/nearby_share_certificate_manager.h index b040269f..2b79b8f2 100644 --- a/sharing/certificates/nearby_share_certificate_manager.h +++ b/sharing/certificates/nearby_share_certificate_manager.h @@ -81,6 +81,12 @@ class NearbyShareCertificateManager { std::optional EncryptPrivateCertificateMetadataKey(proto::DeviceVisibility visibility); + // Returns the id of the currently valid private certificate with + // |visibility|, or absl::nullopt if there is no valid private certificate + // with |visibility|. + std::optional GetPrivateCertificateId( + proto::DeviceVisibility visibility); + // Signs the input |payload| using the currently valid private certificate // with |visibility|. Returns absl::nullopt if there is no valid private // certificate with |visibility| or if the signing was unsuccessful. diff --git a/sharing/certificates/nearby_share_certificate_manager_impl_test.cc b/sharing/certificates/nearby_share_certificate_manager_impl_test.cc index 83ebc46d..09717a4a 100644 --- a/sharing/certificates/nearby_share_certificate_manager_impl_test.cc +++ b/sharing/certificates/nearby_share_certificate_manager_impl_test.cc @@ -636,6 +636,31 @@ TEST_F(NearbyShareCertificateManagerImplTest, DeviceVisibility::DEVICE_VISIBILITY_ALL_CONTACTS)); } +TEST_F(NearbyShareCertificateManagerImplTest, + GetPrivateCertificateIdWithNoCertificates) { + Initialize(); + cert_store_->ReplacePrivateCertificates({}); + EXPECT_FALSE(cert_manager_->GetPrivateCertificateId( + DeviceVisibility::DEVICE_VISIBILITY_ALL_CONTACTS).has_value()); +} + +TEST_F(NearbyShareCertificateManagerImplTest, + GetPrivateCertificateIdWithValidCertificate) { + Initialize(); + NearbySharePrivateCertificate private_certificate = + GetNearbyShareTestPrivateCertificate( + DeviceVisibility::DEVICE_VISIBILITY_ALL_CONTACTS); + cert_store_->ReplacePrivateCertificates({private_certificate}); + FastForward(GetNearbyShareTestNotBefore() + + kNearbyShareCertificateValidityPeriod * 0.5 - Now()); + ASSERT_TRUE(cert_manager_->GetPrivateCertificateId( + DeviceVisibility::DEVICE_VISIBILITY_ALL_CONTACTS).has_value()); + EXPECT_EQ(cert_manager_->GetPrivateCertificateId( + DeviceVisibility::DEVICE_VISIBILITY_ALL_CONTACTS).value(), + std::string(private_certificate.id().begin(), + private_certificate.id().end())); +} + TEST_F(NearbyShareCertificateManagerImplTest, SignWithPrivateCertificate) { Initialize(); NearbySharePrivateCertificate private_certificate = diff --git a/sharing/nearby_sharing_service_impl.cc b/sharing/nearby_sharing_service_impl.cc index c1b8fed1..4cbede27 100644 --- a/sharing/nearby_sharing_service_impl.cc +++ b/sharing/nearby_sharing_service_impl.cc @@ -2761,6 +2761,20 @@ void NearbySharingServiceImpl::BeginOutgoingPairing( }); } +std::vector NearbySharingServiceImpl::GetCertIdsForSyncBinding() { + std::vector cert_ids; + cert_ids.reserve(2); + if (auto id = certificate_manager_->GetPrivateCertificateId( + proto::DeviceVisibility::DEVICE_VISIBILITY_SELF_SHARE)) { + cert_ids.push_back(*id); + } + if (auto id = certificate_manager_->GetPrivateCertificateId( + proto::DeviceVisibility::DEVICE_VISIBILITY_ALL_CONTACTS)) { + cert_ids.push_back(*id); + } + return cert_ids; +} + void NearbySharingServiceImpl::OnInitiateSyncBindingResponse( int64_t share_target_id, absl::StatusOr binding_status) { RunOnNearbySharingServiceThread( @@ -2779,7 +2793,7 @@ void NearbySharingServiceImpl::OnInitiateSyncBindingResponse( LOG(INFO) << __func__ << ": Sync binding rpc succeeded: id=" << binding_id; session->StartPeerBinding( - binding_id, BindingRequest::FILESYNC, + binding_id, BindingRequest::FILESYNC, GetCertIdsForSyncBinding(), [this, share_target_id, binding_id](BindingResponse::Status status) { OnPeerSyncBindingComplete(share_target_id, binding_id, status); diff --git a/sharing/nearby_sharing_service_impl.h b/sharing/nearby_sharing_service_impl.h index fe799f4b..7223f632 100644 --- a/sharing/nearby_sharing_service_impl.h +++ b/sharing/nearby_sharing_service_impl.h @@ -409,6 +409,7 @@ class NearbySharingServiceImpl bool OutgoingSessionAccept(OutgoingShareSession& session); void OnIncomingFilesMetadataUpdated(int64_t share_target_id, TransferMetadata metadata, bool success); + std::vector GetCertIdsForSyncBinding(); // Called when InitiateBinding rpc returns. void OnInitiateSyncBindingResponse( int64_t share_target_id, absl::StatusOr binding_status); diff --git a/sharing/nearby_sharing_service_impl_test.cc b/sharing/nearby_sharing_service_impl_test.cc index 1c8cc1ea..a9ab39be 100644 --- a/sharing/nearby_sharing_service_impl_test.cc +++ b/sharing/nearby_sharing_service_impl_test.cc @@ -5179,6 +5179,7 @@ TEST_F(NearbySharingServiceImplTest, EXPECT_EQ(frame->v1().bindings().binding_request().binding_id(), kBindingId); EXPECT_EQ(frame->v1().bindings().binding_request().type(), service::proto::BindingRequest::FILESYNC); + EXPECT_EQ(frame->v1().bindings().binding_request().cert_ids_size(), 2); // BindingResponse frame timeout. FastForward(absl::Seconds(60)); diff --git a/sharing/outgoing_share_session.cc b/sharing/outgoing_share_session.cc index ce22718c..eb613ab9 100644 --- a/sharing/outgoing_share_session.cc +++ b/sharing/outgoing_share_session.cc @@ -27,6 +27,7 @@ #include "absl/functional/any_invocable.h" #include "absl/strings/string_view.h" #include "absl/time/time.h" +#include "absl/types/span.h" #include "internal/base/file_path.h" #include "internal/base/files.h" #include "internal/platform/clock.h" @@ -647,6 +648,7 @@ OutgoingShareSession::ProcessPayloadTransferUpdates() { void OutgoingShareSession::StartPeerBinding( std::string binding_id, BindingRequest::Type binding_type, + absl::Span cert_ids, absl::AnyInvocable callback) { Frame frame; frame.set_version(Frame::V1); @@ -656,6 +658,7 @@ void OutgoingShareSession::StartPeerBinding( v1_frame->mutable_bindings()->mutable_binding_request(); binding_request->set_binding_id(binding_id); binding_request->set_type(binding_type); + binding_request->mutable_cert_ids()->Add(cert_ids.begin(), cert_ids.end()); WriteFrame(frame); LOG(INFO) << "Waiting for bindings response frame from " << share_target().id; UpdateTransferMetadata( diff --git a/sharing/outgoing_share_session.h b/sharing/outgoing_share_session.h index 401b04a3..5ff89dce 100644 --- a/sharing/outgoing_share_session.h +++ b/sharing/outgoing_share_session.h @@ -26,6 +26,7 @@ #include "absl/functional/any_invocable.h" #include "absl/strings/string_view.h" #include "absl/time/time.h" +#include "absl/types/span.h" #include "internal/platform/clock.h" #include "internal/platform/task_runner.h" #include "sharing/analytics/analytics_recorder.h" @@ -164,11 +165,14 @@ class OutgoingShareSession : public ShareSession { // Initiates the peer binding message exchange with the remote device. // `binding_id` is the result of a successful call to InitiateBinding rpc. + // `cert_ids` are the public certificate ids that can be used to identify this + // device. // `callback` is called when either a BindingResponse frame is received or a // timeout occurs. void StartPeerBinding( std::string binding_id, nearby::sharing::service::proto::BindingRequest::Type binding_type, + absl::Span cert_ids, absl::AnyInvocable< void(nearby::sharing::service::proto::BindingResponse::Status)> callback); diff --git a/sharing/outgoing_share_session_test.cc b/sharing/outgoing_share_session_test.cc index 7843bfa6..43cf62f0 100644 --- a/sharing/outgoing_share_session_test.cc +++ b/sharing/outgoing_share_session_test.cc @@ -928,6 +928,8 @@ TEST_F(OutgoingShareSessionTest, StartPeerBindingSuccess) { binding_request { binding_id: "test_binding_id" type: FILESYNC + cert_ids: "cert_id_1" + cert_ids: "cert_id_2" } } } @@ -946,11 +948,11 @@ TEST_F(OutgoingShareSessionTest, StartPeerBindingSuccess) { HasUsage(ShareSessionUsage::kPairing)))); BindingResponse::Status binding_response_status = BindingResponse::FAILURE; - session_.StartPeerBinding("test_binding_id", BindingRequest::FILESYNC, - [&binding_response_status]( - BindingResponse::Status status) { - binding_response_status = status; - }); + session_.StartPeerBinding( + "test_binding_id", BindingRequest::FILESYNC, {"cert_id_1", "cert_id_2"}, + [&binding_response_status](BindingResponse::Status status) { + binding_response_status = status; + }); Frame frame; ASSERT_THAT(frame.ParseFromArray(frame_data.data(), frame_data.size()), @@ -1014,11 +1016,11 @@ TEST_F(OutgoingShareSessionTest, StartPeerBindingTimeout) { HasUsage(ShareSessionUsage::kPairing)))); BindingResponse::Status binding_response_status = BindingResponse::FAILURE; - session_.StartPeerBinding("test_binding_id", BindingRequest::FILESYNC, - [&binding_response_status]( - BindingResponse::Status status) { - binding_response_status = status; - }); + session_.StartPeerBinding( + "test_binding_id", BindingRequest::FILESYNC, {}, + [&binding_response_status](BindingResponse::Status status) { + binding_response_status = status; + }); Frame frame; ASSERT_THAT(frame.ParseFromArray(frame_data.data(), frame_data.size()), @@ -1065,11 +1067,11 @@ TEST_F(OutgoingShareSessionTest, StartPeerBindingFailure) { HasUsage(ShareSessionUsage::kPairing)))); BindingResponse::Status binding_response_status = BindingResponse::FAILURE; - session_.StartPeerBinding("test_binding_id", BindingRequest::FILESYNC, - [&binding_response_status]( - BindingResponse::Status status) { - binding_response_status = status; - }); + session_.StartPeerBinding( + "test_binding_id", BindingRequest::FILESYNC, {}, + [&binding_response_status](BindingResponse::Status status) { + binding_response_status = status; + }); Frame frame; ASSERT_THAT(frame.ParseFromArray(frame_data.data(), frame_data.size()),