[Nearby Presence] Read response data from remote device

see go/cros-nearby-presence-np-nc-authentication for details.

PiperOrigin-RevId: 606772097
This commit is contained in:
Juliet Levesque
2024-02-13 15:50:07 -08:00
committed by Copybara-Service
parent f8c907a120
commit caf34a717f
12 changed files with 378 additions and 94 deletions
+2
View File
@@ -35,6 +35,7 @@ cc_library(
"//internal/interop:device",
"//internal/platform:base",
"//internal/platform:types",
"//internal/platform/implementation:comm",
"//internal/platform/implementation:types",
"//internal/proto:local_credential_cc_proto",
"//internal/proto:metadata_cc_proto",
@@ -195,6 +196,7 @@ cc_test(
"//internal/proto:credential_cc_proto",
"//internal/proto:local_credential_cc_proto",
"//internal/proto:metadata_cc_proto",
"//presence/implementation:internal",
"//presence/implementation:internal_test",
"//presence/proto:presence_frame_cc_proto",
"@com_github_protobuf_matchers//protobuf-matchers",
+9 -3
View File
@@ -56,7 +56,7 @@ cc_library(
"advertisement_factory.cc",
"base_broadcast_request.cc",
"broadcast_manager.cc",
"connection_authenticator.cc",
"connection_authenticator_impl.cc",
"credential_manager_impl.cc",
"ldt.cc",
"scan_manager.cc",
@@ -69,6 +69,7 @@ cc_library(
"base_broadcast_request.h",
"broadcast_manager.h",
"connection_authenticator.h",
"connection_authenticator_impl.h",
"credential_manager.h",
"credential_manager_impl.h",
"ldt.h",
@@ -137,6 +138,7 @@ cc_library(
srcs = [
],
hdrs = [
"mock_connection_authenticator.h",
"mock_credential_manager.h",
"mock_service_controller.h",
],
@@ -146,7 +148,11 @@ cc_library(
deps = [
":internal",
"//internal/platform/implementation:comm",
"//internal/proto:credential_cc_proto",
"//internal/proto:local_credential_cc_proto",
"@com_github_protobuf_matchers//protobuf-matchers",
"@com_google_absl//absl/status",
"@com_google_absl//absl/status:statusor",
"@com_google_absl//absl/strings:string_view",
"@com_google_googletest//:gtest_main",
],
@@ -283,9 +289,9 @@ cc_test(
)
cc_test(
name = "connection_authenticator_test",
name = "connection_authenticator_impl_test",
size = "small",
srcs = ["connection_authenticator_test.cc"],
srcs = ["connection_authenticator_impl_test.cc"],
deps = [
":internal",
"//internal/crypto",
@@ -45,6 +45,8 @@ class ConnectionAuthenticator {
using InitiatorData = absl::variant<OneWayInitiatorData, TwoWayInitiatorData>;
virtual ~ConnectionAuthenticator() = default;
// Builds a signed message to be returned to Nearby Connections for
// authentication on the other side of the connection.
// ukey2_secret - The shared secret derived from the UKEY2 handshake in NC.
@@ -53,10 +55,10 @@ class ConnectionAuthenticator {
// performing one-way authentication.
// shared_credential - The shared credential used to decrypt the advertisement
// from the remote device.
absl::StatusOr<InitiatorData> BuildSignedMessageAsInitiator(
virtual absl::StatusOr<InitiatorData> BuildSignedMessageAsInitiator(
absl::string_view ukey2_secret,
std::optional<const internal::LocalCredential> local_credential,
const internal::SharedCredential& shared_credential) const;
const internal::SharedCredential& shared_credential) const = 0;
// Builds a signed message to be returned to Nearby Connections for
// authentication on the other side of the connection.
@@ -64,9 +66,9 @@ class ConnectionAuthenticator {
// local_credential - The local credential used to sign the derived
// information so the initiator can verify against our
// shared credential.
absl::StatusOr<ResponderData> BuildSignedMessageAsResponder(
virtual absl::StatusOr<ResponderData> BuildSignedMessageAsResponder(
absl::string_view ukey2_secret,
const internal::LocalCredential& local_credential) const;
const internal::LocalCredential& local_credential) const = 0;
// Verifies a signed message received from the responder (broadcaster) of the
// Nearby Presence advertisement.
@@ -75,22 +77,24 @@ class ConnectionAuthenticator {
// ukey2_secret - the shared secret derived from the ukey2 handshake in NC.
// shared_credentials - the set of shared credentials that can be used to
// verify the responder data.
absl::Status VerifyMessageAsInitiator(
virtual absl::Status VerifyMessageAsInitiator(
ResponderData authentication_data, absl::string_view ukey2_secret,
const std::vector<internal::SharedCredential>& shared_credentials) const;
const std::vector<internal::SharedCredential>& shared_credentials)
const = 0;
// Verifies a signed message received from the Nearby Connections peer.
// Returns absl::OkStatus() if the verification was successful.
// Returns the matched local credential if the verification was successful.
// ukey2_secret - The shared secret derived from the UKEY2 handshake in NC.
// received_frame - The received frame from Nearby Connections.
// local_credentials - The set of local credentials that may contain the
// required keyseed hash.
// shared_credentials - The set of shared credentials that can be used to
// verify the signed contents of the frame.
absl::StatusOr<internal::LocalCredential> VerifyMessageAsResponder(
virtual absl::StatusOr<internal::LocalCredential> VerifyMessageAsResponder(
absl::string_view ukey2_secret, InitiatorData initiator_data,
const std::vector<internal::LocalCredential>& local_credentials,
const std::vector<internal::SharedCredential>& shared_credentials) const;
const std::vector<internal::SharedCredential>& shared_credentials)
const = 0;
};
} // namespace presence
@@ -12,7 +12,7 @@
// See the License for the specific language governing permissions and
// limitations under the License.
#include "presence/implementation/connection_authenticator.h"
#include "presence/implementation/connection_authenticator_impl.h"
#include <optional>
#include <string>
@@ -47,7 +47,7 @@ constexpr char kDiscovererHkdfInfo[] =
} // namespace
absl::StatusOr<ConnectionAuthenticator::InitiatorData>
ConnectionAuthenticator::BuildSignedMessageAsInitiator(
ConnectionAuthenticatorImpl::BuildSignedMessageAsInitiator(
absl::string_view ukey2_secret,
std::optional<const internal::LocalCredential> local_credential,
const internal::SharedCredential& shared_credential) const {
@@ -78,7 +78,7 @@ ConnectionAuthenticator::BuildSignedMessageAsInitiator(
}
absl::StatusOr<ConnectionAuthenticator::ResponderData>
ConnectionAuthenticator::BuildSignedMessageAsResponder(
ConnectionAuthenticatorImpl::BuildSignedMessageAsResponder(
absl::string_view ukey2_secret,
const internal::LocalCredential& local_credential) const {
auto signer = crypto::Ed25519Signer::Create(
@@ -95,7 +95,7 @@ ConnectionAuthenticator::BuildSignedMessageAsResponder(
*pkey_signature};
}
absl::Status ConnectionAuthenticator::VerifyMessageAsInitiator(
absl::Status ConnectionAuthenticatorImpl::VerifyMessageAsInitiator(
ResponderData authentication_data, absl::string_view ukey2_secret,
const std::vector<internal::SharedCredential>& shared_credentials) const {
if (authentication_data.private_key_signature.empty()) {
@@ -119,7 +119,7 @@ absl::Status ConnectionAuthenticator::VerifyMessageAsInitiator(
}
absl::StatusOr<internal::LocalCredential>
ConnectionAuthenticator::VerifyMessageAsResponder(
ConnectionAuthenticatorImpl::VerifyMessageAsResponder(
absl::string_view ukey2_secret, InitiatorData initiator_data,
const std::vector<internal::LocalCredential>& local_credentials,
const std::vector<internal::SharedCredential>& shared_credentials) const {
@@ -0,0 +1,85 @@
// Copyright 2023 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_PRESENCE_IMPLEMENTATION_CONNECTION_AUTHENTICATOR_IMPL_H_
#define THIRD_PARTY_NEARBY_PRESENCE_IMPLEMENTATION_CONNECTION_AUTHENTICATOR_IMPL_H_
#include <optional>
#include <vector>
#include "absl/status/status.h"
#include "absl/status/statusor.h"
#include "absl/strings/string_view.h"
#include "internal/proto/credential.pb.h"
#include "internal/proto/local_credential.pb.h"
#include "presence/implementation/connection_authenticator.h"
namespace nearby {
namespace presence {
class ConnectionAuthenticatorImpl : public ConnectionAuthenticator {
public:
// Builds a signed message to be returned to Nearby Connections for
// authentication on the other side of the connection.
// ukey2_secret - The shared secret derived from the UKEY2 handshake in NC.
// local_credential - The local credential used to sign the derived
// information. If this is std::nullopt, then we will be
// performing one-way authentication.
// shared_credential - The shared credential used to decrypt the advertisement
// from the remote device.
absl::StatusOr<InitiatorData> BuildSignedMessageAsInitiator(
absl::string_view ukey2_secret,
std::optional<const internal::LocalCredential> local_credential,
const internal::SharedCredential& shared_credential) const override;
// Builds a signed message to be returned to Nearby Connections for
// authentication on the other side of the connection.
// ukey2_secret - The shared secret derived from the UKEY2 handshake in NC.
// local_credential - The local credential used to sign the derived
// information so the initiator can verify against our
// shared credential.
absl::StatusOr<ResponderData> BuildSignedMessageAsResponder(
absl::string_view ukey2_secret,
const internal::LocalCredential& local_credential) const override;
// Verifies a signed message received from the responder (broadcaster) of the
// Nearby Presence advertisement.
// authentication_data - the data required to verify the connection, received
// from the responder.
// ukey2_secret - the shared secret derived from the ukey2 handshake in NC.
// shared_credentials - the set of shared credentials that can be used to
// verify the responder data.
absl::Status VerifyMessageAsInitiator(
ResponderData authentication_data, absl::string_view ukey2_secret,
const std::vector<internal::SharedCredential>& shared_credentials)
const override;
// Verifies a signed message received from the Nearby Connections peer.
// ukey2_secret - The shared secret derived from the UKEY2 handshake in NC.
// received_frame - The received frame from Nearby Connections.
// local_credentials - The set of local credentials that may contain the
// required keyseed hash.
// shared_credentials - The set of shared credentials that can be used to
// verify the signed contents of the frame.
absl::StatusOr<internal::LocalCredential> VerifyMessageAsResponder(
absl::string_view ukey2_secret, InitiatorData initiator_data,
const std::vector<internal::LocalCredential>& local_credentials,
const std::vector<internal::SharedCredential>& shared_credentials)
const override;
};
} // namespace presence
} // namespace nearby
#endif // THIRD_PARTY_NEARBY_PRESENCE_IMPLEMENTATION_CONNECTION_AUTHENTICATOR_IMPL_H_
@@ -12,7 +12,7 @@
// See the License for the specific language governing permissions and
// limitations under the License.
#include "presence/implementation/connection_authenticator.h"
#include "presence/implementation/connection_authenticator_impl.h"
#include <string>
#include <vector>
@@ -79,8 +79,8 @@ class PresenceAuthenticatorTest : public ::testing::Test {
};
TEST_F(PresenceAuthenticatorTest, TestTwoWayInitiatorSignResponderVerify) {
ConnectionAuthenticator responder_authenticator;
ConnectionAuthenticator initiator_authenticator;
ConnectionAuthenticatorImpl responder_authenticator;
ConnectionAuthenticatorImpl initiator_authenticator;
ASSERT_OK_AND_ASSIGN(ConnectionAuthenticator::InitiatorData auth_data,
initiator_authenticator.BuildSignedMessageAsInitiator(
kUkey2Secret, initiator_local_credential_,
@@ -93,8 +93,8 @@ TEST_F(PresenceAuthenticatorTest, TestTwoWayInitiatorSignResponderVerify) {
}
TEST_F(PresenceAuthenticatorTest, TestOneWayInitiatorSignResponderVerify) {
ConnectionAuthenticator responder_authenticator;
ConnectionAuthenticator initiator_authenticator;
ConnectionAuthenticatorImpl responder_authenticator;
ConnectionAuthenticatorImpl initiator_authenticator;
ASSERT_OK_AND_ASSIGN(
ConnectionAuthenticator::InitiatorData auth_data,
initiator_authenticator.BuildSignedMessageAsInitiator(
@@ -107,8 +107,8 @@ TEST_F(PresenceAuthenticatorTest, TestOneWayInitiatorSignResponderVerify) {
}
TEST_F(PresenceAuthenticatorTest, TestResponderSignInitiatorVerify) {
ConnectionAuthenticator responder_authenticator;
ConnectionAuthenticator initiator_authenticator;
ConnectionAuthenticatorImpl responder_authenticator;
ConnectionAuthenticatorImpl initiator_authenticator;
ASSERT_OK_AND_ASSIGN(ConnectionAuthenticator::ResponderData auth_data,
responder_authenticator.BuildSignedMessageAsResponder(
kUkey2Secret, responder_local_credential_));
@@ -118,8 +118,8 @@ TEST_F(PresenceAuthenticatorTest, TestResponderSignInitiatorVerify) {
TEST_F(PresenceAuthenticatorTest,
TestTwoWayInitiatorSignResponderVerifyNoSharedCredentialMatchFails) {
ConnectionAuthenticator responder_authenticator;
ConnectionAuthenticator initiator_authenticator;
ConnectionAuthenticatorImpl responder_authenticator;
ConnectionAuthenticatorImpl initiator_authenticator;
ASSERT_OK_AND_ASSIGN(ConnectionAuthenticator::InitiatorData auth_data,
initiator_authenticator.BuildSignedMessageAsInitiator(
kUkey2Secret, initiator_local_credential_,
@@ -131,8 +131,8 @@ TEST_F(PresenceAuthenticatorTest,
TEST_F(PresenceAuthenticatorTest,
TestOneWayInitiatorSignResponderVerifyNoMatchCredentialFails) {
ConnectionAuthenticator responder_authenticator;
ConnectionAuthenticator initiator_authenticator;
ConnectionAuthenticatorImpl responder_authenticator;
ConnectionAuthenticatorImpl initiator_authenticator;
ASSERT_OK_AND_ASSIGN(
ConnectionAuthenticator::InitiatorData auth_data,
initiator_authenticator.BuildSignedMessageAsInitiator(
@@ -144,8 +144,8 @@ TEST_F(PresenceAuthenticatorTest,
TEST_F(PresenceAuthenticatorTest,
TestOneWayInitiatorSignResponderVerifyNoCredentialFails) {
ConnectionAuthenticator responder_authenticator;
ConnectionAuthenticator initiator_authenticator;
ConnectionAuthenticatorImpl responder_authenticator;
ConnectionAuthenticatorImpl initiator_authenticator;
ASSERT_OK_AND_ASSIGN(
ConnectionAuthenticator::InitiatorData auth_data,
initiator_authenticator.BuildSignedMessageAsInitiator(
@@ -157,8 +157,8 @@ TEST_F(PresenceAuthenticatorTest,
TEST_F(PresenceAuthenticatorTest,
TestTwoWayInitiatorSignResponderVerifyNoMatchCredentialFails) {
ConnectionAuthenticator responder_authenticator;
ConnectionAuthenticator initiator_authenticator;
ConnectionAuthenticatorImpl responder_authenticator;
ConnectionAuthenticatorImpl initiator_authenticator;
ASSERT_OK_AND_ASSIGN(ConnectionAuthenticator::InitiatorData auth_data,
initiator_authenticator.BuildSignedMessageAsInitiator(
kUkey2Secret, initiator_local_credential_,
@@ -170,8 +170,8 @@ TEST_F(PresenceAuthenticatorTest,
TEST_F(PresenceAuthenticatorTest,
TestTwoWayInitiatorSignResponderVerifyWrongKeyFails) {
ConnectionAuthenticator responder_authenticator;
ConnectionAuthenticator initiator_authenticator;
ConnectionAuthenticatorImpl responder_authenticator;
ConnectionAuthenticatorImpl initiator_authenticator;
ASSERT_OK_AND_ASSIGN(ConnectionAuthenticator::InitiatorData auth_data,
initiator_authenticator.BuildSignedMessageAsInitiator(
kUkey2Secret, initiator_local_credential_,
@@ -184,8 +184,8 @@ TEST_F(PresenceAuthenticatorTest,
TEST_F(PresenceAuthenticatorTest,
TestResponderSignInitiatorVerifyNoMatchCredentialFails) {
ConnectionAuthenticator responder_authenticator;
ConnectionAuthenticator initiator_authenticator;
ConnectionAuthenticatorImpl responder_authenticator;
ConnectionAuthenticatorImpl initiator_authenticator;
ASSERT_OK_AND_ASSIGN(ConnectionAuthenticator::ResponderData auth_data,
responder_authenticator.BuildSignedMessageAsResponder(
kUkey2Secret, responder_local_credential_));
@@ -196,8 +196,8 @@ TEST_F(PresenceAuthenticatorTest,
TEST_F(PresenceAuthenticatorTest,
TestResponderSignInitiatorVerifyWrongKeyFails) {
ConnectionAuthenticator responder_authenticator;
ConnectionAuthenticator initiator_authenticator;
ConnectionAuthenticatorImpl responder_authenticator;
ConnectionAuthenticatorImpl initiator_authenticator;
ASSERT_OK_AND_ASSIGN(ConnectionAuthenticator::ResponderData auth_data,
responder_authenticator.BuildSignedMessageAsResponder(
kUkey2Secret, responder_local_credential_));
@@ -209,8 +209,8 @@ TEST_F(PresenceAuthenticatorTest,
TEST_F(PresenceAuthenticatorTest,
TestTwoWayInitiatorSignResponderVerifyNoCidHashFails) {
ConnectionAuthenticator responder_authenticator;
ConnectionAuthenticator initiator_authenticator;
ConnectionAuthenticatorImpl responder_authenticator;
ConnectionAuthenticatorImpl initiator_authenticator;
ASSERT_OK_AND_ASSIGN(ConnectionAuthenticator::InitiatorData auth_data,
initiator_authenticator.BuildSignedMessageAsInitiator(
kUkey2Secret, initiator_local_credential_,
@@ -225,8 +225,8 @@ TEST_F(PresenceAuthenticatorTest,
TEST_F(PresenceAuthenticatorTest,
TestTwoWayInitiatorSignResponderVerifyNoPkeySigFails) {
ConnectionAuthenticator responder_authenticator;
ConnectionAuthenticator initiator_authenticator;
ConnectionAuthenticatorImpl responder_authenticator;
ConnectionAuthenticatorImpl initiator_authenticator;
ASSERT_OK_AND_ASSIGN(ConnectionAuthenticator::InitiatorData auth_data,
initiator_authenticator.BuildSignedMessageAsInitiator(
kUkey2Secret, initiator_local_credential_,
@@ -241,8 +241,8 @@ TEST_F(PresenceAuthenticatorTest,
TEST_F(PresenceAuthenticatorTest,
TestOneWayInitiatorSignResponderVerifyNoCidHashFails) {
ConnectionAuthenticator responder_authenticator;
ConnectionAuthenticator initiator_authenticator;
ConnectionAuthenticatorImpl responder_authenticator;
ConnectionAuthenticatorImpl initiator_authenticator;
ASSERT_OK_AND_ASSIGN(
ConnectionAuthenticator::InitiatorData auth_data,
initiator_authenticator.BuildSignedMessageAsInitiator(
@@ -257,8 +257,8 @@ TEST_F(PresenceAuthenticatorTest,
TEST_F(PresenceAuthenticatorTest,
TestResponderSignInitiatorVerifyNoPkeySigFail) {
ConnectionAuthenticator responder_authenticator;
ConnectionAuthenticator initiator_authenticator;
ConnectionAuthenticatorImpl responder_authenticator;
ConnectionAuthenticatorImpl initiator_authenticator;
ASSERT_OK_AND_ASSIGN(ConnectionAuthenticator::ResponderData auth_data,
responder_authenticator.BuildSignedMessageAsResponder(
kUkey2Secret, responder_local_credential_));
@@ -0,0 +1,63 @@
// Copyright 2023 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_PRESENCE_IMPLEMENTATION_MOCK_CONNECTION_AUTHENTICATOR_H_
#define THIRD_PARTY_NEARBY_PRESENCE_IMPLEMENTATION_MOCK_CONNECTION_AUTHENTICATOR_H_
#include <optional>
#include <vector>
#include "gmock/gmock.h"
#include "absl/status/status.h"
#include "absl/status/statusor.h"
#include "absl/strings/string_view.h"
#include "internal/proto/credential.pb.h"
#include "internal/proto/local_credential.pb.h"
#include "presence/implementation/connection_authenticator.h"
namespace nearby {
namespace presence {
/*
* This class is for unit tests, mocking {@code ConnectionAuthenticator}
* functions in `PresenceDeviceProviderTest`.
*/
class MockConnectionAuthenticator : public ConnectionAuthenticator {
public:
MOCK_METHOD(absl::StatusOr<InitiatorData>, BuildSignedMessageAsInitiator,
(absl::string_view ukey2_secret,
std::optional<const internal::LocalCredential> local_credential,
const internal::SharedCredential& shared_credential),
(const override));
MOCK_METHOD(absl::StatusOr<ResponderData>, BuildSignedMessageAsResponder,
(absl::string_view ukey2_secret,
const internal::LocalCredential& local_credential),
(const override));
MOCK_METHOD(
absl::Status, VerifyMessageAsInitiator,
(ResponderData authentication_data, absl::string_view ukey2_secret,
const std::vector<internal::SharedCredential>& shared_credentials),
(const override));
MOCK_METHOD(
absl::StatusOr<internal::LocalCredential>, VerifyMessageAsResponder,
(absl::string_view ukey2_secret, InitiatorData initiator_data,
const std::vector<internal::LocalCredential>& local_credentials,
const std::vector<internal::SharedCredential>& shared_credentials),
(const override));
};
} // namespace presence
} // namespace nearby
#endif // THIRD_PARTY_NEARBY_PRESENCE_IMPLEMENTATION_MOCK_CONNECTION_AUTHENTICATOR_H_
+68 -14
View File
@@ -18,6 +18,7 @@
#include <string>
#include <vector>
#include "absl/log/check.h"
#include "absl/types/variant.h"
#include "absl/strings/string_view.h"
#include "absl/time/time.h"
@@ -96,9 +97,13 @@ PresenceAuthenticationFrame BuildInitiatorPresenceAuthenticationFrame(
} // namespace
PresenceDeviceProvider::PresenceDeviceProvider(
ServiceController* service_controller)
ServiceController* service_controller,
const ConnectionAuthenticator* connection_authenticator)
: service_controller_(*service_controller),
device_{service_controller_.GetLocalDeviceMetadata()} {}
device_{service_controller_.GetLocalDeviceMetadata()},
connection_authenticator_(*connection_authenticator) {
CHECK(connection_authenticator);
}
AuthenticationStatus PresenceDeviceProvider::AuthenticateAsInitiator(
const NearbyDevice& remote_device, absl::string_view shared_secret,
@@ -110,9 +115,12 @@ AuthenticationStatus PresenceDeviceProvider::AuthenticateAsInitiator(
// iterates over the returned list and returns the local credential
// that corresponds with the current time.
//
// TODO(b/304843571): Add support for additional IdentityTypes. Currently,
// only `IDENTITY_TYPE_PRIVATE` is supported in order to unblock Nearby
// Presence MVP.
// TODO(b/304843571): Add support for additional IdentityTypes and for
// AuthenticationStatus::kUnknown. Currently, only `IDENTITY_TYPE_PRIVATE` is
// supported in order to unblock Nearby Presence MVP on CrOS, however in
// order to support future IdentityTypes, there needs to be a way to
// plumb in the requested identity type, as well as report back the
// unknown result to callers in NC.
service_controller_.GetLocalCredentials(
/*credential_selector=*/{.manager_app_id = manager_app_id_,
.account_name =
@@ -141,7 +149,7 @@ AuthenticationStatus PresenceDeviceProvider::AuthenticateAsInitiator(
// 2. Construct the frame and write to the
// |authentication_transport|.
if (!WriteToRemoteDevice(
/*remote_device=*/&remote_device,
/*remote_device=*/remote_device,
/*shared_secret=*/shared_secret,
/*authentication_transport=*/authentication_transport,
/*local_credential=*/credential.value(),
@@ -150,12 +158,17 @@ AuthenticationStatus PresenceDeviceProvider::AuthenticateAsInitiator(
return;
}
// TODO(b/282027237): Continue with the following steps, which will
// be done in follow up CL's.
// 3. Read the message from the remote device via
// |authentication_transport|.
// |authentication_transport| and verify the response data.
if (!ReadAndVerifyRemoteDeviceData(
/*remote_device=*/remote_device,
/*shared_secret=*/shared_secret,
/*authentication_transport=*/authentication_transport)) {
response.Set(AuthenticationStatus::kFailure);
return;
}
// 4. Return the status of the authentication to the callers.
// For now, return success on the Future.
response.Set(AuthenticationStatus::kSuccess);
}});
@@ -169,7 +182,7 @@ AuthenticationStatus PresenceDeviceProvider::AuthenticateAsInitiator(
}
bool PresenceDeviceProvider::WriteToRemoteDevice(
const NearbyDevice* remote_device, absl::string_view shared_secret,
const NearbyDevice& remote_device, absl::string_view shared_secret,
const AuthenticationTransport& authentication_transport,
const internal::LocalCredential& local_credential,
Future<AuthenticationStatus>& response) const {
@@ -177,7 +190,7 @@ bool PresenceDeviceProvider::WriteToRemoteDevice(
// it's shared credentials, which is safe to do since the |remote_device|
// passed to the `PresenceDeviceProvider` will always be a `PresenceDevice`.
const PresenceDevice* remote_presence_device =
static_cast<const PresenceDevice*>(remote_device);
static_cast<const PresenceDevice*>(&remote_device);
auto shared_credential = remote_presence_device->GetDecryptSharedCredential();
if (!shared_credential.has_value()) {
NEARBY_LOGS(INFO)
@@ -190,8 +203,6 @@ bool PresenceDeviceProvider::WriteToRemoteDevice(
connection_authenticator_.BuildSignedMessageAsInitiator(
/*ukey2_secret=*/shared_secret, /*local_credential=*/local_credential,
/*shared_credential=*/shared_credential.value());
// TODO(b/317219088): Add test covereage for when
// `ConnectionAuthenticator::BuildSignedMessageAsInitiator()` fails.
if (!status_or_initiator_data.ok()) {
NEARBY_LOGS(INFO) << __func__
<< ": failure to build signed message as initiator";
@@ -207,5 +218,48 @@ bool PresenceDeviceProvider::WriteToRemoteDevice(
return true;
}
bool PresenceDeviceProvider::ReadAndVerifyRemoteDeviceData(
const NearbyDevice& remote_device, absl::string_view shared_secret,
const AuthenticationTransport& authentication_transport) const {
// Fetch the local public credentials to be used to verify the response data.
Future<bool> read_and_verify_result;
service_controller_.GetLocalPublicCredentials(
/*credential_selector=*/{.manager_app_id = manager_app_id_,
.account_name =
device_.GetMetadata().account_name(),
.identity_type = ::nearby::internal::
IdentityType::IDENTITY_TYPE_PRIVATE},
/*callback=*/{.credentials_fetched_cb = [this, &read_and_verify_result,
&authentication_transport,
&shared_secret](
auto status_or_credentials) {
if (!status_or_credentials.ok()) {
NEARBY_LOGS(INFO)
<< __func__ << ": failure to fetch local public credentials";
read_and_verify_result.Set(/*success=*/false);
return;
}
std::string response_data = authentication_transport.ReadMessage();
auto status = connection_authenticator_.VerifyMessageAsInitiator(
/*authentication_data=*/{.private_key_signature = response_data},
/*ukey2_secret=*/shared_secret,
/*shared_credential=*/status_or_credentials.value());
if (!status.ok()) {
NEARBY_LOGS(INFO) << __func__ << ": failure to verify remote device";
read_and_verify_result.Set(/*success=*/false);
return;
}
read_and_verify_result.Set(/*success=*/true);
}});
NEARBY_LOGS(INFO) << __func__ << ": Waiting for future to complete";
ExceptionOr<bool> result = read_and_verify_result.Get();
NEARBY_LOGS(INFO) << "Future:[" << __func__
<< "] completed with status:" << result.result();
return result.result();
}
} // namespace presence
} // namespace nearby
+9 -3
View File
@@ -15,6 +15,7 @@
#ifndef THIRD_PARTY_NEARBY_PRESENCE_PRESENCE_DEVICE_PROVIDER_H_
#define THIRD_PARTY_NEARBY_PRESENCE_PRESENCE_DEVICE_PROVIDER_H_
#include <memory>
#include <string>
#include "absl/strings/string_view.h"
@@ -34,7 +35,9 @@ class ServiceController;
class PresenceDeviceProvider : public NearbyDeviceProvider {
public:
explicit PresenceDeviceProvider(ServiceController* service_controller);
PresenceDeviceProvider(
ServiceController* service_controller,
const ConnectionAuthenticator* connection_authenticator);
const NearbyDevice* GetLocalDevice() override { return &device_; }
@@ -70,15 +73,18 @@ class PresenceDeviceProvider : public NearbyDeviceProvider {
private:
bool WriteToRemoteDevice(
const NearbyDevice* remote_device, absl::string_view shared_secret,
const NearbyDevice& remote_device, absl::string_view shared_secret,
const AuthenticationTransport& authentication_transport,
const internal::LocalCredential& local_credential,
Future<AuthenticationStatus>& response) const;
bool ReadAndVerifyRemoteDeviceData(
const NearbyDevice& remote_device, absl::string_view shared_secret,
const AuthenticationTransport& authentication_transport) const;
ServiceController& service_controller_;
PresenceDevice device_;
std::string manager_app_id_;
ConnectionAuthenticator connection_authenticator_;
const ConnectionAuthenticator& connection_authenticator_;
};
} // namespace presence
+68 -6
View File
@@ -35,6 +35,8 @@
#include "internal/proto/credential.pb.h"
#include "internal/proto/local_credential.pb.h"
#include "internal/proto/metadata.pb.h"
#include "presence/implementation/connection_authenticator.h"
#include "presence/implementation/mock_connection_authenticator.h"
#include "presence/implementation/mock_service_controller.h"
#include "presence/presence_device.h"
#include "presence/proto/presence_frame.pb.h"
@@ -49,6 +51,8 @@ constexpr absl::string_view kManagerAppId = "test_app_id";
constexpr char kUkey2Secret[] = {0x34, 0x56, 0x78, 0x90};
constexpr char kKeySeed[] = {1, 2, 3, 4, 5, 6, 7, 8};
constexpr int kPresenceVersion = 1;
constexpr absl::string_view kSharedCredentialHash = "shared_cred_hash";
constexpr absl::string_view kPrivateKeySignature = "private_key_signature";
Metadata CreateTestMetadata() {
Metadata metadata;
@@ -90,6 +94,13 @@ internal::SharedCredential BuildSharedCredential(
return shared_credential;
}
ConnectionAuthenticator::TwoWayInitiatorData BuildDefaultInitiatorData() {
ConnectionAuthenticator::TwoWayInitiatorData data;
data.shared_credential_hash = kSharedCredentialHash;
data.private_key_signature = kPrivateKeySignature;
return data;
}
class MockAuthenticationTransport : public AuthenticationTransport {
public:
MOCK_METHOD(void, WriteMessage, (absl::string_view), (const override));
@@ -101,8 +112,8 @@ class PresenceDeviceProviderTest : public ::testing::Test {
PresenceDeviceProviderTest() {
ON_CALL(mock_service_controller_, GetLocalDeviceMetadata)
.WillByDefault(testing::Return(CreateTestMetadata()));
provider_ =
std::make_unique<PresenceDeviceProvider>(&mock_service_controller_);
provider_ = std::make_unique<PresenceDeviceProvider>(
&mock_service_controller_, &mock_connection_authenticator_);
}
void SetUp() override {
@@ -114,6 +125,7 @@ class PresenceDeviceProviderTest : public ::testing::Test {
MockServiceController mock_service_controller_;
std::unique_ptr<PresenceDeviceProvider> provider_;
crypto::Ed25519KeyPair key_pair_;
MockConnectionAuthenticator mock_connection_authenticator_;
};
TEST_F(PresenceDeviceProviderTest, ProviderIsNotTriviallyConstructible) {
@@ -200,7 +212,7 @@ TEST_F(PresenceDeviceProviderTest,
EXPECT_EQ(AuthenticationStatus::kFailure, status);
}
TEST_F(PresenceDeviceProviderTest, AuthenticateAsInitiator_Success) {
TEST_F(PresenceDeviceProviderTest, AuthenticateAsInitiator_FailureToVerify) {
EXPECT_CALL(mock_service_controller_, GetLocalCredentials)
.WillOnce([&](const CredentialSelector& credential_selector,
GetLocalCredentialsResultCallback callback) {
@@ -208,10 +220,63 @@ TEST_F(PresenceDeviceProviderTest, AuthenticateAsInitiator_Success) {
credentials.push_back(CreateValidLocalCredential(key_pair_));
std::move(callback.credentials_fetched_cb)(credentials);
});
EXPECT_CALL(mock_service_controller_, GetLocalPublicCredentials)
.WillOnce([&](const CredentialSelector& credential_selector,
GetPublicCredentialsResultCallback callback) {
std::vector<nearby::internal::SharedCredential> credentials;
credentials.push_back(BuildSharedCredential(key_pair_));
std::move(callback.credentials_fetched_cb)(credentials);
});
PresenceDevice remote_device(CreateTestMetadata());
remote_device.SetDecryptSharedCredential(BuildSharedCredential(key_pair_));
MockAuthenticationTransport authentication_transport;
EXPECT_CALL(authentication_transport, WriteMessage)
.WillOnce([&](absl::string_view message) {
PresenceAuthenticationFrame authentication_frame;
EXPECT_TRUE(authentication_frame.ParseFromString(message));
EXPECT_EQ(kPresenceVersion, authentication_frame.version());
});
EXPECT_CALL(authentication_transport, ReadMessage).WillOnce([&]() {
PresenceAuthenticationFrame authentication_frame;
return authentication_frame.SerializeAsString();
});
EXPECT_CALL(mock_connection_authenticator_, BuildSignedMessageAsInitiator)
.WillOnce(testing::Return(BuildDefaultInitiatorData()));
EXPECT_CALL(mock_connection_authenticator_, VerifyMessageAsInitiator)
.WillOnce(testing::Return(
absl::Status(absl::StatusCode::kCancelled, /*msg=*/std::string())));
auto status = provider_->AuthenticateAsInitiator(
/*remote_device=*/remote_device, /*shared_secret=*/kUkey2Secret,
/*authentication_transport=*/authentication_transport);
EXPECT_EQ(AuthenticationStatus::kFailure, status);
}
TEST_F(PresenceDeviceProviderTest, AuthenticateAsInitiator_Success) {
EXPECT_CALL(mock_service_controller_, GetLocalCredentials)
.WillOnce([&](const CredentialSelector& credential_selector,
GetLocalCredentialsResultCallback callback) {
std::vector<nearby::internal::LocalCredential> credentials;
credentials.push_back(CreateValidLocalCredential(key_pair_));
std::move(callback.credentials_fetched_cb)(credentials);
});
EXPECT_CALL(mock_service_controller_, GetLocalPublicCredentials)
.WillOnce([&](const CredentialSelector& credential_selector,
GetPublicCredentialsResultCallback callback) {
std::vector<nearby::internal::SharedCredential> credentials;
credentials.push_back(BuildSharedCredential(key_pair_));
std::move(callback.credentials_fetched_cb)(std::move(credentials));
});
PresenceDevice remote_device(CreateTestMetadata());
remote_device.SetDecryptSharedCredential(BuildSharedCredential(key_pair_));
ON_CALL(mock_connection_authenticator_, BuildSignedMessageAsInitiator)
.WillByDefault(testing::Return(BuildDefaultInitiatorData()));
MockAuthenticationTransport authentication_transport;
EXPECT_CALL(authentication_transport, WriteMessage)
.WillOnce([&](absl::string_view message) {
@@ -224,9 +289,6 @@ TEST_F(PresenceDeviceProviderTest, AuthenticateAsInitiator_Success) {
/*remote_device=*/remote_device, /*shared_secret=*/kUkey2Secret,
/*authentication_transport=*/authentication_transport);
// TODO(b/282027237): Once additional logic is added in follow up CL's
// to continue the authentication, add coverage in this unit test for a
// success case.
EXPECT_EQ(AuthenticationStatus::kSuccess, status);
}
+11 -19
View File
@@ -20,41 +20,33 @@
#include "internal/platform/borrowable.h"
#include "presence/data_types.h"
#include "presence/implementation/service_controller_impl.h"
#include "presence/presence_client_impl.h"
#include "presence/presence_device_provider.h"
namespace nearby {
namespace presence {
PresenceServiceImpl::PresenceServiceImpl() {
service_controller_ = std::make_unique<ServiceControllerImpl>(
&executor_, &credential_manager_, &scan_manager_, &broadcast_manager_);
provider_ =
std::make_unique<PresenceDeviceProvider>(service_controller_.get());
}
std::unique_ptr<PresenceClient> PresenceServiceImpl::CreatePresenceClient() {
return PresenceClientImpl::Factory::Create(lender_.GetBorrowable());
}
absl::StatusOr<ScanSessionId> PresenceServiceImpl::StartScan(
ScanRequest scan_request, ScanCallback callback) {
return service_controller_->StartScan(scan_request, std::move(callback));
return service_controller_.StartScan(scan_request, std::move(callback));
}
void PresenceServiceImpl::StopScan(ScanSessionId id) {
service_controller_->StopScan(id);
service_controller_.StopScan(id);
}
absl::StatusOr<BroadcastSessionId> PresenceServiceImpl::StartBroadcast(
BroadcastRequest broadcast_request, BroadcastCallback callback) {
return service_controller_->StartBroadcast(broadcast_request,
std::move(callback));
return service_controller_.StartBroadcast(broadcast_request,
std::move(callback));
}
void PresenceServiceImpl::StopBroadcast(BroadcastSessionId session) {
service_controller_->StopBroadcast(session);
service_controller_.StopBroadcast(session);
}
void PresenceServiceImpl::UpdateLocalDeviceMetadata(
@@ -63,9 +55,9 @@ void PresenceServiceImpl::UpdateLocalDeviceMetadata(
const std::vector<nearby::internal::IdentityType>& identity_types,
int credential_life_cycle_days, int contiguous_copy_of_credentials,
GenerateCredentialsResultCallback credentials_generated_cb) {
provider_->UpdateMetadata(metadata);
provider_->SetManagerAppId(manager_app_id);
service_controller_->UpdateLocalDeviceMetadata(
provider_.UpdateMetadata(metadata);
provider_.SetManagerAppId(manager_app_id);
service_controller_.UpdateLocalDeviceMetadata(
metadata, regen_credentials, manager_app_id, identity_types,
credential_life_cycle_days, contiguous_copy_of_credentials,
std::move(credentials_generated_cb));
@@ -74,15 +66,15 @@ void PresenceServiceImpl::UpdateLocalDeviceMetadata(
void PresenceServiceImpl::GetLocalPublicCredentials(
const CredentialSelector& credential_selector,
GetPublicCredentialsResultCallback callback) {
service_controller_->GetLocalPublicCredentials(credential_selector,
std::move(callback));
service_controller_.GetLocalPublicCredentials(credential_selector,
std::move(callback));
}
void PresenceServiceImpl::UpdateRemotePublicCredentials(
absl::string_view manager_app_id, absl::string_view account_name,
const std::vector<nearby::internal::SharedCredential>& remote_public_creds,
UpdateRemotePublicCredentialsCallback credentials_updated_cb) {
service_controller_->UpdateRemotePublicCredentials(
service_controller_.UpdateRemotePublicCredentials(
manager_app_id, account_name, remote_public_creds,
std::move(credentials_updated_cb));
}
+16 -6
View File
@@ -19,17 +19,24 @@
#include <utility>
#include <vector>
#include "absl/status/statusor.h"
#include "absl/strings/string_view.h"
#include "internal/platform/borrowable.h"
#include "internal/platform/implementation/credential_callbacks.h"
#include "internal/platform/single_thread_executor.h"
#include "internal/proto/metadata.pb.h"
#include "presence/broadcast_request.h"
#include "presence/data_types.h"
#include "presence/implementation/broadcast_manager.h"
#include "presence/implementation/connection_authenticator_impl.h"
#include "presence/implementation/credential_manager_impl.h"
#include "presence/implementation/mediums/mediums.h"
#include "presence/implementation/scan_manager.h"
#include "presence/implementation/service_controller.h"
#include "presence/implementation/service_controller_impl.h"
#include "presence/presence_client.h"
#include "presence/presence_device_provider.h"
#include "presence/presence_service.h"
#include "presence/scan_request.h"
namespace nearby {
namespace presence {
@@ -41,7 +48,7 @@ namespace presence {
*/
class PresenceServiceImpl : public PresenceService {
public:
PresenceServiceImpl();
PresenceServiceImpl() = default;
~PresenceServiceImpl() override { lender_.Release(); }
std::unique_ptr<PresenceClient> CreatePresenceClient() override;
@@ -63,11 +70,11 @@ class PresenceServiceImpl : public PresenceService {
GenerateCredentialsResultCallback credentials_generated_cb) override;
PresenceDeviceProvider* GetLocalDeviceProvider() override {
return provider_.get();
return &provider_;
}
::nearby::internal::Metadata GetLocalDeviceMetadata() override {
return service_controller_->GetLocalDeviceMetadata();
return service_controller_.GetLocalDeviceMetadata();
}
void GetLocalPublicCredentials(
@@ -86,9 +93,12 @@ class PresenceServiceImpl : public PresenceService {
CredentialManagerImpl credential_manager_{&executor_};
ScanManager scan_manager_{mediums_, credential_manager_, executor_};
BroadcastManager broadcast_manager_{mediums_, credential_manager_, executor_};
std::unique_ptr<ServiceController> service_controller_;
ServiceControllerImpl service_controller_{
&executor_, &credential_manager_, &scan_manager_, &broadcast_manager_};
ConnectionAuthenticatorImpl connection_authenticator_;
::nearby::Lender<PresenceService*> lender_{this};
std::unique_ptr<PresenceDeviceProvider> provider_;
PresenceDeviceProvider provider_{&service_controller_,
&connection_authenticator_};
};
} // namespace presence