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

Side by Side Diff: sync/util/cryptographer.cc

Issue 10827266: [Sync] Add SyncEncryptionHandler (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Fix Created 8 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 | Annotate | Revision Log
« no previous file with comments | « sync/util/cryptographer.h ('k') | sync/util/cryptographer_unittest.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. 1 // Copyright (c) 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/util/cryptographer.h" 5 #include "sync/util/cryptographer.h"
6 6
7 #include <algorithm> 7 #include <algorithm>
8 8
9 #include "base/base64.h" 9 #include "base/base64.h"
10 #include "base/logging.h" 10 #include "base/logging.h"
11 #include "sync/protocol/nigori_specifics.pb.h"
12 #include "sync/syncable/nigori_handler.h"
11 #include "sync/util/encryptor.h" 13 #include "sync/util/encryptor.h"
12 14
13 namespace syncer { 15 namespace syncer {
14 16
15 const char kNigoriTag[] = "google_chrome_nigori"; 17 const char kNigoriTag[] = "google_chrome_nigori";
16 18
17 // We name a particular Nigori instance (ie. a triplet consisting of a hostname, 19 // We name a particular Nigori instance (ie. a triplet consisting of a hostname,
18 // a username, and a password) by calling Permute on this string. Since the 20 // a username, and a password) by calling Permute on this string. Since the
19 // output of Permute is always the same for a given triplet, clients will always 21 // output of Permute is always the same for a given triplet, clients will always
20 // assign the same name to a particular triplet. 22 // assign the same name to a particular triplet.
21 const char kNigoriKeyName[] = "nigori-key"; 23 const char kNigoriKeyName[] = "nigori-key";
22 24
23 Cryptographer::Observer::~Observer() {}
24
25 Cryptographer::Cryptographer(Encryptor* encryptor) 25 Cryptographer::Cryptographer(Encryptor* encryptor)
26 : encryptor_(encryptor), 26 : encryptor_(encryptor),
27 default_nigori_(NULL), 27 default_nigori_(NULL),
28 keystore_nigori_(NULL), 28 keystore_nigori_(NULL),
29 encrypted_types_(SensitiveTypes()), 29 nigori_node_handler_(NULL) {
30 encrypt_everything_(false) {
31 DCHECK(encryptor); 30 DCHECK(encryptor);
32 } 31 }
33 32
34 Cryptographer::~Cryptographer() {} 33 Cryptographer::~Cryptographer() {}
35 34
36 void Cryptographer::AddObserver(Observer* observer) { 35 void Cryptographer::SetNigoriHandler(syncable::NigoriHandler* delegate) {
37 observers_.AddObserver(observer); 36 nigori_node_handler_ = delegate;
38 } 37 }
39 38
40 void Cryptographer::RemoveObserver(Observer* observer) { 39 void Cryptographer::ApplyNigoriUpdate(
41 observers_.RemoveObserver(observer); 40 const sync_pb::NigoriSpecifics& nigori,
41 syncable::BaseTransaction* const trans) {
42 nigori_node_handler_->ApplyNigoriUpdate(nigori, trans);
42 } 43 }
43 44
45 ModelTypeSet Cryptographer::GetEncryptedTypes() const {
46 return nigori_node_handler_->GetEncryptedTypes();
47 }
48
49 void Cryptographer::UpdateNigoriFromEncryptedTypes(
50 sync_pb::NigoriSpecifics* nigori,
51 syncable::BaseTransaction* const trans) const {
52 nigori_node_handler_->UpdateNigoriFromEncryptedTypes(nigori, trans);
53 }
54
55
44 void Cryptographer::Bootstrap(const std::string& restored_bootstrap_token) { 56 void Cryptographer::Bootstrap(const std::string& restored_bootstrap_token) {
45 if (is_initialized()) { 57 if (is_initialized()) {
46 NOTREACHED(); 58 NOTREACHED();
47 return; 59 return;
48 } 60 }
49 61
50 scoped_ptr<Nigori> nigori(UnpackBootstrapToken(restored_bootstrap_token)); 62 scoped_ptr<Nigori> nigori(UnpackBootstrapToken(restored_bootstrap_token));
51 if (nigori.get()) 63 if (nigori.get())
52 AddKeyImpl(nigori.release(), false); 64 AddKeyImpl(nigori.release(), false);
53 } 65 }
(...skipping 133 matching lines...) Expand 10 before | Expand all | Expand 10 after
187 199
188 void Cryptographer::InstallKeys(const sync_pb::EncryptedData& encrypted) { 200 void Cryptographer::InstallKeys(const sync_pb::EncryptedData& encrypted) {
189 DCHECK(CanDecrypt(encrypted)); 201 DCHECK(CanDecrypt(encrypted));
190 202
191 sync_pb::NigoriKeyBag bag; 203 sync_pb::NigoriKeyBag bag;
192 if (!Decrypt(encrypted, &bag)) 204 if (!Decrypt(encrypted, &bag))
193 return; 205 return;
194 InstallKeyBag(bag); 206 InstallKeyBag(bag);
195 } 207 }
196 208
209 void Cryptographer::SetDefaultKey(const std::string& key_name) {
210 DCHECK(nigoris_.end() != nigoris_.find(key_name));
211 default_nigori_ = &*nigoris_.find(key_name);
212 }
213
197 void Cryptographer::SetPendingKeys(const sync_pb::EncryptedData& encrypted) { 214 void Cryptographer::SetPendingKeys(const sync_pb::EncryptedData& encrypted) {
198 DCHECK(!CanDecrypt(encrypted)); 215 DCHECK(!CanDecrypt(encrypted));
199 pending_keys_.reset(new sync_pb::EncryptedData(encrypted)); 216 pending_keys_.reset(new sync_pb::EncryptedData(encrypted));
200 } 217 }
201 218
202 const sync_pb::EncryptedData& Cryptographer::GetPendingKeys() const { 219 const sync_pb::EncryptedData& Cryptographer::GetPendingKeys() const {
203 DCHECK(has_pending_keys()); 220 DCHECK(has_pending_keys());
204 return *(pending_keys_.get()); 221 return *(pending_keys_.get());
205 } 222 }
206 223
(...skipping 97 matching lines...) Expand 10 before | Expand all | Expand 10 after
304 scoped_ptr<Nigori> nigori(new Nigori); 321 scoped_ptr<Nigori> nigori(new Nigori);
305 if (!nigori->InitByImport(key.user_key(), key.encryption_key(), 322 if (!nigori->InitByImport(key.user_key(), key.encryption_key(),
306 key.mac_key())) { 323 key.mac_key())) {
307 NOTREACHED(); 324 NOTREACHED();
308 return NULL; 325 return NULL;
309 } 326 }
310 327
311 return nigori.release(); 328 return nigori.release();
312 } 329 }
313 330
314 Cryptographer::UpdateResult Cryptographer::Update(
315 const sync_pb::NigoriSpecifics& nigori) {
316 UpdateEncryptedTypesFromNigori(nigori);
317 if (!nigori.encrypted().blob().empty()) {
318 if (CanDecrypt(nigori.encrypted())) {
319 InstallKeys(nigori.encrypted());
320 // We only update the default passphrase if this was a new explicit
321 // passphrase. Else, since it was decryptable, it must not have been a new
322 // key.
323 if (nigori.using_explicit_passphrase()) {
324 std::string new_default_key_name = nigori.encrypted().key_name();
325 DCHECK(nigoris_.end() != nigoris_.find(new_default_key_name));
326 default_nigori_ = &*nigoris_.find(new_default_key_name);
327 }
328 return Cryptographer::SUCCESS;
329 } else {
330 SetPendingKeys(nigori.encrypted());
331 return Cryptographer::NEEDS_PASSPHRASE;
332 }
333 }
334 return Cryptographer::SUCCESS;
335 }
336
337 bool Cryptographer::SetKeystoreKey(const std::string& keystore_key) { 331 bool Cryptographer::SetKeystoreKey(const std::string& keystore_key) {
338 if (keystore_key.empty()) 332 if (keystore_key.empty())
339 return false; 333 return false;
340 KeyParams params = {"localhost", "dummy", keystore_key}; 334 KeyParams params = {"localhost", "dummy", keystore_key};
341 335
342 // Create the new Nigori and make it the default keystore encryptor. 336 // Create the new Nigori and make it the default keystore encryptor.
343 scoped_ptr<Nigori> nigori(new Nigori); 337 scoped_ptr<Nigori> nigori(new Nigori);
344 if (!nigori->InitByDerivation(params.hostname, 338 if (!nigori->InitByDerivation(params.hostname,
345 params.username, 339 params.username,
346 params.password)) { 340 params.password)) {
347 NOTREACHED(); // Invalid username or password. 341 NOTREACHED(); // Invalid username or password.
348 return false; 342 return false;
349 } 343 }
350 344
351 return AddKeyImpl(nigori.release(), true); 345 return AddKeyImpl(nigori.release(), true);
352 } 346 }
353 347
354 bool Cryptographer::HasKeystoreKey() const { 348 bool Cryptographer::HasKeystoreKey() const {
355 return keystore_nigori_ != NULL; 349 return keystore_nigori_ != NULL;
356 } 350 }
357 351
358 // Static
359 ModelTypeSet Cryptographer::SensitiveTypes() {
360 // Both of these have their own encryption schemes, but we include them
361 // anyways.
362 ModelTypeSet types;
363 types.Put(PASSWORDS);
364 types.Put(NIGORI);
365 return types;
366 }
367
368 void Cryptographer::UpdateEncryptedTypesFromNigori(
369 const sync_pb::NigoriSpecifics& nigori) {
370 if (nigori.encrypt_everything()) {
371 set_encrypt_everything();
372 return;
373 }
374
375 ModelTypeSet encrypted_types(SensitiveTypes());
376 if (nigori.encrypt_bookmarks())
377 encrypted_types.Put(BOOKMARKS);
378 if (nigori.encrypt_preferences())
379 encrypted_types.Put(PREFERENCES);
380 if (nigori.encrypt_autofill_profile())
381 encrypted_types.Put(AUTOFILL_PROFILE);
382 if (nigori.encrypt_autofill())
383 encrypted_types.Put(AUTOFILL);
384 if (nigori.encrypt_themes())
385 encrypted_types.Put(THEMES);
386 if (nigori.encrypt_typed_urls())
387 encrypted_types.Put(TYPED_URLS);
388 if (nigori.encrypt_extension_settings())
389 encrypted_types.Put(EXTENSION_SETTINGS);
390 if (nigori.encrypt_extensions())
391 encrypted_types.Put(EXTENSIONS);
392 if (nigori.encrypt_search_engines())
393 encrypted_types.Put(SEARCH_ENGINES);
394 if (nigori.encrypt_sessions())
395 encrypted_types.Put(SESSIONS);
396 if (nigori.encrypt_app_settings())
397 encrypted_types.Put(APP_SETTINGS);
398 if (nigori.encrypt_apps())
399 encrypted_types.Put(APPS);
400 if (nigori.encrypt_app_notifications())
401 encrypted_types.Put(APP_NOTIFICATIONS);
402
403 // Note: the initial version with encryption did not support the
404 // encrypt_everything field. If anything more than the sensitive types were
405 // encrypted, it meant we were encrypting everything.
406 if (!nigori.has_encrypt_everything() &&
407 !Difference(encrypted_types, SensitiveTypes()).Empty()) {
408 set_encrypt_everything();
409 return;
410 }
411
412 MergeEncryptedTypes(encrypted_types);
413 }
414
415 void Cryptographer::UpdateNigoriFromEncryptedTypes(
416 sync_pb::NigoriSpecifics* nigori) const {
417 nigori->set_encrypt_everything(encrypt_everything_);
418 nigori->set_encrypt_bookmarks(
419 encrypted_types_.Has(BOOKMARKS));
420 nigori->set_encrypt_preferences(
421 encrypted_types_.Has(PREFERENCES));
422 nigori->set_encrypt_autofill_profile(
423 encrypted_types_.Has(AUTOFILL_PROFILE));
424 nigori->set_encrypt_autofill(encrypted_types_.Has(AUTOFILL));
425 nigori->set_encrypt_themes(encrypted_types_.Has(THEMES));
426 nigori->set_encrypt_typed_urls(
427 encrypted_types_.Has(TYPED_URLS));
428 nigori->set_encrypt_extension_settings(
429 encrypted_types_.Has(EXTENSION_SETTINGS));
430 nigori->set_encrypt_extensions(
431 encrypted_types_.Has(EXTENSIONS));
432 nigori->set_encrypt_search_engines(
433 encrypted_types_.Has(SEARCH_ENGINES));
434 nigori->set_encrypt_sessions(encrypted_types_.Has(SESSIONS));
435 nigori->set_encrypt_app_settings(
436 encrypted_types_.Has(APP_SETTINGS));
437 nigori->set_encrypt_apps(encrypted_types_.Has(APPS));
438 nigori->set_encrypt_app_notifications(
439 encrypted_types_.Has(APP_NOTIFICATIONS));
440 }
441
442 void Cryptographer::set_encrypt_everything() {
443 if (encrypt_everything_) {
444 DCHECK(encrypted_types_.Equals(ModelTypeSet::All()));
445 return;
446 }
447 encrypt_everything_ = true;
448 // Change |encrypted_types_| directly to avoid sending more than one
449 // notification.
450 encrypted_types_ = ModelTypeSet::All();
451 EmitEncryptedTypesChangedNotification();
452 }
453
454 bool Cryptographer::encrypt_everything() const {
455 return encrypt_everything_;
456 }
457
458 ModelTypeSet Cryptographer::GetEncryptedTypes() const {
459 return encrypted_types_;
460 }
461
462 void Cryptographer::MergeEncryptedTypesForTest(ModelTypeSet encrypted_types) {
463 MergeEncryptedTypes(encrypted_types);
464 }
465
466 void Cryptographer::MergeEncryptedTypes(ModelTypeSet encrypted_types) {
467 if (encrypted_types_.HasAll(encrypted_types)) {
468 return;
469 }
470 encrypted_types_ = encrypted_types;
471 EmitEncryptedTypesChangedNotification();
472 }
473
474 void Cryptographer::EmitEncryptedTypesChangedNotification() {
475 FOR_EACH_OBSERVER(
476 Observer, observers_,
477 OnEncryptedTypesChanged(encrypted_types_, encrypt_everything_));
478 }
479
480 void Cryptographer::InstallKeyBag(const sync_pb::NigoriKeyBag& bag) { 352 void Cryptographer::InstallKeyBag(const sync_pb::NigoriKeyBag& bag) {
481 int key_size = bag.key_size(); 353 int key_size = bag.key_size();
482 for (int i = 0; i < key_size; ++i) { 354 for (int i = 0; i < key_size; ++i) {
483 const sync_pb::NigoriKey key = bag.key(i); 355 const sync_pb::NigoriKey key = bag.key(i);
484 // Only use this key if we don't already know about it. 356 // Only use this key if we don't already know about it.
485 if (nigoris_.end() == nigoris_.find(key.name())) { 357 if (nigoris_.end() == nigoris_.find(key.name())) {
486 scoped_ptr<Nigori> new_nigori(new Nigori); 358 scoped_ptr<Nigori> new_nigori(new Nigori);
487 if (!new_nigori->InitByImport(key.user_key(), 359 if (!new_nigori->InitByImport(key.user_key(),
488 key.encryption_key(), 360 key.encryption_key(),
489 key.mac_key())) { 361 key.mac_key())) {
490 NOTREACHED(); 362 NOTREACHED();
491 continue; 363 continue;
492 } 364 }
493 nigoris_[key.name()] = make_linked_ptr(new_nigori.release()); 365 nigoris_[key.name()] = make_linked_ptr(new_nigori.release());
494 } 366 }
495 } 367 }
496 } 368 }
497 369
498 } // namespace syncer 370 } // namespace syncer
OLDNEW
« no previous file with comments | « sync/util/cryptographer.h ('k') | sync/util/cryptographer_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698