| OLD | NEW |
| 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 Loading... |
| 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 Loading... |
| 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 |
| OLD | NEW |