diff --git a/presence/implementation/BUILD b/presence/implementation/BUILD index 75a624ba..d62eb726 100644 --- a/presence/implementation/BUILD +++ b/presence/implementation/BUILD @@ -96,7 +96,6 @@ cc_library( "//internal/proto:metadata_cc_proto", "//presence:types", "//presence/implementation/mediums", - "//presence/proto:presence_frame_cc_proto", "@com_google_absl//absl/base:core_headers", "@com_google_absl//absl/container:flat_hash_map", "@com_google_absl//absl/container:flat_hash_set", diff --git a/presence/implementation/connection_authenticator.cc b/presence/implementation/connection_authenticator.cc index 5b4b0a4b..3f1e0a7c 100644 --- a/presence/implementation/connection_authenticator.cc +++ b/presence/implementation/connection_authenticator.cc @@ -14,7 +14,9 @@ #include "presence/implementation/connection_authenticator.h" +#include #include +#include #include #include "absl/status/status.h" @@ -26,7 +28,6 @@ #include "internal/crypto/secure_util.h" #include "internal/proto/credential.pb.h" #include "internal/proto/local_credential.pb.h" -#include "presence/proto/presence_frame.pb.h" namespace nearby { namespace presence { @@ -45,70 +46,62 @@ constexpr char kDiscovererHkdfInfo[] = "Nearby Presence Discoverer Credential Hash"; } // namespace -absl::StatusOr ConnectionAuthenticator::BuildSignedMessage( +absl::StatusOr +ConnectionAuthenticator::BuildSignedMessageAsInitiator( absl::string_view ukey2_secret, - const internal::LocalCredential& local_credential, - bool is_initiator) const { + std::optional local_credential, + const internal::SharedCredential& shared_credential) const { + auto shared_credential_hash = crypto::HkdfSha256( + absl::StrCat(ukey2_secret, shared_credential.key_seed()), kHkdfSalt, + kDiscovererHkdfInfo, kPresenceAuthenticatorHkdfKeySize); + if (local_credential.has_value()) { + // two-way authentication, private identity. + auto signer = crypto::Ed25519Signer::Create( + (*local_credential).connection_signing_key().key()); + if (!signer.ok()) { + return signer.status(); + } + auto pkey_signature = + signer->Sign(absl::StrCat(kDiscovererMessageHeader, ukey2_secret)); + if (!pkey_signature.has_value()) { + return absl::InternalError("Signing using private key failed."); + } + return ConnectionAuthenticator::TwoWayInitiatorData{ + .shared_credential_hash = shared_credential_hash, + .private_key_signature = *pkey_signature, + }; + } + // one-way authentication, trusted identity. + return ConnectionAuthenticator::OneWayInitiatorData{ + .shared_credential_hash = shared_credential_hash, + }; +} + +absl::StatusOr +ConnectionAuthenticator::BuildSignedMessageAsResponder( + absl::string_view ukey2_secret, + const internal::LocalCredential& local_credential) const { auto signer = crypto::Ed25519Signer::Create( local_credential.connection_signing_key().key()); if (!signer.ok()) { return signer.status(); } - auto pkey_signature = signer->Sign(absl::StrCat( - is_initiator ? kDiscovererMessageHeader : kBroadcasterMessageHeader, - ukey2_secret)); + auto pkey_signature = + signer->Sign(absl::StrCat(kBroadcasterMessageHeader, ukey2_secret)); if (!pkey_signature.has_value()) { return absl::InternalError("Signing using private key failed."); } - auto credential_id_hash = crypto::HkdfSha256( - absl::StrCat(ukey2_secret, local_credential.key_seed()), kHkdfSalt, - is_initiator ? kDiscovererHkdfInfo : kBroadcasterHkdfInfo, - kPresenceAuthenticatorHkdfKeySize); - PresenceFrame frame; - frame.mutable_v1_frame()->mutable_authentication_frame()->set_version( - kPresenceAuthenticatorVersion); - frame.mutable_v1_frame() - ->mutable_authentication_frame() - ->set_private_key_signature(*pkey_signature); - frame.mutable_v1_frame() - ->mutable_authentication_frame() - ->set_credential_id_hash(credential_id_hash); - return frame.SerializeAsString(); + return ConnectionAuthenticator::ResponderData{.private_key_signature = + *pkey_signature}; } -absl::Status ConnectionAuthenticator::VerifyMessage( - absl::string_view ukey2_secret, absl::string_view received_frame, - const std::vector& shared_credentials, - bool is_initiator) const { - PresenceFrame frame; - frame.ParseFromString(std::string(received_frame)); - if (!frame.has_v1_frame() || !frame.v1_frame().has_authentication_frame()) { - return absl::InvalidArgumentError("No presence authentication frame."); +absl::Status ConnectionAuthenticator::VerifyMessageAsInitiator( + ResponderData authentication_data, absl::string_view ukey2_secret, + const std::vector& shared_credentials) const { + if (authentication_data.private_key_signature.empty()) { + return absl::InvalidArgumentError("Empty private key signature."); } - // Now we know we have an AuthenticationFrame - PresenceAuthenticationFrame auth_frame = - frame.v1_frame().authentication_frame(); - if (auth_frame.version() != kPresenceAuthenticatorVersion) { - return absl::InvalidArgumentError("Presence frame has wrong version."); - } - if (!auth_frame.has_credential_id_hash() || - (auth_frame.credential_id_hash().size() != - kPresenceAuthenticatorHkdfKeySize)) { - return absl::InvalidArgumentError( - "Presence frame missing/has bad cid hash"); - } - // We want to check each shared credential to verify using its public key. for (const auto& shared_credential : shared_credentials) { - // Verify Credential ID hash. - auto cid_hash = crypto::HkdfSha256( - absl::StrCat(ukey2_secret, shared_credential.key_seed()), kHkdfSalt, - is_initiator ? kBroadcasterHkdfInfo : kDiscovererHkdfInfo, - kPresenceAuthenticatorHkdfKeySize); - if (!crypto::SecureMemEqual(cid_hash.c_str(), - auth_frame.credential_id_hash().c_str(), - kPresenceAuthenticatorHkdfKeySize)) { - continue; - } auto verifier = crypto::Ed25519Verifier::Create( shared_credential.connection_signature_verification_key()); if (!verifier.ok()) { @@ -116,15 +109,88 @@ absl::Status ConnectionAuthenticator::VerifyMessage( } // Verify ED25519 signature, returning true if verification succeeded. if (verifier - ->Verify(absl::StrCat(is_initiator ? kBroadcasterMessageHeader - : kDiscovererMessageHeader, - ukey2_secret), - auth_frame.private_key_signature()) + ->Verify(absl::StrCat(kBroadcasterMessageHeader, ukey2_secret), + authentication_data.private_key_signature) .ok()) { return absl::OkStatus(); } } - return absl::InternalError("Unable to verify presence auth message"); + return absl::InternalError("Unable to verify responder's private key sig."); +} + +absl::StatusOr +ConnectionAuthenticator::VerifyMessageAsResponder( + absl::string_view ukey2_secret, InitiatorData initiator_data, + const std::vector& local_credentials, + const std::vector& shared_credentials) const { + std::string shared_credential_hash; + std::optional matched_local_credential; + if (std::holds_alternative(initiator_data)) { + // one-way. we only need to verify if the hash matches one of our + // local credentials. + auto auth_data = std::get(initiator_data); + if (auth_data.shared_credential_hash.size() != + kPresenceAuthenticatorHkdfKeySize) { + return absl::InvalidArgumentError("Invalid shared credential hash size."); + } + for (const auto& local_credential : local_credentials) { + // Verify Credential ID hash. + auto cid_hash = crypto::HkdfSha256( + absl::StrCat(ukey2_secret, local_credential.key_seed()), kHkdfSalt, + kDiscovererHkdfInfo, kPresenceAuthenticatorHkdfKeySize); + if (crypto::SecureMemEqual(cid_hash.c_str(), + auth_data.shared_credential_hash.c_str(), + kPresenceAuthenticatorHkdfKeySize)) { + matched_local_credential = local_credential; + } + } + } else { + // two-way. we need to verify if the hash matches one of our local + // credentials _and_ make sure it matches one of our shared credentials. + // We want to check each shared credential to verify using its public key. + + // Match the local credential. + auto auth_data = std::get(initiator_data); + if (auth_data.shared_credential_hash.size() != + kPresenceAuthenticatorHkdfKeySize) { + return absl::InvalidArgumentError("Invalid shared credential hash size."); + } + if (auth_data.private_key_signature.empty()) { + return absl::InvalidArgumentError("Empty private key signature."); + } + for (const auto& local_credential : local_credentials) { + // Verify Credential ID hash. + auto cid_hash = crypto::HkdfSha256( + absl::StrCat(ukey2_secret, local_credential.key_seed()), kHkdfSalt, + kDiscovererHkdfInfo, kPresenceAuthenticatorHkdfKeySize); + if (crypto::SecureMemEqual(cid_hash.c_str(), + auth_data.shared_credential_hash.c_str(), + kPresenceAuthenticatorHkdfKeySize)) { + matched_local_credential = local_credential; + } + } + // Now, match our shared credential. + std::optional matched_shared_credential; + for (const auto& shared_credential : shared_credentials) { + auto verifier = crypto::Ed25519Verifier::Create( + shared_credential.connection_signature_verification_key()); + if (!verifier.ok() || + verifier + ->Verify(absl::StrCat(kDiscovererMessageHeader, ukey2_secret), + auth_data.private_key_signature) + .ok()) { + matched_shared_credential = shared_credential; + break; + } + } + if (!matched_shared_credential.has_value()) { + return absl::InternalError("Unable to verify shared credential."); + } + } + if (matched_local_credential.has_value()) { + return *matched_local_credential; + } + return absl::InternalError("Unable to verify local credential."); } } // namespace presence diff --git a/presence/implementation/connection_authenticator.h b/presence/implementation/connection_authenticator.h index bf7aea07..0933a966 100644 --- a/presence/implementation/connection_authenticator.h +++ b/presence/implementation/connection_authenticator.h @@ -15,6 +15,7 @@ #ifndef THIRD_PARTY_NEARBY_PRESENCE_IMPLEMENTATION_CONNECTION_AUTHENTICATOR_H_ #define THIRD_PARTY_NEARBY_PRESENCE_IMPLEMENTATION_CONNECTION_AUTHENTICATOR_H_ +#include #include #include @@ -29,29 +30,67 @@ namespace presence { class ConnectionAuthenticator { public: + struct OneWayInitiatorData { + std::string shared_credential_hash; + }; + + struct TwoWayInitiatorData { + std::string shared_credential_hash; + std::string private_key_signature; + }; + + struct ResponderData { + std::string private_key_signature; + }; + + using InitiatorData = absl::variant; + // 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. - // is_initiator - True if the current client is the initiator of the current - // connection (initiates RequestConnection()). - absl::StatusOr BuildSignedMessage( + // 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 BuildSignedMessageAsInitiator( absl::string_view ukey2_secret, - const internal::LocalCredential& local_credential, - bool is_initiator) const; + std::optional local_credential, + const internal::SharedCredential& shared_credential) const; + + // 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 BuildSignedMessageAsResponder( + absl::string_view ukey2_secret, + const internal::LocalCredential& local_credential) const; + + // 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& shared_credentials) const; + // Verifies a signed message received from the Nearby Connections peer. // Returns absl::OkStatus() 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. - // is_initiator - True if the current client is the initiator of the current - // connection (initiates RequestConnection()). - absl::Status VerifyMessage( - absl::string_view ukey2_secret, absl::string_view received_frame, - const std::vector& shared_credentials, - bool is_initiator) const; + absl::StatusOr VerifyMessageAsResponder( + absl::string_view ukey2_secret, InitiatorData initiator_data, + const std::vector& local_credentials, + const std::vector& shared_credentials) const; }; } // namespace presence diff --git a/presence/implementation/connection_authenticator_test.cc b/presence/implementation/connection_authenticator_test.cc index f0f6103f..5e2e042e 100644 --- a/presence/implementation/connection_authenticator_test.cc +++ b/presence/implementation/connection_authenticator_test.cc @@ -23,12 +23,12 @@ #include "internal/crypto/ed25519.h" #include "internal/proto/credential.pb.h" #include "internal/proto/local_credential.pb.h" -#include "presence/proto/presence_frame.pb.h" namespace nearby { namespace presence { namespace { +using ::protobuf_matchers::EqualsProto; using ::testing::status::StatusIs; constexpr char kUkey2Secret[] = {0x34, 0x56, 0x78, 0x90}; @@ -53,257 +53,220 @@ internal::SharedCredential BuildSharedCredential( return shared_credential; } -TEST(PresenceAuthenticatorTest, TestSignHasV1AuthFrame) { - ConnectionAuthenticator authenticator; - auto key_pair_or_status = crypto::Ed25519Signer::CreateNewKeyPair(); - crypto::Ed25519KeyPair key_pair; - ASSERT_OK_AND_ASSIGN(key_pair, key_pair_or_status); - std::string auth_msg; - ASSERT_OK_AND_ASSIGN( - auth_msg, - authenticator.BuildSignedMessage( - kUkey2Secret, BuildLocalCredential(key_pair, kKeySeed1), true)); - PresenceFrame frame; - frame.ParseFromString(auth_msg); - EXPECT_TRUE(frame.has_v1_frame()); - EXPECT_TRUE(frame.v1_frame().has_authentication_frame()); -} +class PresenceAuthenticatorTest : public ::testing::Test { + protected: + void SetUp() override { + auto key_pair_or_status = crypto::Ed25519Signer::CreateNewKeyPair(); + ASSERT_OK_AND_ASSIGN(auto key_pair1, key_pair_or_status); + auto key_pair2_or_status = crypto::Ed25519Signer::CreateNewKeyPair(); + ASSERT_OK_AND_ASSIGN(auto key_pair2, key_pair2_or_status); + initiator_local_credential_ = BuildLocalCredential(key_pair1, kKeySeed1); + initiator_shared_credential_ = BuildSharedCredential(key_pair1, kKeySeed1); + initiator_shared_credential_wrong_key_ = + BuildSharedCredential(key_pair2, kKeySeed1); + responder_local_credential_ = BuildLocalCredential(key_pair2, kKeySeed2); + responder_shared_credential_ = BuildSharedCredential(key_pair2, kKeySeed2); + responder_shared_credential_wrong_key_ = + BuildSharedCredential(key_pair1, kKeySeed2); + } -TEST(PresenceAuthenticatorTest, TestInitiatorSignResponderVerify) { + internal::LocalCredential initiator_local_credential_; + internal::LocalCredential responder_local_credential_; + internal::SharedCredential initiator_shared_credential_; + internal::SharedCredential initiator_shared_credential_wrong_key_; + internal::SharedCredential responder_shared_credential_; + internal::SharedCredential responder_shared_credential_wrong_key_; +}; + +TEST_F(PresenceAuthenticatorTest, TestTwoWayInitiatorSignResponderVerify) { ConnectionAuthenticator responder_authenticator; ConnectionAuthenticator initiator_authenticator; - auto key_pair_or_status = crypto::Ed25519Signer::CreateNewKeyPair(); - crypto::Ed25519KeyPair key_pair; - ASSERT_OK_AND_ASSIGN(key_pair, key_pair_or_status); - std::string auth_msg; - ASSERT_OK_AND_ASSIGN( - auth_msg, - initiator_authenticator.BuildSignedMessage( - kUkey2Secret, BuildLocalCredential(key_pair, kKeySeed1), true)); - EXPECT_OK(responder_authenticator.VerifyMessage( - kUkey2Secret, auth_msg, {BuildSharedCredential(key_pair, kKeySeed1)}, - false)); + ASSERT_OK_AND_ASSIGN(ConnectionAuthenticator::InitiatorData auth_data, + initiator_authenticator.BuildSignedMessageAsInitiator( + kUkey2Secret, initiator_local_credential_, + responder_shared_credential_)); + auto local_credential = responder_authenticator.VerifyMessageAsResponder( + kUkey2Secret, auth_data, {responder_local_credential_}, + {initiator_shared_credential_}); + ASSERT_TRUE(local_credential.ok()); + EXPECT_THAT(*local_credential, EqualsProto(responder_local_credential_)); } -TEST(PresenceAuthenticatorTest, TestResponderSignInitiatorVerify) { +TEST_F(PresenceAuthenticatorTest, TestOneWayInitiatorSignResponderVerify) { ConnectionAuthenticator responder_authenticator; ConnectionAuthenticator initiator_authenticator; - auto key_pair_or_status = crypto::Ed25519Signer::CreateNewKeyPair(); - crypto::Ed25519KeyPair key_pair; - ASSERT_OK_AND_ASSIGN(key_pair, key_pair_or_status); ASSERT_OK_AND_ASSIGN( - std::string auth_msg, - responder_authenticator.BuildSignedMessage( - kUkey2Secret, BuildLocalCredential(key_pair, kKeySeed1), false)); - EXPECT_OK(initiator_authenticator.VerifyMessage( - kUkey2Secret, auth_msg, {BuildSharedCredential(key_pair, kKeySeed1)}, - true)); + ConnectionAuthenticator::InitiatorData auth_data, + initiator_authenticator.BuildSignedMessageAsInitiator( + kUkey2Secret, std::nullopt, responder_shared_credential_)); + auto local_credential = responder_authenticator.VerifyMessageAsResponder( + kUkey2Secret, auth_data, {responder_local_credential_}, + {initiator_shared_credential_}); + ASSERT_TRUE(local_credential.ok()); + EXPECT_THAT(*local_credential, EqualsProto(responder_local_credential_)); } -TEST(PresenceAuthenticatorTest, TestInitiatorSignInitiatorVerifyFails) { - ConnectionAuthenticator initiator_authenticator; - auto key_pair_or_status = crypto::Ed25519Signer::CreateNewKeyPair(); - crypto::Ed25519KeyPair key_pair; - ASSERT_OK_AND_ASSIGN(key_pair, key_pair_or_status); - std::string auth_msg; - ASSERT_OK_AND_ASSIGN( - auth_msg, - initiator_authenticator.BuildSignedMessage( - kUkey2Secret, BuildLocalCredential(key_pair, kKeySeed1), true)); - EXPECT_THAT(initiator_authenticator.VerifyMessage( - kUkey2Secret, auth_msg, - {BuildSharedCredential(key_pair, kKeySeed1)}, true), - StatusIs(absl::StatusCode::kInternal)); -} - -TEST(PresenceAuthenticatorTest, TestResponderSignResponderVerifyFails) { +TEST_F(PresenceAuthenticatorTest, TestResponderSignInitiatorVerify) { ConnectionAuthenticator responder_authenticator; - auto key_pair_or_status = crypto::Ed25519Signer::CreateNewKeyPair(); - crypto::Ed25519KeyPair key_pair; - ASSERT_OK_AND_ASSIGN(key_pair, key_pair_or_status); - std::string auth_msg; - ASSERT_OK_AND_ASSIGN( - auth_msg, - responder_authenticator.BuildSignedMessage( - kUkey2Secret, BuildLocalCredential(key_pair, kKeySeed1), false)); - EXPECT_THAT(responder_authenticator.VerifyMessage( - kUkey2Secret, auth_msg, - {BuildSharedCredential(key_pair, kKeySeed1)}, false), + ConnectionAuthenticator initiator_authenticator; + ASSERT_OK_AND_ASSIGN(ConnectionAuthenticator::ResponderData auth_data, + responder_authenticator.BuildSignedMessageAsResponder( + kUkey2Secret, responder_local_credential_)); + EXPECT_OK(initiator_authenticator.VerifyMessageAsInitiator( + auth_data, kUkey2Secret, {responder_shared_credential_})); +} + +TEST_F(PresenceAuthenticatorTest, + TestTwoWayInitiatorSignResponderVerifyNoSharedCredentialMatchFails) { + ConnectionAuthenticator responder_authenticator; + ConnectionAuthenticator initiator_authenticator; + ASSERT_OK_AND_ASSIGN(ConnectionAuthenticator::InitiatorData auth_data, + initiator_authenticator.BuildSignedMessageAsInitiator( + kUkey2Secret, initiator_local_credential_, + responder_shared_credential_)); + EXPECT_THAT(responder_authenticator.VerifyMessageAsResponder( + kUkey2Secret, auth_data, {}, {initiator_shared_credential_}), StatusIs(absl::StatusCode::kInternal)); } -TEST(PresenceAuthenticatorTest, TestBadKeypairSignVerifyFails) { - ConnectionAuthenticator authenticator; - auto key_pair_or_status = crypto::Ed25519Signer::CreateNewKeyPair(); - crypto::Ed25519KeyPair key_pair; - ASSERT_OK_AND_ASSIGN(key_pair, key_pair_or_status); - auto key_pair_or_status2 = crypto::Ed25519Signer::CreateNewKeyPair(); - crypto::Ed25519KeyPair key_pair2; - ASSERT_OK_AND_ASSIGN(key_pair2, key_pair_or_status2); - std::string auth_msg; +TEST_F(PresenceAuthenticatorTest, + TestOneWayInitiatorSignResponderVerifyNoMatchCredentialFails) { + ConnectionAuthenticator responder_authenticator; + ConnectionAuthenticator initiator_authenticator; ASSERT_OK_AND_ASSIGN( - auth_msg, - authenticator.BuildSignedMessage( - kUkey2Secret, BuildLocalCredential(key_pair, kKeySeed1), true)); - EXPECT_THAT(authenticator.VerifyMessage( - kUkey2Secret, auth_msg, - {BuildSharedCredential(key_pair2, kKeySeed1)}, false), + ConnectionAuthenticator::InitiatorData auth_data, + initiator_authenticator.BuildSignedMessageAsInitiator( + kUkey2Secret, std::nullopt, responder_shared_credential_)); + EXPECT_THAT(responder_authenticator.VerifyMessageAsResponder( + kUkey2Secret, auth_data, {}, {initiator_shared_credential_}), StatusIs(absl::StatusCode::kInternal)); } -TEST(PresenceAuthenticatorTest, TestBadKeyseedSignVerifyFails) { - ConnectionAuthenticator authenticator; - auto key_pair_or_status = crypto::Ed25519Signer::CreateNewKeyPair(); - crypto::Ed25519KeyPair key_pair; - ASSERT_OK_AND_ASSIGN(key_pair, key_pair_or_status); - std::string auth_msg; +TEST_F(PresenceAuthenticatorTest, + TestOneWayInitiatorSignResponderVerifyNoCredentialFails) { + ConnectionAuthenticator responder_authenticator; + ConnectionAuthenticator initiator_authenticator; ASSERT_OK_AND_ASSIGN( - auth_msg, - authenticator.BuildSignedMessage( - kUkey2Secret, BuildLocalCredential(key_pair, kKeySeed1), true)); - EXPECT_THAT(authenticator.VerifyMessage( - kUkey2Secret, auth_msg, - {BuildSharedCredential(key_pair, kKeySeed2)}, false), + ConnectionAuthenticator::InitiatorData auth_data, + initiator_authenticator.BuildSignedMessageAsInitiator( + kUkey2Secret, std::nullopt, responder_shared_credential_)); + EXPECT_THAT(responder_authenticator.VerifyMessageAsResponder( + kUkey2Secret, auth_data, {}, {}), StatusIs(absl::StatusCode::kInternal)); } -TEST(PresenceAuthenticatorTest, TestBadSharedCredentialSignVerifyFails) { - ConnectionAuthenticator authenticator; - auto key_pair_or_status = crypto::Ed25519Signer::CreateNewKeyPair(); - crypto::Ed25519KeyPair key_pair; - ASSERT_OK_AND_ASSIGN(key_pair, key_pair_or_status); - auto key_pair_or_status2 = crypto::Ed25519Signer::CreateNewKeyPair(); - crypto::Ed25519KeyPair key_pair2; - ASSERT_OK_AND_ASSIGN(key_pair2, key_pair_or_status2); - std::string auth_msg; - ASSERT_OK_AND_ASSIGN( - auth_msg, - authenticator.BuildSignedMessage( - kUkey2Secret, BuildLocalCredential(key_pair, kKeySeed1), true)); - EXPECT_THAT(authenticator.VerifyMessage( - kUkey2Secret, auth_msg, - {BuildSharedCredential(key_pair2, kKeySeed2)}, false), +TEST_F(PresenceAuthenticatorTest, + TestTwoWayInitiatorSignResponderVerifyNoMatchCredentialFails) { + ConnectionAuthenticator responder_authenticator; + ConnectionAuthenticator initiator_authenticator; + ASSERT_OK_AND_ASSIGN(ConnectionAuthenticator::InitiatorData auth_data, + initiator_authenticator.BuildSignedMessageAsInitiator( + kUkey2Secret, initiator_local_credential_, + responder_shared_credential_)); + EXPECT_THAT(responder_authenticator.VerifyMessageAsResponder( + kUkey2Secret, auth_data, {}, {initiator_shared_credential_}), StatusIs(absl::StatusCode::kInternal)); } -TEST(PresenceAuthenticatorTest, TestBadPresenceFrameFails) { - ConnectionAuthenticator authenticator; - auto key_pair_or_status = crypto::Ed25519Signer::CreateNewKeyPair(); - crypto::Ed25519KeyPair key_pair; - ASSERT_OK_AND_ASSIGN(key_pair, key_pair_or_status); - std::string auth_msg = "\x34\x45"; - EXPECT_THAT(authenticator.VerifyMessage( - kUkey2Secret, auth_msg, - {BuildSharedCredential(key_pair, kKeySeed1)}, false), +TEST_F(PresenceAuthenticatorTest, + TestTwoWayInitiatorSignResponderVerifyWrongKeyFails) { + ConnectionAuthenticator responder_authenticator; + ConnectionAuthenticator initiator_authenticator; + ASSERT_OK_AND_ASSIGN(ConnectionAuthenticator::InitiatorData auth_data, + initiator_authenticator.BuildSignedMessageAsInitiator( + kUkey2Secret, initiator_local_credential_, + responder_shared_credential_)); + EXPECT_THAT(responder_authenticator.VerifyMessageAsResponder( + kUkey2Secret, auth_data, {responder_local_credential_}, + {initiator_shared_credential_wrong_key_}), + StatusIs(absl::StatusCode::kInternal)); +} + +TEST_F(PresenceAuthenticatorTest, + TestResponderSignInitiatorVerifyNoMatchCredentialFails) { + ConnectionAuthenticator responder_authenticator; + ConnectionAuthenticator initiator_authenticator; + ASSERT_OK_AND_ASSIGN(ConnectionAuthenticator::ResponderData auth_data, + responder_authenticator.BuildSignedMessageAsResponder( + kUkey2Secret, responder_local_credential_)); + EXPECT_THAT(initiator_authenticator.VerifyMessageAsInitiator( + auth_data, kUkey2Secret, {}), + StatusIs(absl::StatusCode::kInternal)); +} + +TEST_F(PresenceAuthenticatorTest, + TestResponderSignInitiatorVerifyWrongKeyFails) { + ConnectionAuthenticator responder_authenticator; + ConnectionAuthenticator initiator_authenticator; + ASSERT_OK_AND_ASSIGN(ConnectionAuthenticator::ResponderData auth_data, + responder_authenticator.BuildSignedMessageAsResponder( + kUkey2Secret, responder_local_credential_)); + EXPECT_THAT( + initiator_authenticator.VerifyMessageAsInitiator( + auth_data, kUkey2Secret, {responder_shared_credential_wrong_key_}), + StatusIs(absl::StatusCode::kInternal)); +} + +TEST_F(PresenceAuthenticatorTest, + TestTwoWayInitiatorSignResponderVerifyNoCidHashFails) { + ConnectionAuthenticator responder_authenticator; + ConnectionAuthenticator initiator_authenticator; + ASSERT_OK_AND_ASSIGN(ConnectionAuthenticator::InitiatorData auth_data, + initiator_authenticator.BuildSignedMessageAsInitiator( + kUkey2Secret, initiator_local_credential_, + responder_shared_credential_)); + std::get(auth_data) + .shared_credential_hash.clear(); + EXPECT_THAT(responder_authenticator.VerifyMessageAsResponder( + kUkey2Secret, auth_data, {responder_local_credential_}, + {initiator_shared_credential_wrong_key_}), StatusIs(absl::StatusCode::kInvalidArgument)); } -TEST(PresenceAuthenticatorTest, TestNoV1FrameFails) { - PresenceFrame frame; - ASSERT_FALSE(frame.has_v1_frame()); - ConnectionAuthenticator authenticator; - auto key_pair_or_status = crypto::Ed25519Signer::CreateNewKeyPair(); - crypto::Ed25519KeyPair key_pair; - ASSERT_OK_AND_ASSIGN(key_pair, key_pair_or_status); - EXPECT_THAT(authenticator.VerifyMessage( - kUkey2Secret, frame.SerializeAsString(), - {BuildSharedCredential(key_pair, kKeySeed1)}, false), +TEST_F(PresenceAuthenticatorTest, + TestTwoWayInitiatorSignResponderVerifyNoPkeySigFails) { + ConnectionAuthenticator responder_authenticator; + ConnectionAuthenticator initiator_authenticator; + ASSERT_OK_AND_ASSIGN(ConnectionAuthenticator::InitiatorData auth_data, + initiator_authenticator.BuildSignedMessageAsInitiator( + kUkey2Secret, initiator_local_credential_, + responder_shared_credential_)); + std::get(auth_data) + .private_key_signature.clear(); + EXPECT_THAT(responder_authenticator.VerifyMessageAsResponder( + kUkey2Secret, auth_data, {responder_local_credential_}, + {initiator_shared_credential_wrong_key_}), StatusIs(absl::StatusCode::kInvalidArgument)); } -TEST(PresenceAuthenticatorTest, TestNoAuthFrameFails) { - PresenceFrame frame; - frame.mutable_v1_frame()->clear_authentication_frame(); - ASSERT_TRUE(frame.has_v1_frame()); - ASSERT_FALSE(frame.v1_frame().has_authentication_frame()); - ConnectionAuthenticator authenticator; - auto key_pair_or_status = crypto::Ed25519Signer::CreateNewKeyPair(); - crypto::Ed25519KeyPair key_pair; - ASSERT_OK_AND_ASSIGN(key_pair, key_pair_or_status); - EXPECT_THAT(authenticator.VerifyMessage( - kUkey2Secret, frame.SerializeAsString(), - {BuildSharedCredential(key_pair, kKeySeed1)}, false), +TEST_F(PresenceAuthenticatorTest, + TestOneWayInitiatorSignResponderVerifyNoCidHashFails) { + ConnectionAuthenticator responder_authenticator; + ConnectionAuthenticator initiator_authenticator; + ASSERT_OK_AND_ASSIGN( + ConnectionAuthenticator::InitiatorData auth_data, + initiator_authenticator.BuildSignedMessageAsInitiator( + kUkey2Secret, std::nullopt, responder_shared_credential_)); + std::get(auth_data) + .shared_credential_hash.clear(); + EXPECT_THAT(responder_authenticator.VerifyMessageAsResponder( + kUkey2Secret, auth_data, {responder_local_credential_}, + {initiator_shared_credential_}), StatusIs(absl::StatusCode::kInvalidArgument)); } -TEST(PresenceAuthenticatorTest, TestBadVersionFails) { - ConnectionAuthenticator authenticator; - auto key_pair_or_status = crypto::Ed25519Signer::CreateNewKeyPair(); - crypto::Ed25519KeyPair key_pair; - ASSERT_OK_AND_ASSIGN(key_pair, key_pair_or_status); - std::string auth_msg; - ASSERT_OK_AND_ASSIGN( - auth_msg, - authenticator.BuildSignedMessage( - kUkey2Secret, BuildLocalCredential(key_pair, kKeySeed1), true)); - PresenceFrame frame; - frame.ParseFromString(auth_msg); - frame.mutable_v1_frame()->mutable_authentication_frame()->set_version(2); - EXPECT_THAT(authenticator.VerifyMessage( - kUkey2Secret, frame.SerializeAsString(), - {BuildSharedCredential(key_pair, kKeySeed1)}, false), +TEST_F(PresenceAuthenticatorTest, + TestResponderSignInitiatorVerifyNoPkeySigFail) { + ConnectionAuthenticator responder_authenticator; + ConnectionAuthenticator initiator_authenticator; + ASSERT_OK_AND_ASSIGN(ConnectionAuthenticator::ResponderData auth_data, + responder_authenticator.BuildSignedMessageAsResponder( + kUkey2Secret, responder_local_credential_)); + auth_data.private_key_signature.clear(); + EXPECT_THAT(initiator_authenticator.VerifyMessageAsInitiator( + auth_data, kUkey2Secret, {responder_shared_credential_}), StatusIs(absl::StatusCode::kInvalidArgument)); } - -TEST(PresenceAuthenticatorTest, TestMissingCredentialIdHashFails) { - ConnectionAuthenticator authenticator; - auto key_pair_or_status = crypto::Ed25519Signer::CreateNewKeyPair(); - crypto::Ed25519KeyPair key_pair; - ASSERT_OK_AND_ASSIGN(key_pair, key_pair_or_status); - std::string auth_msg; - ASSERT_OK_AND_ASSIGN( - auth_msg, - authenticator.BuildSignedMessage( - kUkey2Secret, BuildLocalCredential(key_pair, kKeySeed1), true)); - PresenceFrame frame; - frame.ParseFromString(auth_msg); - frame.mutable_v1_frame() - ->mutable_authentication_frame() - ->clear_credential_id_hash(); - EXPECT_THAT(authenticator.VerifyMessage( - kUkey2Secret, frame.SerializeAsString(), - {BuildSharedCredential(key_pair, kKeySeed1)}, false), - StatusIs(absl::StatusCode::kInvalidArgument)); -} - -TEST(PresenceAuthenticatorTest, TestMissingPrivateKeySignatureFails) { - ConnectionAuthenticator authenticator; - auto key_pair_or_status = crypto::Ed25519Signer::CreateNewKeyPair(); - crypto::Ed25519KeyPair key_pair; - ASSERT_OK_AND_ASSIGN(key_pair, key_pair_or_status); - std::string auth_msg; - ASSERT_OK_AND_ASSIGN( - auth_msg, - authenticator.BuildSignedMessage( - kUkey2Secret, BuildLocalCredential(key_pair, kKeySeed1), true)); - PresenceFrame frame; - frame.ParseFromString(auth_msg); - frame.mutable_v1_frame() - ->mutable_authentication_frame() - ->clear_private_key_signature(); - EXPECT_THAT(authenticator.VerifyMessage( - kUkey2Secret, frame.SerializeAsString(), - {BuildSharedCredential(key_pair, kKeySeed1)}, false), - StatusIs(absl::StatusCode::kInternal)); -} - -TEST(PresenceAuthenticatorTest, TestMissingPublicKeyVerifyFails) { - ConnectionAuthenticator authenticator; - auto key_pair_or_status = crypto::Ed25519Signer::CreateNewKeyPair(); - crypto::Ed25519KeyPair key_pair; - ASSERT_OK_AND_ASSIGN(key_pair, key_pair_or_status); - std::string auth_msg; - ASSERT_OK_AND_ASSIGN( - auth_msg, - authenticator.BuildSignedMessage( - kUkey2Secret, BuildLocalCredential(key_pair, kKeySeed1), true)); - key_pair.public_key.clear(); - EXPECT_THAT(authenticator.VerifyMessage( - kUkey2Secret, auth_msg, - {BuildSharedCredential(key_pair, kKeySeed1)}, true), - StatusIs(absl::StatusCode::kInternal)); -} - } // namespace } // namespace presence } // namespace nearby