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

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 tests 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
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/internal_api/public/sync_encryption_handler.h"
12 #include "sync/protocol/nigori_specifics.pb.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 sync_encryption_delegate_(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::SetSyncEncryptionHandlerDelegate(
37 observers_.AddObserver(observer); 36 SyncEncryptionHandler* delegate) {
37 sync_encryption_delegate_ = delegate;
38 } 38 }
39 39
40 void Cryptographer::RemoveObserver(Observer* observer) { 40 void Cryptographer::UpdateFromNigori(const sync_pb::NigoriSpecifics& nigori) {
41 observers_.RemoveObserver(observer); 41 sync_encryption_delegate_->UpdateFromNigori(nigori);
42 } 42 }
43 43
44 ModelTypeSet Cryptographer::GetEncryptedTypes() const {
45 return sync_encryption_delegate_->GetEncryptedTypes();
46 }
47
48 void Cryptographer::UpdateNigoriFromEncryptedTypes(
49 sync_pb::NigoriSpecifics* nigori) const {
50 sync_encryption_delegate_->UpdateNigoriFromEncryptedTypes(nigori);
51 }
52
53
44 void Cryptographer::Bootstrap(const std::string& restored_bootstrap_token) { 54 void Cryptographer::Bootstrap(const std::string& restored_bootstrap_token) {
45 if (is_initialized()) { 55 if (is_initialized()) {
46 NOTREACHED(); 56 NOTREACHED();
47 return; 57 return;
48 } 58 }
49 59
50 scoped_ptr<Nigori> nigori(UnpackBootstrapToken(restored_bootstrap_token)); 60 scoped_ptr<Nigori> nigori(UnpackBootstrapToken(restored_bootstrap_token));
51 if (nigori.get()) 61 if (nigori.get())
52 AddKeyImpl(nigori.release(), false); 62 AddKeyImpl(nigori.release(), false);
53 } 63 }
(...skipping 133 matching lines...) Expand 10 before | Expand all | Expand 10 after
187 197
188 void Cryptographer::InstallKeys(const sync_pb::EncryptedData& encrypted) { 198 void Cryptographer::InstallKeys(const sync_pb::EncryptedData& encrypted) {
189 DCHECK(CanDecrypt(encrypted)); 199 DCHECK(CanDecrypt(encrypted));
190 200
191 sync_pb::NigoriKeyBag bag; 201 sync_pb::NigoriKeyBag bag;
192 if (!Decrypt(encrypted, &bag)) 202 if (!Decrypt(encrypted, &bag))
193 return; 203 return;
194 InstallKeyBag(bag); 204 InstallKeyBag(bag);
195 } 205 }
196 206
207 void Cryptographer::SetDefaultKey(std::string key_name) {
208 DCHECK(nigoris_.end() != nigoris_.find(key_name));
209 default_nigori_ = &*nigoris_.find(key_name);
210 }
211
197 void Cryptographer::SetPendingKeys(const sync_pb::EncryptedData& encrypted) { 212 void Cryptographer::SetPendingKeys(const sync_pb::EncryptedData& encrypted) {
198 DCHECK(!CanDecrypt(encrypted)); 213 DCHECK(!CanDecrypt(encrypted));
199 pending_keys_.reset(new sync_pb::EncryptedData(encrypted)); 214 pending_keys_.reset(new sync_pb::EncryptedData(encrypted));
200 } 215 }
201 216
202 const sync_pb::EncryptedData& Cryptographer::GetPendingKeys() const { 217 const sync_pb::EncryptedData& Cryptographer::GetPendingKeys() const {
203 DCHECK(has_pending_keys()); 218 DCHECK(has_pending_keys());
204 return *(pending_keys_.get()); 219 return *(pending_keys_.get());
205 } 220 }
206 221
(...skipping 97 matching lines...) Expand 10 before | Expand all | Expand 10 after
304 scoped_ptr<Nigori> nigori(new Nigori); 319 scoped_ptr<Nigori> nigori(new Nigori);
305 if (!nigori->InitByImport(key.user_key(), key.encryption_key(), 320 if (!nigori->InitByImport(key.user_key(), key.encryption_key(),
306 key.mac_key())) { 321 key.mac_key())) {
307 NOTREACHED(); 322 NOTREACHED();
308 return NULL; 323 return NULL;
309 } 324 }
310 325
311 return nigori.release(); 326 return nigori.release();
312 } 327 }
313 328
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) { 329 bool Cryptographer::SetKeystoreKey(const std::string& keystore_key) {
338 if (keystore_key.empty()) 330 if (keystore_key.empty())
339 return false; 331 return false;
340 KeyParams params = {"localhost", "dummy", keystore_key}; 332 KeyParams params = {"localhost", "dummy", keystore_key};
341 333
342 // Create the new Nigori and make it the default keystore encryptor. 334 // Create the new Nigori and make it the default keystore encryptor.
343 scoped_ptr<Nigori> nigori(new Nigori); 335 scoped_ptr<Nigori> nigori(new Nigori);
344 if (!nigori->InitByDerivation(params.hostname, 336 if (!nigori->InitByDerivation(params.hostname,
345 params.username, 337 params.username,
346 params.password)) { 338 params.password)) {
347 NOTREACHED(); // Invalid username or password. 339 NOTREACHED(); // Invalid username or password.
348 return false; 340 return false;
349 } 341 }
350 342
351 return AddKeyImpl(nigori.release(), true); 343 return AddKeyImpl(nigori.release(), true);
352 } 344 }
353 345
354 bool Cryptographer::HasKeystoreKey() const { 346 bool Cryptographer::HasKeystoreKey() const {
355 return keystore_nigori_ != NULL; 347 return keystore_nigori_ != NULL;
356 } 348 }
357 349
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) { 350 void Cryptographer::InstallKeyBag(const sync_pb::NigoriKeyBag& bag) {
481 int key_size = bag.key_size(); 351 int key_size = bag.key_size();
482 for (int i = 0; i < key_size; ++i) { 352 for (int i = 0; i < key_size; ++i) {
483 const sync_pb::NigoriKey key = bag.key(i); 353 const sync_pb::NigoriKey key = bag.key(i);
484 // Only use this key if we don't already know about it. 354 // Only use this key if we don't already know about it.
485 if (nigoris_.end() == nigoris_.find(key.name())) { 355 if (nigoris_.end() == nigoris_.find(key.name())) {
486 scoped_ptr<Nigori> new_nigori(new Nigori); 356 scoped_ptr<Nigori> new_nigori(new Nigori);
487 if (!new_nigori->InitByImport(key.user_key(), 357 if (!new_nigori->InitByImport(key.user_key(),
488 key.encryption_key(), 358 key.encryption_key(),
489 key.mac_key())) { 359 key.mac_key())) {
490 NOTREACHED(); 360 NOTREACHED();
491 continue; 361 continue;
492 } 362 }
493 nigoris_[key.name()] = make_linked_ptr(new_nigori.release()); 363 nigoris_[key.name()] = make_linked_ptr(new_nigori.release());
494 } 364 }
495 } 365 }
496 } 366 }
497 367
498 } // namespace syncer 368 } // namespace syncer
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698