Skip to content

Commit

Permalink
[Sync] Share helpers for explicit passphrase mojo between Ash and Lacros
Browse files Browse the repository at this point in the history
This CL intoduces "chromeos" subfolder under components/sync, moves
there functions for conversions between Nigori and its mojo
representation, that used to be duplicated in Ash and Lacros, and adds
test coverage for them.

Bug: 1233545
Change-Id: I4174ed10b0e07090d8567b6727fc06b72a995ed9
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/3568461
Reviewed-by: Marc Treib <treib@chromium.org>
Reviewed-by: Hidehiko Abe <hidehiko@chromium.org>
Commit-Queue: Maksim Moskvitin <mmoskvitin@google.com>
Cr-Commit-Position: refs/heads/main@{#989467}
  • Loading branch information
Maksim Moskvitin authored and Chromium LUCI CQ committed Apr 6, 2022
1 parent 8dfcc68 commit ad2943a
Show file tree
Hide file tree
Showing 12 changed files with 163 additions and 76 deletions.
34 changes: 4 additions & 30 deletions chrome/browser/ash/sync/sync_explicit_passphrase_client_ash.cc
Expand Up @@ -12,6 +12,7 @@
#include "components/account_manager_core/account.h"
#include "components/account_manager_core/account_manager_util.h"
#include "components/signin/public/identity_manager/account_info.h"
#include "components/sync/chromeos/explicit_passphrase_mojo_utils.h"
#include "components/sync/driver/sync_user_settings.h"
#include "components/sync/engine/nigori/nigori.h"
#include "third_party/abseil-cpp/absl/types/optional.h"
Expand All @@ -20,41 +21,13 @@ namespace ash {

namespace {

crosapi::mojom::NigoriKeyPtr NigoriToMojo(const syncer::Nigori& nigori) {
std::string deprecated_user_key;
std::string encryption_key;
std::string mac_key;
nigori.ExportKeys(&deprecated_user_key, &encryption_key, &mac_key);

crosapi::mojom::NigoriKeyPtr mojo_result = crosapi::mojom::NigoriKey::New();
mojo_result->encryption_key =
std::vector<uint8_t>(encryption_key.begin(), encryption_key.end());
mojo_result->mac_key = std::vector<uint8_t>(mac_key.begin(), mac_key.end());
return mojo_result;
}

std::unique_ptr<syncer::Nigori> NigoriFromMojo(
const crosapi::mojom::NigoriKey& mojo_key) {
const std::string encryption_key(mojo_key.encryption_key.begin(),
mojo_key.encryption_key.end());
const std::string mac_key(mojo_key.mac_key.begin(), mojo_key.mac_key.end());
// |user_key| is deprecated, it's safe to pass empty string.
return syncer::Nigori::CreateByImport(
/*user_key=*/std::string(), encryption_key, mac_key);
}

bool IsPassphraseAvailable(const syncer::SyncService& sync_service) {
return sync_service.GetUserSettings()->IsUsingExplicitPassphrase() &&
!sync_service.GetUserSettings()->IsPassphraseRequired();
}

} // namespace

crosapi::mojom::NigoriKeyPtr NigoriToMojoForTesting( // IN-TEST
const syncer::Nigori& nigori) {
return NigoriToMojo(nigori);
}

SyncExplicitPassphraseClientAsh::SyncExplicitPassphraseClientAsh(
syncer::SyncService* sync_service)
: sync_service_(sync_service),
Expand Down Expand Up @@ -104,7 +77,7 @@ void SyncExplicitPassphraseClientAsh::GetDecryptionNigoriKey(
return;
}

std::move(callback).Run(NigoriToMojo(*decryption_key));
std::move(callback).Run(syncer::NigoriToMojo(*decryption_key));
}

void SyncExplicitPassphraseClientAsh::SetDecryptionNigoriKey(
Expand All @@ -114,7 +87,8 @@ void SyncExplicitPassphraseClientAsh::SetDecryptionNigoriKey(
return;
}

std::unique_ptr<syncer::Nigori> nigori_key = NigoriFromMojo(*mojo_nigori_key);
std::unique_ptr<syncer::Nigori> nigori_key =
syncer::NigoriFromMojo(*mojo_nigori_key);
if (!nigori_key) {
// Deserialization failed, |mojo_nigori_key| doesn't represent an actual
// Nigori key.
Expand Down
7 changes: 0 additions & 7 deletions chrome/browser/ash/sync/sync_explicit_passphrase_client_ash.h
Expand Up @@ -14,10 +14,6 @@
#include "mojo/public/cpp/bindings/receiver_set.h"
#include "mojo/public/cpp/bindings/remote_set.h"

namespace syncer {
class Nigori;
}

namespace ash {

class SyncExplicitPassphraseClientAsh
Expand Down Expand Up @@ -69,9 +65,6 @@ class SyncExplicitPassphraseClientAsh
observers_;
};

crosapi::mojom::NigoriKeyPtr NigoriToMojoForTesting(
const syncer::Nigori& nigori);

} // namespace ash

#endif // CHROME_BROWSER_ASH_SYNC_SYNC_EXPLICIT_PASSPHRASE_CLIENT_ASH_H_
Expand Up @@ -6,6 +6,7 @@

#include "base/test/task_environment.h"
#include "chromeos/crosapi/mojom/sync.mojom-test-utils.h"
#include "components/sync/chromeos/explicit_passphrase_mojo_utils.h"
#include "components/sync/driver/mock_sync_service.h"
#include "components/sync/driver/sync_user_settings_mock.h"
#include "components/sync/engine/nigori/key_derivation_params.h"
Expand All @@ -28,7 +29,7 @@ std::unique_ptr<syncer::Nigori> MakeTestNigoriKey() {

crosapi::mojom::NigoriKeyPtr MakeTestMojoNigoriKey() {
std::unique_ptr<syncer::Nigori> nigori_key = MakeTestNigoriKey();
return NigoriToMojoForTesting(*nigori_key);
return syncer::NigoriToMojo(*nigori_key);
}

class TestSyncExplicitPassphraseClientObserver
Expand Down
Expand Up @@ -9,56 +9,28 @@
#include "components/account_manager_core/account.h"
#include "components/account_manager_core/account_manager_util.h"
#include "components/signin/public/identity_manager/account_info.h"
#include "components/sync/chromeos/explicit_passphrase_mojo_utils.h"
#include "components/sync/driver/sync_service.h"
#include "components/sync/driver/sync_user_settings.h"
#include "components/sync/engine/nigori/nigori.h"

namespace {

// TODO(crbug.com/1233545): Move common parts of Ash and Lacros implementation
// somewhere under components/ and reuse them (mojo utils, test helpers, maybe
// observer of the sync service).
crosapi::mojom::AccountKeyPtr GetMojoAccountKey(
const syncer::SyncService& sync_service) {
return account_manager::ToMojoAccountKey(account_manager::AccountKey(
sync_service.GetAccountInfo().gaia, account_manager::AccountType::kGaia));
}

crosapi::mojom::NigoriKeyPtr NigoriToMojo(const syncer::Nigori& nigori) {
std::string deprecated_user_key;
std::string encryption_key;
std::string mac_key;
nigori.ExportKeys(&deprecated_user_key, &encryption_key, &mac_key);

crosapi::mojom::NigoriKeyPtr mojo_result = crosapi::mojom::NigoriKey::New();
mojo_result->encryption_key =
std::vector<uint8_t>(encryption_key.begin(), encryption_key.end());
mojo_result->mac_key = std::vector<uint8_t>(mac_key.begin(), mac_key.end());
return mojo_result;
}

std::unique_ptr<syncer::Nigori> NigoriFromMojo(
const crosapi::mojom::NigoriKey& mojo_key) {
const std::string encryption_key(mojo_key.encryption_key.begin(),
mojo_key.encryption_key.end());
const std::string mac_key(mojo_key.mac_key.begin(), mojo_key.mac_key.end());
// |user_key| is deprecated, it's safe to pass empty string.
return syncer::Nigori::CreateByImport(
/*user_key=*/std::string(), encryption_key, mac_key);
}

bool IsPassphraseAvailable(const syncer::SyncService& sync_service) {
return sync_service.GetUserSettings()->IsUsingExplicitPassphrase() &&
!sync_service.GetUserSettings()->IsPassphraseRequired();
}

} // namespace

crosapi::mojom::NigoriKeyPtr NigoriToMojoForTesting( // IN-TEST
const syncer::Nigori& nigori) {
return NigoriToMojo(nigori);
}

// TODO(crbug.com/1233545): Consider sharing sync service observer logic between
// Ash and Lacros.
SyncExplicitPassphraseClientLacros::LacrosSyncServiceObserver::
LacrosSyncServiceObserver(
syncer::SyncService* sync_service,
Expand Down Expand Up @@ -208,7 +180,7 @@ void SyncExplicitPassphraseClientLacros::SendDecryptionKeyToAsh() {
return;
}
remote_->SetDecryptionNigoriKey(GetMojoAccountKey(*sync_service_),
NigoriToMojo(*decryption_key));
syncer::NigoriToMojo(*decryption_key));
}

void SyncExplicitPassphraseClientLacros::OnQueryDecryptionKeyFromAshCompleted(
Expand All @@ -218,7 +190,8 @@ void SyncExplicitPassphraseClientLacros::OnQueryDecryptionKeyFromAshCompleted(
return;
}

std::unique_ptr<syncer::Nigori> nigori_key = NigoriFromMojo(*mojo_nigori_key);
std::unique_ptr<syncer::Nigori> nigori_key =
syncer::NigoriFromMojo(*mojo_nigori_key);
if (!nigori_key) {
// Deserialization failed, |mojo_nigori_key| doesn't represent an actual
// Nigori key.
Expand Down
Expand Up @@ -14,7 +14,6 @@
#include "mojo/public/cpp/bindings/remote.h"

namespace syncer {
class Nigori;
class SyncService;
} // namespace syncer

Expand Down Expand Up @@ -113,7 +112,4 @@ class SyncExplicitPassphraseClientLacros {
mojo::Remote<crosapi::mojom::SyncExplicitPassphraseClient> remote_;
};

crosapi::mojom::NigoriKeyPtr NigoriToMojoForTesting(
const syncer::Nigori& nigori);

#endif // CHROME_BROWSER_LACROS_SYNC_SYNC_EXPLICIT_PASSPHRASE_CLIENT_LACROS_H_
Expand Up @@ -10,6 +10,7 @@
#include "components/account_manager_core/account.h"
#include "components/account_manager_core/account_manager_util.h"
#include "components/signin/public/identity_manager/account_info.h"
#include "components/sync/chromeos/explicit_passphrase_mojo_utils.h"
#include "components/sync/driver/mock_sync_service.h"
#include "components/sync/driver/sync_service_observer.h"
#include "components/sync/driver/sync_user_settings_mock.h"
Expand All @@ -33,7 +34,7 @@ std::unique_ptr<syncer::Nigori> MakeTestNigoriKey() {

crosapi::mojom::NigoriKeyPtr MakeTestMojoNigoriKey() {
std::unique_ptr<syncer::Nigori> nigori_key = MakeTestNigoriKey();
return NigoriToMojoForTesting(*nigori_key);
return syncer::NigoriToMojo(*nigori_key);
}

crosapi::mojom::AccountKeyPtr MakeMojoAccountKey(
Expand Down
7 changes: 7 additions & 0 deletions components/sync/BUILD.gn
Expand Up @@ -16,6 +16,9 @@ group("sync") {
if (!is_android) {
public_deps += [ "//components/sync/trusted_vault" ]
}
if (is_chromeos) {
public_deps += [ "//components/sync/chromeos" ]
}
}

group("test_support") {
Expand Down Expand Up @@ -219,6 +222,10 @@ source_set("unit_tests") {
]
}

if (is_chromeos) {
sources += [ "chromeos/explicit_passphrase_mojo_utils_unittest.cc" ]
}

configs += [ "//build/config:precompiled_headers" ]

data = [
Expand Down
12 changes: 12 additions & 0 deletions components/sync/chromeos/BUILD.gn
@@ -0,0 +1,12 @@
# Copyright 2022 The Chromium Authors. All rights reserved.
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.

static_library("chromeos") {
sources = [
"explicit_passphrase_mojo_utils.cc",
"explicit_passphrase_mojo_utils.h",
]
public_deps = [ "//chromeos/crosapi/mojom" ]
deps = [ "//components/sync/engine" ]
}
4 changes: 4 additions & 0 deletions components/sync/chromeos/DEPS
@@ -0,0 +1,4 @@
include_rules = [
"+chromeos/crosapi/mojom",
"+components/sync/engine",
]
38 changes: 38 additions & 0 deletions components/sync/chromeos/explicit_passphrase_mojo_utils.cc
@@ -0,0 +1,38 @@
// Copyright 2022 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "components/sync/chromeos/explicit_passphrase_mojo_utils.h"

#include <string>
#include <vector>

#include "components/sync/engine/nigori/nigori.h"

namespace syncer {

crosapi::mojom::NigoriKeyPtr NigoriToMojo(const Nigori& nigori) {
std::string deprecated_user_key;
std::string encryption_key;
std::string mac_key;
nigori.ExportKeys(&deprecated_user_key, &encryption_key, &mac_key);

crosapi::mojom::NigoriKeyPtr mojo_result = crosapi::mojom::NigoriKey::New();
mojo_result->encryption_key =
std::vector<uint8_t>(encryption_key.begin(), encryption_key.end());
mojo_result->mac_key = std::vector<uint8_t>(mac_key.begin(), mac_key.end());
return mojo_result;
}

std::unique_ptr<Nigori> NigoriFromMojo(
const crosapi::mojom::NigoriKey& mojo_nigori_key) {
const std::string encryption_key(mojo_nigori_key.encryption_key.begin(),
mojo_nigori_key.encryption_key.end());
const std::string mac_key(mojo_nigori_key.mac_key.begin(),
mojo_nigori_key.mac_key.end());
// |user_key| is deprecated, it's safe to pass empty string.
return Nigori::CreateByImport(
/*user_key=*/std::string(), encryption_key, mac_key);
}

} // namespace syncer
26 changes: 26 additions & 0 deletions components/sync/chromeos/explicit_passphrase_mojo_utils.h
@@ -0,0 +1,26 @@
// Copyright 2022 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#ifndef COMPONENTS_SYNC_CHROMEOS_EXPLICIT_PASSPHRASE_MOJO_UTILS_H_
#define COMPONENTS_SYNC_CHROMEOS_EXPLICIT_PASSPHRASE_MOJO_UTILS_H_

#include <memory>

#include "chromeos/crosapi/mojom/sync.mojom.h"

namespace syncer {

class Nigori;

// Converts |nigori| into its mojo representation.
crosapi::mojom::NigoriKeyPtr NigoriToMojo(const Nigori& nigori);

// Creates Nigori from its mojo representation. Returns nullptr if
// |mojo_nigori_key| doesn't represent a valid Nigori.
std::unique_ptr<Nigori> NigoriFromMojo(
const crosapi::mojom::NigoriKey& mojo_nigori_key);

} // namespace syncer

#endif // COMPONENTS_SYNC_CHROMEOS_EXPLICIT_PASSPHRASE_MOJO_UTILS_H_
@@ -0,0 +1,62 @@
// Copyright 2022 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "components/sync/chromeos/explicit_passphrase_mojo_utils.h"

#include <string>

#include "chromeos/crosapi/mojom/sync.mojom.h"
#include "components/sync/engine/nigori/key_derivation_params.h"
#include "components/sync/engine/nigori/nigori.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"

namespace syncer {

namespace {

using testing::Eq;
using testing::IsNull;
using testing::NotNull;

TEST(ExplicitPassphraseMojoUtilsTest, ShouldConvertNigoriToMojoAndBack) {
auto nigori1 = Nigori::CreateByDerivation(
KeyDerivationParams::CreateForPbkdf2(), "password");
ASSERT_THAT(nigori1, NotNull());

auto mojo_nigori_key = NigoriToMojo(*nigori1);
ASSERT_FALSE(mojo_nigori_key.is_null());

auto nigori2 = NigoriFromMojo(*mojo_nigori_key);
ASSERT_THAT(nigori2, NotNull());

std::string deprecated_user_key1;
std::string encryption_key1;
std::string mac_key1;
nigori1->ExportKeys(&deprecated_user_key1, &encryption_key1, &mac_key1);

std::string deprecated_user_key2;
std::string encryption_key2;
std::string mac_key2;
nigori2->ExportKeys(&deprecated_user_key2, &encryption_key2, &mac_key2);
// Don't check user key, because it's deprecated and safe to ignore.
EXPECT_THAT(encryption_key1, Eq(encryption_key2));
EXPECT_THAT(mac_key1, Eq(mac_key2));
}

TEST(ExplicitPassphraseMojoUtilsTest, ShouldFailMojoToNigoriIfMojoEmpty) {
auto empty_mojo_nigori_key = crosapi::mojom::NigoriKey::New();
EXPECT_THAT(NigoriFromMojo(*empty_mojo_nigori_key), IsNull());
}

TEST(ExplicitPassphraseMojoUtilsTest, ShouldFailMojoToNigoriIfMojoNotValid) {
auto invalid_mojo_nigori_key = crosapi::mojom::NigoriKey::New();
invalid_mojo_nigori_key->encryption_key = {1, 2, 3};
invalid_mojo_nigori_key->mac_key = {1, 2, 3};
EXPECT_THAT(NigoriFromMojo(*invalid_mojo_nigori_key), IsNull());
}

} // namespace

} // namespace syncer

0 comments on commit ad2943a

Please sign in to comment.