Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(49)

Unified Diff: chrome/browser/sync/syncable/nigori_util.cc

Issue 6465005: [Sync] Initial support for encrypting any datatype (no UI hookup yet). (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Self review Created 9 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: chrome/browser/sync/syncable/nigori_util.cc
diff --git a/chrome/browser/sync/syncable/nigori_util.cc b/chrome/browser/sync/syncable/nigori_util.cc
new file mode 100644
index 0000000000000000000000000000000000000000..308d7bf5e6fed841f55026a24bf9138685672302
--- /dev/null
+++ b/chrome/browser/sync/syncable/nigori_util.cc
@@ -0,0 +1,170 @@
+// Copyright (c) 2011 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 "chrome/browser/sync/syncable/nigori_util.h"
+
+#include <queue>
+#include <vector>
+
+#include "chrome/browser/sync/engine/syncer_util.h"
+#include "chrome/browser/sync/syncable/syncable.h"
+#include "chrome/browser/sync/util/cryptographer.h"
+
+namespace syncable {
+
+ModelTypeSet GetEncryptedDatatypesFromNigori(
+ const sync_pb::NigoriSpecifics& nigori) {
+ // We don't check NIGORI and PASSWORDS datatypes, they use their own
+ // encryption scheme.
+ ModelTypeSet encrypted_types;
+ if(nigori.encrypt_bookmarks())
+ encrypted_types.insert(BOOKMARKS);
+ if(nigori.encrypt_preferences())
+ encrypted_types.insert(PREFERENCES);
+ if(nigori.encrypt_passwords())
+ encrypted_types.insert(PASSWORDS);
+ if(nigori.encrypt_autofill_profile())
+ encrypted_types.insert(AUTOFILL_PROFILE);
+ if(nigori.encrypt_autofill())
+ encrypted_types.insert(AUTOFILL);
+ if(nigori.encrypt_themes())
+ encrypted_types.insert(THEMES);
+ if(nigori.encrypt_typed_urls())
+ encrypted_types.insert(TYPED_URLS);
+ if(nigori.encrypt_extensions())
+ encrypted_types.insert(EXTENSIONS);
+ if(nigori.encrypt_sessions())
+ encrypted_types.insert(SESSIONS);
+ if(nigori.encrypt_apps())
+ encrypted_types.insert(APPS);
+ return encrypted_types;
+}
+
+void FillNigoriEncryptedTypes(const ModelTypeSet& types,
+ sync_pb::NigoriSpecifics* nigori) {
+ DCHECK(nigori);
+ nigori->set_encrypt_bookmarks(types.count(BOOKMARKS) > 0);
+ nigori->set_encrypt_preferences(types.count(PREFERENCES) > 0);
+ nigori->set_encrypt_passwords(types.count(PASSWORDS) > 0);
+ nigori->set_encrypt_autofill_profile(types.count(AUTOFILL_PROFILE) > 0);
+ nigori->set_encrypt_autofill(types.count(AUTOFILL) > 0);
+ nigori->set_encrypt_themes(types.count(THEMES) > 0);
+ nigori->set_encrypt_typed_urls(types.count(TYPED_URLS) > 0);
+ nigori->set_encrypt_extensions(types.count(EXTENSIONS) > 0);
+ nigori->set_encrypt_sessions(types.count(SESSIONS) > 0);
+ nigori->set_encrypt_apps(types.count(APPS) > 0);
+}
+
+bool ProcessUnsyncedChangesForEncryption(
+ WriteTransaction* const trans,
+ const ModelTypeSet& encrypted_types,
+ browser_sync::Cryptographer* cryptographer) {
+ // Get list of all datatypes with unsynced changes. It's possible that our
+ // local changes need to be encrypted if encryption for that datatype was
+ // just turned on (and vice versa). This should never affect passwords.
+ std::vector<int64> handles;
+ browser_sync::SyncerUtil::GetUnsyncedEntries(trans, &handles);
+ for (size_t i = 0; i < handles.size(); ++i) {
+ MutableEntry entry(trans, GET_BY_HANDLE, handles[i]);
+ sync_pb::EntitySpecifics new_specifics;
+ const sync_pb::EntitySpecifics& entry_specifics = entry.Get(SPECIFICS);
+ ModelType type = entry.GetModelType();
+ if (type == PASSWORDS)
+ continue;
+ if (encrypted_types.count(type) > 0 &&
+ !entry_specifics.has_encrypted()) {
+ // This entry now requires encryption.
+ AddDefaultExtensionValue(type, &new_specifics);
+ if (!cryptographer->Encrypt(
+ entry_specifics,
+ new_specifics.mutable_encrypted())) {
+ LOG(ERROR) << "Could not encrypt data for newly encrypted type " <<
+ ModelTypeToString(type);
+ NOTREACHED();
+ return false;
+ } else {
+ VLOG(1) << "Encrypted change for newly encrypted type " <<
+ ModelTypeToString(type);
+ entry.Put(SPECIFICS, new_specifics);
+ }
+ } else if (encrypted_types.count(type) == 0 &&
+ entry_specifics.has_encrypted()) {
+ // This entry no longer requires encryption.
+ if (!cryptographer->Decrypt(entry_specifics.encrypted(),
+ &new_specifics)) {
+ LOG(ERROR) << "Could not decrypt data for newly unencrypted type " <<
+ ModelTypeToString(type);
+ NOTREACHED();
+ return false;
+ } else {
+ VLOG(1) << "Decrypted change for newly unencrypted type " <<
+ ModelTypeToString(type);
+ entry.Put(SPECIFICS, new_specifics);
+ }
+ }
+ }
+ return true;
+}
+
+bool VerifyUnsyncedChangesAreEncrypted(
+ BaseTransaction* const trans,
+ const ModelTypeSet& encrypted_types) {
+ std::vector<int64> handles;
+ browser_sync::SyncerUtil::GetUnsyncedEntries(trans, &handles);
+ for (size_t i = 0; i < handles.size(); ++i) {
+ Entry entry(trans, GET_BY_HANDLE, handles[i]);
+ if (!entry.good()) {
+ NOTREACHED();
+ return false;
+ }
+ const sync_pb::EntitySpecifics& entry_specifics = entry.Get(SPECIFICS);
+ ModelType type = entry.GetModelType();
+ if (type == PASSWORDS)
+ continue;
+ if (encrypted_types.count(type) > 0 &&
+ !entry_specifics.has_encrypted()) {
+ // This datatype requires encryption but this data is not encrypted.
+ return false;
+ }
+ }
+ return true;
+}
+
+// Mainly for testing.
+bool VerifyDataTypeEncryption(BaseTransaction* const trans,
+ ModelType type,
+ bool is_encrypted) {
+ if(type == PASSWORDS) {
+ NOTREACHED();
+ return true;
+ }
+ std::string type_tag = ModelTypeToRootTag(type);
+ Entry root(trans, GET_BY_SERVER_TAG, type_tag);
+ if (!root.good()) {
+ NOTREACHED();
+ return false;
+ }
+
+ Directory::ChildHandles handles;
+ trans->directory()->GetChildHandles(trans, root.Get(ID), &handles);
+ Directory::ChildHandles::iterator i = handles.begin();
+ while (i != handles.end()) {
+ Entry child(trans, GET_BY_HANDLE, *i++);
+ if (!child.good()) {
+ NOTREACHED();
+ return false;
+ }
+ // TODO(zea): traverse into directories as well.
+ if (child.Get(IS_DIR)) {
+ NOTREACHED();
+ continue;
+ }
+ const sync_pb::EntitySpecifics& specifics = child.Get(SPECIFICS);
+ if (specifics.has_encrypted() != is_encrypted)
+ return false;
+ }
+ return true;
+}
+
+} // namespace syncable

Powered by Google App Engine
This is Rietveld 408576698