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

Side by Side 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 unified diff | Download patch | Annotate | Revision Log
OLDNEW
(Empty)
1 // Copyright (c) 2011 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include "chrome/browser/sync/syncable/nigori_util.h"
6
7 #include <queue>
8 #include <vector>
9
10 #include "chrome/browser/sync/engine/syncer_util.h"
11 #include "chrome/browser/sync/syncable/syncable.h"
12 #include "chrome/browser/sync/util/cryptographer.h"
13
14 namespace syncable {
15
16 ModelTypeSet GetEncryptedDatatypesFromNigori(
17 const sync_pb::NigoriSpecifics& nigori) {
18 // We don't check NIGORI and PASSWORDS datatypes, they use their own
19 // encryption scheme.
20 ModelTypeSet encrypted_types;
21 if(nigori.encrypt_bookmarks())
22 encrypted_types.insert(BOOKMARKS);
23 if(nigori.encrypt_preferences())
24 encrypted_types.insert(PREFERENCES);
25 if(nigori.encrypt_passwords())
26 encrypted_types.insert(PASSWORDS);
27 if(nigori.encrypt_autofill_profile())
28 encrypted_types.insert(AUTOFILL_PROFILE);
29 if(nigori.encrypt_autofill())
30 encrypted_types.insert(AUTOFILL);
31 if(nigori.encrypt_themes())
32 encrypted_types.insert(THEMES);
33 if(nigori.encrypt_typed_urls())
34 encrypted_types.insert(TYPED_URLS);
35 if(nigori.encrypt_extensions())
36 encrypted_types.insert(EXTENSIONS);
37 if(nigori.encrypt_sessions())
38 encrypted_types.insert(SESSIONS);
39 if(nigori.encrypt_apps())
40 encrypted_types.insert(APPS);
41 return encrypted_types;
42 }
43
44 void FillNigoriEncryptedTypes(const ModelTypeSet& types,
45 sync_pb::NigoriSpecifics* nigori) {
46 DCHECK(nigori);
47 nigori->set_encrypt_bookmarks(types.count(BOOKMARKS) > 0);
48 nigori->set_encrypt_preferences(types.count(PREFERENCES) > 0);
49 nigori->set_encrypt_passwords(types.count(PASSWORDS) > 0);
50 nigori->set_encrypt_autofill_profile(types.count(AUTOFILL_PROFILE) > 0);
51 nigori->set_encrypt_autofill(types.count(AUTOFILL) > 0);
52 nigori->set_encrypt_themes(types.count(THEMES) > 0);
53 nigori->set_encrypt_typed_urls(types.count(TYPED_URLS) > 0);
54 nigori->set_encrypt_extensions(types.count(EXTENSIONS) > 0);
55 nigori->set_encrypt_sessions(types.count(SESSIONS) > 0);
56 nigori->set_encrypt_apps(types.count(APPS) > 0);
57 }
58
59 bool ProcessUnsyncedChangesForEncryption(
60 WriteTransaction* const trans,
61 const ModelTypeSet& encrypted_types,
62 browser_sync::Cryptographer* cryptographer) {
63 // Get list of all datatypes with unsynced changes. It's possible that our
64 // local changes need to be encrypted if encryption for that datatype was
65 // just turned on (and vice versa). This should never affect passwords.
66 std::vector<int64> handles;
67 browser_sync::SyncerUtil::GetUnsyncedEntries(trans, &handles);
68 for (size_t i = 0; i < handles.size(); ++i) {
69 MutableEntry entry(trans, GET_BY_HANDLE, handles[i]);
70 sync_pb::EntitySpecifics new_specifics;
71 const sync_pb::EntitySpecifics& entry_specifics = entry.Get(SPECIFICS);
72 ModelType type = entry.GetModelType();
73 if (type == PASSWORDS)
74 continue;
75 if (encrypted_types.count(type) > 0 &&
76 !entry_specifics.has_encrypted()) {
77 // This entry now requires encryption.
78 AddDefaultExtensionValue(type, &new_specifics);
79 if (!cryptographer->Encrypt(
80 entry_specifics,
81 new_specifics.mutable_encrypted())) {
82 LOG(ERROR) << "Could not encrypt data for newly encrypted type " <<
83 ModelTypeToString(type);
84 NOTREACHED();
85 return false;
86 } else {
87 VLOG(1) << "Encrypted change for newly encrypted type " <<
88 ModelTypeToString(type);
89 entry.Put(SPECIFICS, new_specifics);
90 }
91 } else if (encrypted_types.count(type) == 0 &&
92 entry_specifics.has_encrypted()) {
93 // This entry no longer requires encryption.
94 if (!cryptographer->Decrypt(entry_specifics.encrypted(),
95 &new_specifics)) {
96 LOG(ERROR) << "Could not decrypt data for newly unencrypted type " <<
97 ModelTypeToString(type);
98 NOTREACHED();
99 return false;
100 } else {
101 VLOG(1) << "Decrypted change for newly unencrypted type " <<
102 ModelTypeToString(type);
103 entry.Put(SPECIFICS, new_specifics);
104 }
105 }
106 }
107 return true;
108 }
109
110 bool VerifyUnsyncedChangesAreEncrypted(
111 BaseTransaction* const trans,
112 const ModelTypeSet& encrypted_types) {
113 std::vector<int64> handles;
114 browser_sync::SyncerUtil::GetUnsyncedEntries(trans, &handles);
115 for (size_t i = 0; i < handles.size(); ++i) {
116 Entry entry(trans, GET_BY_HANDLE, handles[i]);
117 if (!entry.good()) {
118 NOTREACHED();
119 return false;
120 }
121 const sync_pb::EntitySpecifics& entry_specifics = entry.Get(SPECIFICS);
122 ModelType type = entry.GetModelType();
123 if (type == PASSWORDS)
124 continue;
125 if (encrypted_types.count(type) > 0 &&
126 !entry_specifics.has_encrypted()) {
127 // This datatype requires encryption but this data is not encrypted.
128 return false;
129 }
130 }
131 return true;
132 }
133
134 // Mainly for testing.
135 bool VerifyDataTypeEncryption(BaseTransaction* const trans,
136 ModelType type,
137 bool is_encrypted) {
138 if(type == PASSWORDS) {
139 NOTREACHED();
140 return true;
141 }
142 std::string type_tag = ModelTypeToRootTag(type);
143 Entry root(trans, GET_BY_SERVER_TAG, type_tag);
144 if (!root.good()) {
145 NOTREACHED();
146 return false;
147 }
148
149 Directory::ChildHandles handles;
150 trans->directory()->GetChildHandles(trans, root.Get(ID), &handles);
151 Directory::ChildHandles::iterator i = handles.begin();
152 while (i != handles.end()) {
153 Entry child(trans, GET_BY_HANDLE, *i++);
154 if (!child.good()) {
155 NOTREACHED();
156 return false;
157 }
158 // TODO(zea): traverse into directories as well.
159 if (child.Get(IS_DIR)) {
160 NOTREACHED();
161 continue;
162 }
163 const sync_pb::EntitySpecifics& specifics = child.Get(SPECIFICS);
164 if (specifics.has_encrypted() != is_encrypted)
165 return false;
166 }
167 return true;
168 }
169
170 } // namespace syncable
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698