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

Side by Side Diff: components/sync/syncable/nigori_util.cc

Issue 2130453004: [Sync] Move //sync to //components/sync. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Rebase. Created 4 years, 4 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
OLDNEW
1 // Copyright 2012 The Chromium Authors. All rights reserved. 1 // Copyright 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "sync/syncable/nigori_util.h" 5 #include "components/sync/syncable/nigori_util.h"
6 6
7 #include <stddef.h> 7 #include <stddef.h>
8 #include <stdint.h> 8 #include <stdint.h>
9 9
10 #include <queue> 10 #include <queue>
11 #include <string> 11 #include <string>
12 #include <vector> 12 #include <vector>
13 13
14 #include "base/json/json_writer.h" 14 #include "base/json/json_writer.h"
15 #include "sync/syncable/directory.h" 15 #include "components/sync/base/cryptographer.h"
16 #include "sync/syncable/entry.h" 16 #include "components/sync/syncable/directory.h"
17 #include "sync/syncable/mutable_entry.h" 17 #include "components/sync/syncable/entry.h"
18 #include "sync/syncable/nigori_handler.h" 18 #include "components/sync/syncable/mutable_entry.h"
19 #include "sync/syncable/syncable_util.h" 19 #include "components/sync/syncable/nigori_handler.h"
20 #include "sync/syncable/syncable_write_transaction.h" 20 #include "components/sync/syncable/syncable_util.h"
21 #include "sync/util/cryptographer.h" 21 #include "components/sync/syncable/syncable_write_transaction.h"
22 22
23 namespace syncer { 23 namespace syncer {
24 namespace syncable { 24 namespace syncable {
25 25
26 bool ProcessUnsyncedChangesForEncryption( 26 bool ProcessUnsyncedChangesForEncryption(WriteTransaction* const trans) {
27 WriteTransaction* const trans) {
28 NigoriHandler* nigori_handler = trans->directory()->GetNigoriHandler(); 27 NigoriHandler* nigori_handler = trans->directory()->GetNigoriHandler();
29 ModelTypeSet encrypted_types = nigori_handler->GetEncryptedTypes(trans); 28 ModelTypeSet encrypted_types = nigori_handler->GetEncryptedTypes(trans);
30 Cryptographer* cryptographer = trans->directory()->GetCryptographer(trans); 29 Cryptographer* cryptographer = trans->directory()->GetCryptographer(trans);
31 DCHECK(cryptographer->is_ready()); 30 DCHECK(cryptographer->is_ready());
32 31
33 // Get list of all datatypes with unsynced changes. It's possible that our 32 // Get list of all datatypes with unsynced changes. It's possible that our
34 // local changes need to be encrypted if encryption for that datatype was 33 // local changes need to be encrypted if encryption for that datatype was
35 // just turned on (and vice versa). 34 // just turned on (and vice versa).
36 // Note: we do not attempt to re-encrypt data with a new key here as key 35 // Note: we do not attempt to re-encrypt data with a new key here as key
37 // changes in this code path are likely due to consistency issues (we have 36 // changes in this code path are likely due to consistency issues (we have
38 // to be updated to a key we already have, e.g. an old key). 37 // to be updated to a key we already have, e.g. an old key).
39 std::vector<int64_t> handles; 38 std::vector<int64_t> handles;
40 GetUnsyncedEntries(trans, &handles); 39 GetUnsyncedEntries(trans, &handles);
41 for (size_t i = 0; i < handles.size(); ++i) { 40 for (size_t i = 0; i < handles.size(); ++i) {
42 MutableEntry entry(trans, GET_BY_HANDLE, handles[i]); 41 MutableEntry entry(trans, GET_BY_HANDLE, handles[i]);
43 const sync_pb::EntitySpecifics& specifics = entry.GetSpecifics(); 42 const sync_pb::EntitySpecifics& specifics = entry.GetSpecifics();
44 // Ignore types that don't need encryption or entries that are already 43 // Ignore types that don't need encryption or entries that are already
45 // encrypted. 44 // encrypted.
46 if (!SpecificsNeedsEncryption(encrypted_types, specifics)) 45 if (!SpecificsNeedsEncryption(encrypted_types, specifics))
47 continue; 46 continue;
48 if (!UpdateEntryWithEncryption(trans, specifics, &entry)) 47 if (!UpdateEntryWithEncryption(trans, specifics, &entry))
49 return false; 48 return false;
50 } 49 }
51 return true; 50 return true;
52 } 51 }
53 52
54 bool VerifyUnsyncedChangesAreEncrypted( 53 bool VerifyUnsyncedChangesAreEncrypted(BaseTransaction* const trans,
55 BaseTransaction* const trans, 54 ModelTypeSet encrypted_types) {
56 ModelTypeSet encrypted_types) {
57 std::vector<int64_t> handles; 55 std::vector<int64_t> handles;
58 GetUnsyncedEntries(trans, &handles); 56 GetUnsyncedEntries(trans, &handles);
59 for (size_t i = 0; i < handles.size(); ++i) { 57 for (size_t i = 0; i < handles.size(); ++i) {
60 Entry entry(trans, GET_BY_HANDLE, handles[i]); 58 Entry entry(trans, GET_BY_HANDLE, handles[i]);
61 if (!entry.good()) { 59 if (!entry.good()) {
62 NOTREACHED(); 60 NOTREACHED();
63 return false; 61 return false;
64 } 62 }
65 if (EntryNeedsEncryption(encrypted_types, entry)) 63 if (EntryNeedsEncryption(encrypted_types, entry))
66 return false; 64 return false;
67 } 65 }
68 return true; 66 return true;
69 } 67 }
70 68
71 bool EntryNeedsEncryption(ModelTypeSet encrypted_types, 69 bool EntryNeedsEncryption(ModelTypeSet encrypted_types, const Entry& entry) {
72 const Entry& entry) {
73 if (!entry.GetUniqueServerTag().empty()) 70 if (!entry.GetUniqueServerTag().empty())
74 return false; // We don't encrypt unique server nodes. 71 return false; // We don't encrypt unique server nodes.
75 ModelType type = entry.GetModelType(); 72 ModelType type = entry.GetModelType();
76 if (type == PASSWORDS || IsControlType(type)) 73 if (type == PASSWORDS || IsControlType(type))
77 return false; 74 return false;
78 // Checking NON_UNIQUE_NAME is not necessary for the correctness of encrypting 75 // Checking NON_UNIQUE_NAME is not necessary for the correctness of encrypting
79 // the data, nor for determining if data is encrypted. We simply ensure it has 76 // the data, nor for determining if data is encrypted. We simply ensure it has
80 // been overwritten to avoid any possible leaks of sensitive data. 77 // been overwritten to avoid any possible leaks of sensitive data.
81 return SpecificsNeedsEncryption(encrypted_types, entry.GetSpecifics()) || 78 return SpecificsNeedsEncryption(encrypted_types, entry.GetSpecifics()) ||
82 (encrypted_types.Has(type) && 79 (encrypted_types.Has(type) &&
83 entry.GetNonUniqueName() != kEncryptedString); 80 entry.GetNonUniqueName() != kEncryptedString);
84 } 81 }
85 82
86 bool SpecificsNeedsEncryption(ModelTypeSet encrypted_types, 83 bool SpecificsNeedsEncryption(ModelTypeSet encrypted_types,
87 const sync_pb::EntitySpecifics& specifics) { 84 const sync_pb::EntitySpecifics& specifics) {
88 const ModelType type = GetModelTypeFromSpecifics(specifics); 85 const ModelType type = GetModelTypeFromSpecifics(specifics);
89 if (type == PASSWORDS || IsControlType(type)) 86 if (type == PASSWORDS || IsControlType(type))
90 return false; // These types have their own encryption schemes. 87 return false; // These types have their own encryption schemes.
91 if (!encrypted_types.Has(type)) 88 if (!encrypted_types.Has(type))
92 return false; // This type does not require encryption 89 return false; // This type does not require encryption
93 return !specifics.has_encrypted(); 90 return !specifics.has_encrypted();
94 } 91 }
95 92
96 // Mainly for testing. 93 // Mainly for testing.
97 bool VerifyDataTypeEncryptionForTest( 94 bool VerifyDataTypeEncryptionForTest(BaseTransaction* const trans,
98 BaseTransaction* const trans, 95 ModelType type,
99 ModelType type, 96 bool is_encrypted) {
100 bool is_encrypted) {
101 Cryptographer* cryptographer = trans->directory()->GetCryptographer(trans); 97 Cryptographer* cryptographer = trans->directory()->GetCryptographer(trans);
102 if (type == PASSWORDS || IsControlType(type)) { 98 if (type == PASSWORDS || IsControlType(type)) {
103 NOTREACHED(); 99 NOTREACHED();
104 return true; 100 return true;
105 } 101 }
106 Entry type_root(trans, GET_TYPE_ROOT, type); 102 Entry type_root(trans, GET_TYPE_ROOT, type);
107 if (!type_root.good()) { 103 if (!type_root.good()) {
108 NOTREACHED(); 104 NOTREACHED();
109 return false; 105 return false;
110 } 106 }
(...skipping 30 matching lines...) Expand all
141 if (!cryptographer->CanDecryptUsingDefaultKey(specifics.encrypted())) 137 if (!cryptographer->CanDecryptUsingDefaultKey(specifics.encrypted()))
142 return false; 138 return false;
143 } 139 }
144 } 140 }
145 // Push the successor. 141 // Push the successor.
146 to_visit.push(child.GetSuccessorId()); 142 to_visit.push(child.GetSuccessorId());
147 } 143 }
148 return true; 144 return true;
149 } 145 }
150 146
151 bool UpdateEntryWithEncryption( 147 bool UpdateEntryWithEncryption(BaseTransaction* const trans,
152 BaseTransaction* const trans, 148 const sync_pb::EntitySpecifics& new_specifics,
153 const sync_pb::EntitySpecifics& new_specifics, 149 syncable::MutableEntry* entry) {
154 syncable::MutableEntry* entry) {
155 NigoriHandler* nigori_handler = trans->directory()->GetNigoriHandler(); 150 NigoriHandler* nigori_handler = trans->directory()->GetNigoriHandler();
156 Cryptographer* cryptographer = trans->directory()->GetCryptographer(trans); 151 Cryptographer* cryptographer = trans->directory()->GetCryptographer(trans);
157 ModelType type = GetModelTypeFromSpecifics(new_specifics); 152 ModelType type = GetModelTypeFromSpecifics(new_specifics);
158 DCHECK_GE(type, FIRST_REAL_MODEL_TYPE); 153 DCHECK_GE(type, FIRST_REAL_MODEL_TYPE);
159 const sync_pb::EntitySpecifics& old_specifics = entry->GetSpecifics(); 154 const sync_pb::EntitySpecifics& old_specifics = entry->GetSpecifics();
160 const ModelTypeSet encrypted_types = 155 const ModelTypeSet encrypted_types =
161 nigori_handler? 156 nigori_handler ? nigori_handler->GetEncryptedTypes(trans)
162 nigori_handler->GetEncryptedTypes(trans) : ModelTypeSet(); 157 : ModelTypeSet();
163 // It's possible the nigori lost the set of encrypted types. If the current 158 // It's possible the nigori lost the set of encrypted types. If the current
164 // specifics are already encrypted, we want to ensure we continue encrypting. 159 // specifics are already encrypted, we want to ensure we continue encrypting.
165 bool was_encrypted = old_specifics.has_encrypted(); 160 bool was_encrypted = old_specifics.has_encrypted();
166 sync_pb::EntitySpecifics generated_specifics; 161 sync_pb::EntitySpecifics generated_specifics;
167 if (new_specifics.has_encrypted()) { 162 if (new_specifics.has_encrypted()) {
168 NOTREACHED() << "New specifics already has an encrypted blob."; 163 NOTREACHED() << "New specifics already has an encrypted blob.";
169 return false; 164 return false;
170 } 165 }
171 if ((!SpecificsNeedsEncryption(encrypted_types, new_specifics) && 166 if ((!SpecificsNeedsEncryption(encrypted_types, new_specifics) &&
172 !was_encrypted) || 167 !was_encrypted) ||
173 !cryptographer || !cryptographer->is_initialized()) { 168 !cryptographer || !cryptographer->is_initialized()) {
174 // No encryption required or we are unable to encrypt. 169 // No encryption required or we are unable to encrypt.
175 generated_specifics.CopyFrom(new_specifics); 170 generated_specifics.CopyFrom(new_specifics);
176 } else { 171 } else {
177 // Encrypt new_specifics into generated_specifics. 172 // Encrypt new_specifics into generated_specifics.
178 if (VLOG_IS_ON(2)) { 173 if (VLOG_IS_ON(2)) {
179 std::unique_ptr<base::DictionaryValue> value(entry->ToValue(NULL)); 174 std::unique_ptr<base::DictionaryValue> value(entry->ToValue(NULL));
180 std::string info; 175 std::string info;
181 base::JSONWriter::WriteWithOptions( 176 base::JSONWriter::WriteWithOptions(
182 *value, base::JSONWriter::OPTIONS_PRETTY_PRINT, &info); 177 *value, base::JSONWriter::OPTIONS_PRETTY_PRINT, &info);
183 DVLOG(2) << "Encrypting specifics of type " 178 DVLOG(2) << "Encrypting specifics of type " << ModelTypeToString(type)
184 << ModelTypeToString(type) 179 << " with content: " << info;
185 << " with content: "
186 << info;
187 } 180 }
188 // Only copy over the old specifics if it is of the right type and already 181 // Only copy over the old specifics if it is of the right type and already
189 // encrypted. The first time we encrypt a node we start from scratch, hence 182 // encrypted. The first time we encrypt a node we start from scratch, hence
190 // removing all the unencrypted data, but from then on we only want to 183 // removing all the unencrypted data, but from then on we only want to
191 // update the node if the data changes or the encryption key changes. 184 // update the node if the data changes or the encryption key changes.
192 if (GetModelTypeFromSpecifics(old_specifics) == type && 185 if (GetModelTypeFromSpecifics(old_specifics) == type && was_encrypted) {
193 was_encrypted) {
194 generated_specifics.CopyFrom(old_specifics); 186 generated_specifics.CopyFrom(old_specifics);
195 } else { 187 } else {
196 AddDefaultFieldValue(type, &generated_specifics); 188 AddDefaultFieldValue(type, &generated_specifics);
197 } 189 }
198 // Does not change anything if underlying encrypted blob was already up 190 // Does not change anything if underlying encrypted blob was already up
199 // to date and encrypted with the default key. 191 // to date and encrypted with the default key.
200 if (!cryptographer->Encrypt(new_specifics, 192 if (!cryptographer->Encrypt(new_specifics,
201 generated_specifics.mutable_encrypted())) { 193 generated_specifics.mutable_encrypted())) {
202 NOTREACHED() << "Could not encrypt data for node of type " 194 NOTREACHED() << "Could not encrypt data for node of type "
203 << ModelTypeToString(type); 195 << ModelTypeToString(type);
204 return false; 196 return false;
205 } 197 }
206 } 198 }
207 199
208 // It's possible this entry was encrypted but didn't properly overwrite the 200 // It's possible this entry was encrypted but didn't properly overwrite the
209 // non_unique_name (see crbug.com/96314). 201 // non_unique_name (see crbug.com/96314).
210 bool encrypted_without_overwriting_name = (was_encrypted && 202 bool encrypted_without_overwriting_name =
211 entry->GetNonUniqueName() != kEncryptedString); 203 (was_encrypted && entry->GetNonUniqueName() != kEncryptedString);
212 204
213 // If we're encrypted but the name wasn't overwritten properly we still want 205 // If we're encrypted but the name wasn't overwritten properly we still want
214 // to rewrite the entry, irrespective of whether the specifics match. 206 // to rewrite the entry, irrespective of whether the specifics match.
215 if (!encrypted_without_overwriting_name && 207 if (!encrypted_without_overwriting_name &&
216 old_specifics.SerializeAsString() == 208 old_specifics.SerializeAsString() ==
217 generated_specifics.SerializeAsString()) { 209 generated_specifics.SerializeAsString()) {
218 DVLOG(2) << "Specifics of type " << ModelTypeToString(type) 210 DVLOG(2) << "Specifics of type " << ModelTypeToString(type)
219 << " already match, dropping change."; 211 << " already match, dropping change.";
220 return true; 212 return true;
221 } 213 }
222 214
223 if (generated_specifics.has_encrypted()) { 215 if (generated_specifics.has_encrypted()) {
224 // Overwrite the possibly sensitive non-specifics data. 216 // Overwrite the possibly sensitive non-specifics data.
225 entry->PutNonUniqueName(kEncryptedString); 217 entry->PutNonUniqueName(kEncryptedString);
226 // For bookmarks we actually put bogus data into the unencrypted specifics, 218 // For bookmarks we actually put bogus data into the unencrypted specifics,
227 // else the server will try to do it for us. 219 // else the server will try to do it for us.
228 if (type == BOOKMARKS) { 220 if (type == BOOKMARKS) {
229 sync_pb::BookmarkSpecifics* bookmark_specifics = 221 sync_pb::BookmarkSpecifics* bookmark_specifics =
230 generated_specifics.mutable_bookmark(); 222 generated_specifics.mutable_bookmark();
231 if (!entry->GetIsDir()) 223 if (!entry->GetIsDir())
232 bookmark_specifics->set_url(kEncryptedString); 224 bookmark_specifics->set_url(kEncryptedString);
233 bookmark_specifics->set_title(kEncryptedString); 225 bookmark_specifics->set_title(kEncryptedString);
234 } 226 }
235 } 227 }
236 entry->PutSpecifics(generated_specifics); 228 entry->PutSpecifics(generated_specifics);
237 DVLOG(1) << "Overwriting specifics of type " 229 DVLOG(1) << "Overwriting specifics of type " << ModelTypeToString(type)
238 << ModelTypeToString(type)
239 << " and marking for syncing."; 230 << " and marking for syncing.";
240 syncable::MarkForSyncing(entry); 231 syncable::MarkForSyncing(entry);
241 return true; 232 return true;
242 } 233 }
243 234
244 void UpdateNigoriFromEncryptedTypes(ModelTypeSet encrypted_types, 235 void UpdateNigoriFromEncryptedTypes(ModelTypeSet encrypted_types,
245 bool encrypt_everything, 236 bool encrypt_everything,
246 sync_pb::NigoriSpecifics* nigori) { 237 sync_pb::NigoriSpecifics* nigori) {
247 nigori->set_encrypt_everything(encrypt_everything); 238 nigori->set_encrypt_everything(encrypt_everything);
248 static_assert(37 == MODEL_TYPE_COUNT, "update encrypted types"); 239 static_assert(37 == MODEL_TYPE_COUNT, "update encrypted types");
249 nigori->set_encrypt_bookmarks( 240 nigori->set_encrypt_bookmarks(encrypted_types.Has(BOOKMARKS));
250 encrypted_types.Has(BOOKMARKS)); 241 nigori->set_encrypt_preferences(encrypted_types.Has(PREFERENCES));
251 nigori->set_encrypt_preferences( 242 nigori->set_encrypt_autofill_profile(encrypted_types.Has(AUTOFILL_PROFILE));
252 encrypted_types.Has(PREFERENCES));
253 nigori->set_encrypt_autofill_profile(
254 encrypted_types.Has(AUTOFILL_PROFILE));
255 nigori->set_encrypt_autofill(encrypted_types.Has(AUTOFILL)); 243 nigori->set_encrypt_autofill(encrypted_types.Has(AUTOFILL));
256 nigori->set_encrypt_autofill_wallet_metadata( 244 nigori->set_encrypt_autofill_wallet_metadata(
257 encrypted_types.Has(AUTOFILL_WALLET_METADATA)); 245 encrypted_types.Has(AUTOFILL_WALLET_METADATA));
258 nigori->set_encrypt_themes(encrypted_types.Has(THEMES)); 246 nigori->set_encrypt_themes(encrypted_types.Has(THEMES));
259 nigori->set_encrypt_typed_urls( 247 nigori->set_encrypt_typed_urls(encrypted_types.Has(TYPED_URLS));
260 encrypted_types.Has(TYPED_URLS));
261 nigori->set_encrypt_extension_settings( 248 nigori->set_encrypt_extension_settings(
262 encrypted_types.Has(EXTENSION_SETTINGS)); 249 encrypted_types.Has(EXTENSION_SETTINGS));
263 nigori->set_encrypt_extensions( 250 nigori->set_encrypt_extensions(encrypted_types.Has(EXTENSIONS));
264 encrypted_types.Has(EXTENSIONS)); 251 nigori->set_encrypt_search_engines(encrypted_types.Has(SEARCH_ENGINES));
265 nigori->set_encrypt_search_engines(
266 encrypted_types.Has(SEARCH_ENGINES));
267 nigori->set_encrypt_sessions(encrypted_types.Has(SESSIONS)); 252 nigori->set_encrypt_sessions(encrypted_types.Has(SESSIONS));
268 nigori->set_encrypt_app_settings( 253 nigori->set_encrypt_app_settings(encrypted_types.Has(APP_SETTINGS));
269 encrypted_types.Has(APP_SETTINGS));
270 nigori->set_encrypt_apps(encrypted_types.Has(APPS)); 254 nigori->set_encrypt_apps(encrypted_types.Has(APPS));
271 nigori->set_encrypt_app_notifications( 255 nigori->set_encrypt_app_notifications(encrypted_types.Has(APP_NOTIFICATIONS));
272 encrypted_types.Has(APP_NOTIFICATIONS));
273 nigori->set_encrypt_dictionary(encrypted_types.Has(DICTIONARY)); 256 nigori->set_encrypt_dictionary(encrypted_types.Has(DICTIONARY));
274 nigori->set_encrypt_favicon_images(encrypted_types.Has(FAVICON_IMAGES)); 257 nigori->set_encrypt_favicon_images(encrypted_types.Has(FAVICON_IMAGES));
275 nigori->set_encrypt_favicon_tracking(encrypted_types.Has(FAVICON_TRACKING)); 258 nigori->set_encrypt_favicon_tracking(encrypted_types.Has(FAVICON_TRACKING));
276 nigori->set_encrypt_articles(encrypted_types.Has(ARTICLES)); 259 nigori->set_encrypt_articles(encrypted_types.Has(ARTICLES));
277 nigori->set_encrypt_app_list(encrypted_types.Has(APP_LIST)); 260 nigori->set_encrypt_app_list(encrypted_types.Has(APP_LIST));
278 nigori->set_encrypt_arc_package(encrypted_types.Has(ARC_PACKAGE)); 261 nigori->set_encrypt_arc_package(encrypted_types.Has(ARC_PACKAGE));
279 } 262 }
280 263
281 ModelTypeSet GetEncryptedTypesFromNigori( 264 ModelTypeSet GetEncryptedTypesFromNigori(
282 const sync_pb::NigoriSpecifics& nigori) { 265 const sync_pb::NigoriSpecifics& nigori) {
(...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after
323 encrypted_types.Put(ARTICLES); 306 encrypted_types.Put(ARTICLES);
324 if (nigori.encrypt_app_list()) 307 if (nigori.encrypt_app_list())
325 encrypted_types.Put(APP_LIST); 308 encrypted_types.Put(APP_LIST);
326 if (nigori.encrypt_arc_package()) 309 if (nigori.encrypt_arc_package())
327 encrypted_types.Put(ARC_PACKAGE); 310 encrypted_types.Put(ARC_PACKAGE);
328 return encrypted_types; 311 return encrypted_types;
329 } 312 }
330 313
331 } // namespace syncable 314 } // namespace syncable
332 } // namespace syncer 315 } // namespace syncer
OLDNEW
« no previous file with comments | « components/sync/syncable/nigori_util.h ('k') | components/sync/syncable/nigori_util_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698