Commit 7983979c authored by Maksim Moskvitin's avatar Maksim Moskvitin Committed by Chromium LUCI CQ

[TrustedVault] DownloadKeys: handle empty trusted vault key

If device was successfully registered with unknown epoch/trusted vault
key, first DownloadKeys call won't have any key available and incoming
keys validation should be skipped.

Note: strictly speaking, there is a constant key; but performing
validation using it doesn't add any value, while would make future
changes harder.

Bug: 1113598
Change-Id: Ib978987b4ba1304f40c54414ea79ef08d7ebb6ff
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2620262
Commit-Queue: Maksim Moskvitin <mmoskvitin@google.com>
Reviewed-by: default avatarMikel Astiz <mastiz@chromium.org>
Cr-Commit-Position: refs/heads/master@{#842088}
parent abf84916
...@@ -146,7 +146,8 @@ DownloadKeysResponseHandler::ProcessedResponse::operator=( ...@@ -146,7 +146,8 @@ DownloadKeysResponseHandler::ProcessedResponse::operator=(
DownloadKeysResponseHandler::ProcessedResponse::~ProcessedResponse() = default; DownloadKeysResponseHandler::ProcessedResponse::~ProcessedResponse() = default;
DownloadKeysResponseHandler::DownloadKeysResponseHandler( DownloadKeysResponseHandler::DownloadKeysResponseHandler(
const TrustedVaultKeyAndVersion& last_trusted_vault_key_and_version, const base::Optional<TrustedVaultKeyAndVersion>&
last_trusted_vault_key_and_version,
std::unique_ptr<SecureBoxKeyPair> device_key_pair) std::unique_ptr<SecureBoxKeyPair> device_key_pair)
: last_trusted_vault_key_and_version_(last_trusted_vault_key_and_version), : last_trusted_vault_key_and_version_(last_trusted_vault_key_and_version),
device_key_pair_(std::move(device_key_pair)) { device_key_pair_(std::move(device_key_pair)) {
...@@ -186,15 +187,25 @@ DownloadKeysResponseHandler::ProcessResponse( ...@@ -186,15 +187,25 @@ DownloadKeysResponseHandler::ProcessResponse(
std::vector<ExtractedSharedKey> extracted_keys = ExtractAndSortSharedKeys( std::vector<ExtractedSharedKey> extracted_keys = ExtractAndSortSharedKeys(
*current_member, device_key_pair_->private_key()); *current_member, device_key_pair_->private_key());
if (extracted_keys.empty() || if (extracted_keys.empty()) {
!IsValidKeyChain(extracted_keys, last_trusted_vault_key_and_version_)) { // |current_member| doesn't have any keys, should be treated as not
// registered member.
return ProcessedResponse(
/*status=*/TrustedVaultRequestStatus::kLocalDataObsolete);
}
if (last_trusted_vault_key_and_version_.has_value() &&
!IsValidKeyChain(extracted_keys, *last_trusted_vault_key_and_version_)) {
// Data corresponding to |current_member| is corrupted or
// |last_trusted_vault_key_and_version_| is too old.
return ProcessedResponse( return ProcessedResponse(
/*status=*/TrustedVaultRequestStatus::kLocalDataObsolete); /*status=*/TrustedVaultRequestStatus::kLocalDataObsolete);
} }
std::vector<std::vector<uint8_t>> new_keys; std::vector<std::vector<uint8_t>> new_keys;
for (const ExtractedSharedKey& key : extracted_keys) { for (const ExtractedSharedKey& key : extracted_keys) {
if (key.version >= last_trusted_vault_key_and_version_.version) { if (!last_trusted_vault_key_and_version_.has_value() ||
key.version >= last_trusted_vault_key_and_version_->version) {
// Don't include previous keys into the result, because they weren't // Don't include previous keys into the result, because they weren't
// validated using |last_trusted_vault_key_and_version| and client should // validated using |last_trusted_vault_key_and_version| and client should
// be already aware of them. // be already aware of them.
......
...@@ -46,11 +46,12 @@ class DownloadKeysResponseHandler { ...@@ -46,11 +46,12 @@ class DownloadKeysResponseHandler {
int last_key_version; int last_key_version;
}; };
// |device_key_pair| must not be null. This class doesn't make an assumption // |device_key_pair| must not be null. If |last_trusted_vault_key_and_version|
// of |last_trusted_vault_key_and_version.key| being non-empty or // is provided, then it will be verified that the new keys are result of
// |last_trusted_vault_key_version_and_version.version| being non-negative. // rotating the provided key.
DownloadKeysResponseHandler( DownloadKeysResponseHandler(
const TrustedVaultKeyAndVersion& last_trusted_vault_key_and_version, const base::Optional<TrustedVaultKeyAndVersion>&
last_trusted_vault_key_and_version,
std::unique_ptr<SecureBoxKeyPair> device_key_pair); std::unique_ptr<SecureBoxKeyPair> device_key_pair);
DownloadKeysResponseHandler(const DownloadKeysResponseHandler& other) = DownloadKeysResponseHandler(const DownloadKeysResponseHandler& other) =
delete; delete;
...@@ -62,7 +63,8 @@ class DownloadKeysResponseHandler { ...@@ -62,7 +63,8 @@ class DownloadKeysResponseHandler {
const std::string& response_body) const; const std::string& response_body) const;
private: private:
const TrustedVaultKeyAndVersion last_trusted_vault_key_and_version_; const base::Optional<TrustedVaultKeyAndVersion>
last_trusted_vault_key_and_version_;
const std::unique_ptr<SecureBoxKeyPair> device_key_pair_; const std::unique_ptr<SecureBoxKeyPair> device_key_pair_;
}; };
......
...@@ -475,6 +475,30 @@ TEST_F(DownloadKeysResponseHandlerTest, ShouldHandleEmptyMember) { ...@@ -475,6 +475,30 @@ TEST_F(DownloadKeysResponseHandlerTest, ShouldHandleEmptyMember) {
Eq(TrustedVaultRequestStatus::kLocalDataObsolete)); Eq(TrustedVaultRequestStatus::kLocalDataObsolete));
} }
// Test scenario, when no trusted vault keys available on the current device
// (e.g. device was registered with constant key). In this case new keys
// shouldn't be validated.
TEST_F(DownloadKeysResponseHandlerTest, ShouldHandleEmptyLastKnownKey) {
// This test uses custom parameters for the handler ctor, so create new
// handler instead of using one from the fixture.
DownloadKeysResponseHandler handler(base::nullopt, MakeTestKeyPair());
const int kLastKeyVersion = 123;
const DownloadKeysResponseHandler::ProcessedResponse processed_response =
handler.ProcessResponse(
/*http_status=*/TrustedVaultRequest::HttpStatus::kSuccess,
/*response_body=*/
CreateListSecurityDomainsResponseWithSingleSyncMember(
/*trusted_vault_keys=*/{kTrustedVaultKey1},
/*trusted_vault_keys_versions=*/{kLastKeyVersion},
/*signing_keys=*/{{}}));
EXPECT_THAT(processed_response.status,
Eq(TrustedVaultRequestStatus::kSuccess));
EXPECT_THAT(processed_response.keys, ElementsAre(kTrustedVaultKey1));
EXPECT_THAT(processed_response.last_key_version, Eq(kLastKeyVersion));
}
} // namespace } // namespace
} // namespace syncer } // namespace syncer
...@@ -42,14 +42,6 @@ MATCHER_P(KeyMaterialEq, expected, "") { ...@@ -42,14 +42,6 @@ MATCHER_P(KeyMaterialEq, expected, "") {
return key_material_as_bytes == expected; return key_material_as_bytes == expected;
} }
// TODO(crbug.com/1102340): leave only Optional* version of this matcher once
// TrustedVaultConnection::DownloadKeys() accept optional key.
MATCHER_P2(TrustedVaultKeyAndVersionEq, expected_key, expected_version, "") {
const TrustedVaultKeyAndVersion& key_and_version = arg;
return key_and_version.key == expected_key &&
key_and_version.version == expected_version;
}
MATCHER_P2(OptionalTrustedVaultKeyAndVersionEq, MATCHER_P2(OptionalTrustedVaultKeyAndVersionEq,
expected_key, expected_key,
expected_version, expected_version,
...@@ -83,14 +75,14 @@ class MockTrustedVaultConnection : public TrustedVaultConnection { ...@@ -83,14 +75,14 @@ class MockTrustedVaultConnection : public TrustedVaultConnection {
const SecureBoxPublicKey& authentication_factor_public_key, const SecureBoxPublicKey& authentication_factor_public_key,
RegisterAuthenticationFactorCallback callback), RegisterAuthenticationFactorCallback callback),
(override)); (override));
MOCK_METHOD( MOCK_METHOD(std::unique_ptr<Request>,
std::unique_ptr<Request>, DownloadKeys,
DownloadKeys, (const CoreAccountInfo& account_info,
(const CoreAccountInfo& account_info, const base::Optional<TrustedVaultKeyAndVersion>&
const TrustedVaultKeyAndVersion& last_trusted_vault_key_and_version, last_trusted_vault_key_and_version,
std::unique_ptr<SecureBoxKeyPair> device_key_pair, std::unique_ptr<SecureBoxKeyPair> device_key_pair,
DownloadKeysCallback callback), DownloadKeysCallback callback),
(override)); (override));
}; };
class StandaloneTrustedVaultBackendTest : public testing::Test { class StandaloneTrustedVaultBackendTest : public testing::Test {
...@@ -515,10 +507,11 @@ TEST_F(StandaloneTrustedVaultBackendTest, ShouldDownloadKeys) { ...@@ -515,10 +507,11 @@ TEST_F(StandaloneTrustedVaultBackendTest, ShouldDownloadKeys) {
TrustedVaultConnection::DownloadKeysCallback download_keys_callback; TrustedVaultConnection::DownloadKeysCallback download_keys_callback;
EXPECT_CALL(*connection(), EXPECT_CALL(*connection(),
DownloadKeys(Eq(account_info), DownloadKeys(Eq(account_info),
TrustedVaultKeyAndVersionEq(kInitialVaultKey, OptionalTrustedVaultKeyAndVersionEq(
kInitialLastKeyVersion), kInitialVaultKey, kInitialLastKeyVersion),
_, _)) _, _))
.WillOnce([&](const CoreAccountInfo&, const TrustedVaultKeyAndVersion&, .WillOnce([&](const CoreAccountInfo&,
const base::Optional<TrustedVaultKeyAndVersion>&,
std::unique_ptr<SecureBoxKeyPair> key_pair, std::unique_ptr<SecureBoxKeyPair> key_pair,
TrustedVaultConnection::DownloadKeysCallback callback) { TrustedVaultConnection::DownloadKeysCallback callback) {
device_key_pair = std::move(key_pair); device_key_pair = std::move(key_pair);
...@@ -562,7 +555,8 @@ TEST_F(StandaloneTrustedVaultBackendTest, ...@@ -562,7 +555,8 @@ TEST_F(StandaloneTrustedVaultBackendTest,
TrustedVaultConnection::DownloadKeysCallback download_keys_callback; TrustedVaultConnection::DownloadKeysCallback download_keys_callback;
ON_CALL(*connection(), DownloadKeys(_, _, _, _)) ON_CALL(*connection(), DownloadKeys(_, _, _, _))
.WillByDefault( .WillByDefault(
[&](const CoreAccountInfo&, const TrustedVaultKeyAndVersion&, [&](const CoreAccountInfo&,
const base::Optional<TrustedVaultKeyAndVersion>&,
std::unique_ptr<SecureBoxKeyPair> key_pair, std::unique_ptr<SecureBoxKeyPair> key_pair,
TrustedVaultConnection::DownloadKeysCallback callback) { TrustedVaultConnection::DownloadKeysCallback callback) {
download_keys_callback = std::move(callback); download_keys_callback = std::move(callback);
......
...@@ -84,7 +84,8 @@ class TrustedVaultConnection { ...@@ -84,7 +84,8 @@ class TrustedVaultConnection {
// or until request needs to be cancelled. // or until request needs to be cancelled.
virtual std::unique_ptr<Request> DownloadKeys( virtual std::unique_ptr<Request> DownloadKeys(
const CoreAccountInfo& account_info, const CoreAccountInfo& account_info,
const TrustedVaultKeyAndVersion& last_trusted_vault_key_and_version, const base::Optional<TrustedVaultKeyAndVersion>&
last_trusted_vault_key_and_version,
std::unique_ptr<SecureBoxKeyPair> device_key_pair, std::unique_ptr<SecureBoxKeyPair> device_key_pair,
DownloadKeysCallback callback) WARN_UNUSED_RESULT = 0; DownloadKeysCallback callback) WARN_UNUSED_RESULT = 0;
}; };
......
...@@ -78,7 +78,8 @@ TrustedVaultConnectionImpl::RegisterAuthenticationFactor( ...@@ -78,7 +78,8 @@ TrustedVaultConnectionImpl::RegisterAuthenticationFactor(
std::unique_ptr<TrustedVaultConnection::Request> std::unique_ptr<TrustedVaultConnection::Request>
TrustedVaultConnectionImpl::DownloadKeys( TrustedVaultConnectionImpl::DownloadKeys(
const CoreAccountInfo& account_info, const CoreAccountInfo& account_info,
const TrustedVaultKeyAndVersion& last_trusted_vault_key_and_version, const base::Optional<TrustedVaultKeyAndVersion>&
last_trusted_vault_key_and_version,
std::unique_ptr<SecureBoxKeyPair> device_key_pair, std::unique_ptr<SecureBoxKeyPair> device_key_pair,
DownloadKeysCallback callback) { DownloadKeysCallback callback) {
auto request = std::make_unique<TrustedVaultRequest>( auto request = std::make_unique<TrustedVaultRequest>(
......
...@@ -45,7 +45,8 @@ class TrustedVaultConnectionImpl : public TrustedVaultConnection { ...@@ -45,7 +45,8 @@ class TrustedVaultConnectionImpl : public TrustedVaultConnection {
std::unique_ptr<Request> DownloadKeys( std::unique_ptr<Request> DownloadKeys(
const CoreAccountInfo& account_info, const CoreAccountInfo& account_info,
const TrustedVaultKeyAndVersion& last_trusted_vault_key_and_version, const base::Optional<TrustedVaultKeyAndVersion>&
last_trusted_vault_key_and_version,
std::unique_ptr<SecureBoxKeyPair> device_key_pair, std::unique_ptr<SecureBoxKeyPair> device_key_pair,
DownloadKeysCallback callback) override; DownloadKeysCallback callback) override;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment