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

Side by Side Diff: components/sync/core_impl/sync_encryption_handler_impl.cc

Issue 2413313004: [Sync] Move the last things out of core/. (Closed)
Patch Set: Address comments. Created 4 years, 2 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
(Empty)
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
3 // found in the LICENSE file.
4
5 #include "components/sync/core_impl/sync_encryption_handler_impl.h"
6
7 #include <stddef.h>
8 #include <stdint.h>
9
10 #include <memory>
11 #include <queue>
12
13 #include "base/base64.h"
14 #include "base/bind.h"
15 #include "base/json/json_string_value_serializer.h"
16 #include "base/location.h"
17 #include "base/metrics/histogram_macros.h"
18 #include "base/single_thread_task_runner.h"
19 #include "base/threading/thread_task_runner_handle.h"
20 #include "base/tracked_objects.h"
21 #include "components/sync/base/encryptor.h"
22 #include "components/sync/base/experiments.h"
23 #include "components/sync/base/passphrase_type.h"
24 #include "components/sync/base/time.h"
25 #include "components/sync/engine/sync_string_conversions.h"
26 #include "components/sync/protocol/encryption.pb.h"
27 #include "components/sync/protocol/nigori_specifics.pb.h"
28 #include "components/sync/protocol/sync.pb.h"
29 #include "components/sync/syncable/directory.h"
30 #include "components/sync/syncable/entry.h"
31 #include "components/sync/syncable/mutable_entry.h"
32 #include "components/sync/syncable/nigori_util.h"
33 #include "components/sync/syncable/read_node.h"
34 #include "components/sync/syncable/read_transaction.h"
35 #include "components/sync/syncable/syncable_base_transaction.h"
36 #include "components/sync/syncable/syncable_model_neutral_write_transaction.h"
37 #include "components/sync/syncable/syncable_write_transaction.h"
38 #include "components/sync/syncable/user_share.h"
39 #include "components/sync/syncable/write_node.h"
40 #include "components/sync/syncable/write_transaction.h"
41
42 namespace syncer {
43
44 namespace {
45
46 // The maximum number of times we will automatically overwrite the nigori node
47 // because the encryption keys don't match (per chrome instantiation).
48 // We protect ourselves against nigori rollbacks, but it's possible two
49 // different clients might have contrasting view of what the nigori node state
50 // should be, in which case they might ping pong (see crbug.com/119207).
51 static const int kNigoriOverwriteLimit = 10;
52
53 // Enumeration of nigori keystore migration results (for use in UMA stats).
54 enum NigoriMigrationResult {
55 FAILED_TO_SET_DEFAULT_KEYSTORE,
56 FAILED_TO_SET_NONDEFAULT_KEYSTORE,
57 FAILED_TO_EXTRACT_DECRYPTOR,
58 FAILED_TO_EXTRACT_KEYBAG,
59 MIGRATION_SUCCESS_KEYSTORE_NONDEFAULT,
60 MIGRATION_SUCCESS_KEYSTORE_DEFAULT,
61 MIGRATION_SUCCESS_FROZEN_IMPLICIT,
62 MIGRATION_SUCCESS_CUSTOM,
63 MIGRATION_RESULT_SIZE,
64 };
65
66 enum NigoriMigrationState {
67 MIGRATED,
68 NOT_MIGRATED_CRYPTO_NOT_READY,
69 NOT_MIGRATED_NO_KEYSTORE_KEY,
70 NOT_MIGRATED_UNKNOWN_REASON,
71 MIGRATION_STATE_SIZE,
72 };
73
74 // The new passphrase state is sufficient to determine whether a nigori node
75 // is migrated to support keystore encryption. In addition though, we also
76 // want to verify the conditions for proper keystore encryption functionality.
77 // 1. Passphrase type is set.
78 // 2. Frozen keybag is true
79 // 3. If passphrase state is keystore, keystore_decryptor_token is set.
80 bool IsNigoriMigratedToKeystore(const sync_pb::NigoriSpecifics& nigori) {
81 if (!nigori.has_passphrase_type())
82 return false;
83 if (!nigori.keybag_is_frozen())
84 return false;
85 if (nigori.passphrase_type() == sync_pb::NigoriSpecifics::IMPLICIT_PASSPHRASE)
86 return false;
87 if (nigori.passphrase_type() ==
88 sync_pb::NigoriSpecifics::KEYSTORE_PASSPHRASE &&
89 nigori.keystore_decryptor_token().blob().empty())
90 return false;
91 return true;
92 }
93
94 PassphraseType ProtoPassphraseTypeToEnum(
95 sync_pb::NigoriSpecifics::PassphraseType type) {
96 switch (type) {
97 case sync_pb::NigoriSpecifics::IMPLICIT_PASSPHRASE:
98 return PassphraseType::IMPLICIT_PASSPHRASE;
99 case sync_pb::NigoriSpecifics::KEYSTORE_PASSPHRASE:
100 return PassphraseType::KEYSTORE_PASSPHRASE;
101 case sync_pb::NigoriSpecifics::CUSTOM_PASSPHRASE:
102 return PassphraseType::CUSTOM_PASSPHRASE;
103 case sync_pb::NigoriSpecifics::FROZEN_IMPLICIT_PASSPHRASE:
104 return PassphraseType::FROZEN_IMPLICIT_PASSPHRASE;
105 default:
106 NOTREACHED();
107 return PassphraseType::IMPLICIT_PASSPHRASE;
108 }
109 }
110
111 sync_pb::NigoriSpecifics::PassphraseType EnumPassphraseTypeToProto(
112 PassphraseType type) {
113 switch (type) {
114 case PassphraseType::IMPLICIT_PASSPHRASE:
115 return sync_pb::NigoriSpecifics::IMPLICIT_PASSPHRASE;
116 case PassphraseType::KEYSTORE_PASSPHRASE:
117 return sync_pb::NigoriSpecifics::KEYSTORE_PASSPHRASE;
118 case PassphraseType::CUSTOM_PASSPHRASE:
119 return sync_pb::NigoriSpecifics::CUSTOM_PASSPHRASE;
120 case PassphraseType::FROZEN_IMPLICIT_PASSPHRASE:
121 return sync_pb::NigoriSpecifics::FROZEN_IMPLICIT_PASSPHRASE;
122 default:
123 NOTREACHED();
124 return sync_pb::NigoriSpecifics::IMPLICIT_PASSPHRASE;
125 }
126 }
127
128 // Keystore Bootstrap Token helper methods.
129 // The bootstrap is a base64 encoded, encrypted, ListValue of keystore key
130 // strings, with the current keystore key as the last value in the list.
131 std::string PackKeystoreBootstrapToken(
132 const std::vector<std::string>& old_keystore_keys,
133 const std::string& current_keystore_key,
134 Encryptor* encryptor) {
135 if (current_keystore_key.empty())
136 return std::string();
137
138 base::ListValue keystore_key_values;
139 for (size_t i = 0; i < old_keystore_keys.size(); ++i)
140 keystore_key_values.AppendString(old_keystore_keys[i]);
141 keystore_key_values.AppendString(current_keystore_key);
142
143 // Update the bootstrap token.
144 // The bootstrap is a base64 encoded, encrypted, ListValue of keystore key
145 // strings, with the current keystore key as the last value in the list.
146 std::string serialized_keystores;
147 JSONStringValueSerializer json(&serialized_keystores);
148 json.Serialize(keystore_key_values);
149 std::string encrypted_keystores;
150 encryptor->EncryptString(serialized_keystores, &encrypted_keystores);
151 std::string keystore_bootstrap;
152 base::Base64Encode(encrypted_keystores, &keystore_bootstrap);
153 return keystore_bootstrap;
154 }
155
156 bool UnpackKeystoreBootstrapToken(const std::string& keystore_bootstrap_token,
157 Encryptor* encryptor,
158 std::vector<std::string>* old_keystore_keys,
159 std::string* current_keystore_key) {
160 if (keystore_bootstrap_token.empty())
161 return false;
162 std::string base64_decoded_keystore_bootstrap;
163 if (!base::Base64Decode(keystore_bootstrap_token,
164 &base64_decoded_keystore_bootstrap)) {
165 return false;
166 }
167 std::string decrypted_keystore_bootstrap;
168 if (!encryptor->DecryptString(base64_decoded_keystore_bootstrap,
169 &decrypted_keystore_bootstrap)) {
170 return false;
171 }
172
173 JSONStringValueDeserializer json(decrypted_keystore_bootstrap);
174 std::unique_ptr<base::Value> deserialized_keystore_keys(
175 json.Deserialize(NULL, NULL));
176 if (!deserialized_keystore_keys)
177 return false;
178 base::ListValue* internal_list_value = NULL;
179 if (!deserialized_keystore_keys->GetAsList(&internal_list_value))
180 return false;
181 int number_of_keystore_keys = internal_list_value->GetSize();
182 if (!internal_list_value->GetString(number_of_keystore_keys - 1,
183 current_keystore_key)) {
184 return false;
185 }
186 old_keystore_keys->resize(number_of_keystore_keys - 1);
187 for (int i = 0; i < number_of_keystore_keys - 1; ++i)
188 internal_list_value->GetString(i, &(*old_keystore_keys)[i]);
189 return true;
190 }
191
192 } // namespace
193
194 SyncEncryptionHandlerImpl::Vault::Vault(Encryptor* encryptor,
195 ModelTypeSet encrypted_types,
196 PassphraseType passphrase_type)
197 : cryptographer(encryptor),
198 encrypted_types(encrypted_types),
199 passphrase_type(passphrase_type) {}
200
201 SyncEncryptionHandlerImpl::Vault::~Vault() {}
202
203 SyncEncryptionHandlerImpl::SyncEncryptionHandlerImpl(
204 UserShare* user_share,
205 Encryptor* encryptor,
206 const std::string& restored_key_for_bootstrapping,
207 const std::string& restored_keystore_key_for_bootstrapping)
208 : user_share_(user_share),
209 vault_unsafe_(encryptor,
210 SensitiveTypes(),
211 PassphraseType::IMPLICIT_PASSPHRASE),
212 encrypt_everything_(false),
213 nigori_overwrite_count_(0),
214 weak_ptr_factory_(this) {
215 // Restore the cryptographer's previous keys. Note that we don't add the
216 // keystore keys into the cryptographer here, in case a migration was pending.
217 vault_unsafe_.cryptographer.Bootstrap(restored_key_for_bootstrapping);
218
219 // If this fails, we won't have a valid keystore key, and will simply request
220 // new ones from the server on the next DownloadUpdates.
221 UnpackKeystoreBootstrapToken(restored_keystore_key_for_bootstrapping,
222 encryptor, &old_keystore_keys_, &keystore_key_);
223 }
224
225 SyncEncryptionHandlerImpl::~SyncEncryptionHandlerImpl() {}
226
227 void SyncEncryptionHandlerImpl::AddObserver(Observer* observer) {
228 DCHECK(thread_checker_.CalledOnValidThread());
229 DCHECK(!observers_.HasObserver(observer));
230 observers_.AddObserver(observer);
231 }
232
233 void SyncEncryptionHandlerImpl::RemoveObserver(Observer* observer) {
234 DCHECK(thread_checker_.CalledOnValidThread());
235 DCHECK(observers_.HasObserver(observer));
236 observers_.RemoveObserver(observer);
237 }
238
239 void SyncEncryptionHandlerImpl::Init() {
240 DCHECK(thread_checker_.CalledOnValidThread());
241 WriteTransaction trans(FROM_HERE, user_share_);
242 WriteNode node(&trans);
243
244 if (node.InitTypeRoot(NIGORI) != BaseNode::INIT_OK)
245 return;
246 if (!ApplyNigoriUpdateImpl(node.GetNigoriSpecifics(),
247 trans.GetWrappedTrans())) {
248 WriteEncryptionStateToNigori(&trans);
249 }
250
251 UMA_HISTOGRAM_ENUMERATION(
252 "Sync.PassphraseType",
253 static_cast<unsigned>(GetPassphraseType(trans.GetWrappedTrans())),
254 static_cast<unsigned>(PassphraseType::PASSPHRASE_TYPE_SIZE));
255
256 bool has_pending_keys =
257 UnlockVault(trans.GetWrappedTrans()).cryptographer.has_pending_keys();
258 bool is_ready = UnlockVault(trans.GetWrappedTrans()).cryptographer.is_ready();
259 // Log the state of the cryptographer regardless of migration state.
260 UMA_HISTOGRAM_BOOLEAN("Sync.CryptographerReady", is_ready);
261 UMA_HISTOGRAM_BOOLEAN("Sync.CryptographerPendingKeys", has_pending_keys);
262 if (IsNigoriMigratedToKeystore(node.GetNigoriSpecifics())) {
263 // This account has a nigori node that has been migrated to support
264 // keystore.
265 UMA_HISTOGRAM_ENUMERATION("Sync.NigoriMigrationState", MIGRATED,
266 MIGRATION_STATE_SIZE);
267 if (has_pending_keys &&
268 GetPassphraseType(trans.GetWrappedTrans()) ==
269 PassphraseType::KEYSTORE_PASSPHRASE) {
270 // If this is happening, it means the keystore decryptor is either
271 // undecryptable with the available keystore keys or does not match the
272 // nigori keybag's encryption key. Otherwise we're simply missing the
273 // keystore key.
274 UMA_HISTOGRAM_BOOLEAN("Sync.KeystoreDecryptionFailed",
275 !keystore_key_.empty());
276 }
277 } else if (!is_ready) {
278 // Migration cannot occur until the cryptographer is ready (initialized
279 // with GAIA password and any pending keys resolved).
280 UMA_HISTOGRAM_ENUMERATION("Sync.NigoriMigrationState",
281 NOT_MIGRATED_CRYPTO_NOT_READY,
282 MIGRATION_STATE_SIZE);
283 } else if (keystore_key_.empty()) {
284 // The client has no keystore key, either because it is not yet enabled or
285 // the server is not sending a valid keystore key.
286 UMA_HISTOGRAM_ENUMERATION("Sync.NigoriMigrationState",
287 NOT_MIGRATED_NO_KEYSTORE_KEY,
288 MIGRATION_STATE_SIZE);
289 } else {
290 // If the above conditions have been met and the nigori node is still not
291 // migrated, something failed in the migration process.
292 UMA_HISTOGRAM_ENUMERATION("Sync.NigoriMigrationState",
293 NOT_MIGRATED_UNKNOWN_REASON,
294 MIGRATION_STATE_SIZE);
295 }
296
297 // Always trigger an encrypted types and cryptographer state change event at
298 // init time so observers get the initial values.
299 FOR_EACH_OBSERVER(Observer, observers_,
300 OnEncryptedTypesChanged(
301 UnlockVault(trans.GetWrappedTrans()).encrypted_types,
302 encrypt_everything_));
303 FOR_EACH_OBSERVER(
304 SyncEncryptionHandler::Observer, observers_,
305 OnCryptographerStateChanged(
306 &UnlockVaultMutable(trans.GetWrappedTrans())->cryptographer));
307
308 // If the cryptographer is not ready (either it has pending keys or we
309 // failed to initialize it), we don't want to try and re-encrypt the data.
310 // If we had encrypted types, the DataTypeManager will block, preventing
311 // sync from happening until the the passphrase is provided.
312 if (UnlockVault(trans.GetWrappedTrans()).cryptographer.is_ready())
313 ReEncryptEverything(&trans);
314 }
315
316 void SyncEncryptionHandlerImpl::SetEncryptionPassphrase(
317 const std::string& passphrase,
318 bool is_explicit) {
319 DCHECK(thread_checker_.CalledOnValidThread());
320 // We do not accept empty passphrases.
321 if (passphrase.empty()) {
322 NOTREACHED() << "Cannot encrypt with an empty passphrase.";
323 return;
324 }
325
326 // All accesses to the cryptographer are protected by a transaction.
327 WriteTransaction trans(FROM_HERE, user_share_);
328 KeyParams key_params = {"localhost", "dummy", passphrase};
329 WriteNode node(&trans);
330 if (node.InitTypeRoot(NIGORI) != BaseNode::INIT_OK) {
331 NOTREACHED();
332 return;
333 }
334
335 Cryptographer* cryptographer =
336 &UnlockVaultMutable(trans.GetWrappedTrans())->cryptographer;
337
338 // Once we've migrated to keystore, the only way to set a passphrase for
339 // encryption is to set a custom passphrase.
340 if (IsNigoriMigratedToKeystore(node.GetNigoriSpecifics())) {
341 if (!is_explicit) {
342 // The user is setting a new implicit passphrase. At this point we don't
343 // care, so drop it on the floor. This is safe because if we have a
344 // migrated nigori node, then we don't need to create an initial
345 // encryption key.
346 LOG(WARNING) << "Ignoring new implicit passphrase. Keystore migration "
347 << "already performed.";
348 return;
349 }
350 // Will fail if we already have an explicit passphrase or we have pending
351 // keys.
352 SetCustomPassphrase(passphrase, &trans, &node);
353
354 // When keystore migration occurs, the "CustomEncryption" UMA stat must be
355 // logged as true.
356 UMA_HISTOGRAM_BOOLEAN("Sync.CustomEncryption", true);
357 return;
358 }
359
360 std::string bootstrap_token;
361 sync_pb::EncryptedData pending_keys;
362 if (cryptographer->has_pending_keys())
363 pending_keys = cryptographer->GetPendingKeys();
364 bool success = false;
365 PassphraseType* passphrase_type =
366 &UnlockVaultMutable(trans.GetWrappedTrans())->passphrase_type;
367 // There are six cases to handle here:
368 // 1. The user has no pending keys and is setting their current GAIA password
369 // as the encryption passphrase. This happens either during first time sync
370 // with a clean profile, or after re-authenticating on a profile that was
371 // already signed in with the cryptographer ready.
372 // 2. The user has no pending keys, and is overwriting an (already provided)
373 // implicit passphrase with an explicit (custom) passphrase.
374 // 3. The user has pending keys for an explicit passphrase that is somehow set
375 // to their current GAIA passphrase.
376 // 4. The user has pending keys encrypted with their current GAIA passphrase
377 // and the caller passes in the current GAIA passphrase.
378 // 5. The user has pending keys encrypted with an older GAIA passphrase
379 // and the caller passes in the current GAIA passphrase.
380 // 6. The user has previously done encryption with an explicit passphrase.
381 // Furthermore, we enforce the fact that the bootstrap encryption token will
382 // always be derived from the newest GAIA password if the account is using
383 // an implicit passphrase (even if the data is encrypted with an old GAIA
384 // password). If the account is using an explicit (custom) passphrase, the
385 // bootstrap token will be derived from the most recently provided explicit
386 // passphrase (that was able to decrypt the data).
387 if (!IsExplicitPassphrase(*passphrase_type)) {
388 if (!cryptographer->has_pending_keys()) {
389 if (cryptographer->AddKey(key_params)) {
390 // Case 1 and 2. We set a new GAIA passphrase when there are no pending
391 // keys (1), or overwriting an implicit passphrase with a new explicit
392 // one (2) when there are no pending keys.
393 if (is_explicit) {
394 DVLOG(1) << "Setting explicit passphrase for encryption.";
395 *passphrase_type = PassphraseType::CUSTOM_PASSPHRASE;
396 custom_passphrase_time_ = base::Time::Now();
397 FOR_EACH_OBSERVER(SyncEncryptionHandler::Observer, observers_,
398 OnPassphraseTypeChanged(
399 *passphrase_type,
400 GetExplicitPassphraseTime(*passphrase_type)));
401 } else {
402 DVLOG(1) << "Setting implicit passphrase for encryption.";
403 }
404 cryptographer->GetBootstrapToken(&bootstrap_token);
405
406 // With M26, sync accounts can be in only one of two encryption states:
407 // 1) Encrypt only passwords with an implicit passphrase.
408 // 2) Encrypt all sync datatypes with an explicit passphrase.
409 // We deprecate the "EncryptAllData" and "CustomPassphrase" histograms,
410 // and keep track of an account's encryption state via the
411 // "CustomEncryption" histogram. See http://crbug.com/131478.
412 UMA_HISTOGRAM_BOOLEAN("Sync.CustomEncryption", is_explicit);
413
414 success = true;
415 } else {
416 NOTREACHED() << "Failed to add key to cryptographer.";
417 success = false;
418 }
419 } else { // cryptographer->has_pending_keys() == true
420 if (is_explicit) {
421 // This can only happen if the nigori node is updated with a new
422 // implicit passphrase while a client is attempting to set a new custom
423 // passphrase (race condition).
424 DVLOG(1) << "Failing because an implicit passphrase is already set.";
425 success = false;
426 } else { // is_explicit == false
427 if (cryptographer->DecryptPendingKeys(key_params)) {
428 // Case 4. We successfully decrypted with the implicit GAIA passphrase
429 // passed in.
430 DVLOG(1) << "Implicit internal passphrase accepted for decryption.";
431 cryptographer->GetBootstrapToken(&bootstrap_token);
432 success = true;
433 } else {
434 // Case 5. Encryption was done with an old GAIA password, but we were
435 // provided with the current GAIA password. We need to generate a new
436 // bootstrap token to preserve it. We build a temporary cryptographer
437 // to allow us to extract these params without polluting our current
438 // cryptographer.
439 DVLOG(1) << "Implicit internal passphrase failed to decrypt, adding "
440 << "anyways as default passphrase and persisting via "
441 << "bootstrap token.";
442 Cryptographer temp_cryptographer(cryptographer->encryptor());
443 temp_cryptographer.AddKey(key_params);
444 temp_cryptographer.GetBootstrapToken(&bootstrap_token);
445 // We then set the new passphrase as the default passphrase of the
446 // real cryptographer, even though we have pending keys. This is safe,
447 // as although Cryptographer::is_initialized() will now be true,
448 // is_ready() will remain false due to having pending keys.
449 cryptographer->AddKey(key_params);
450 success = false;
451 }
452 } // is_explicit
453 } // cryptographer->has_pending_keys()
454 } else { // IsExplicitPassphrase(passphrase_type) == true.
455 // Case 6. We do not want to override a previously set explicit passphrase,
456 // so we return a failure.
457 DVLOG(1) << "Failing because an explicit passphrase is already set.";
458 success = false;
459 }
460
461 DVLOG_IF(1, !success)
462 << "Failure in SetEncryptionPassphrase; notifying and returning.";
463 DVLOG_IF(1, success)
464 << "Successfully set encryption passphrase; updating nigori and "
465 "reencrypting.";
466
467 FinishSetPassphrase(success, bootstrap_token, &trans, &node);
468 }
469
470 void SyncEncryptionHandlerImpl::SetDecryptionPassphrase(
471 const std::string& passphrase) {
472 DCHECK(thread_checker_.CalledOnValidThread());
473 // We do not accept empty passphrases.
474 if (passphrase.empty()) {
475 NOTREACHED() << "Cannot decrypt with an empty passphrase.";
476 return;
477 }
478
479 // All accesses to the cryptographer are protected by a transaction.
480 WriteTransaction trans(FROM_HERE, user_share_);
481 KeyParams key_params = {"localhost", "dummy", passphrase};
482 WriteNode node(&trans);
483 if (node.InitTypeRoot(NIGORI) != BaseNode::INIT_OK) {
484 NOTREACHED();
485 return;
486 }
487
488 // Once we've migrated to keystore, we're only ever decrypting keys derived
489 // from an explicit passphrase. But, for clients without a keystore key yet
490 // (either not on by default or failed to download one), we still support
491 // decrypting with a gaia passphrase, and therefore bypass the
492 // DecryptPendingKeysWithExplicitPassphrase logic.
493 if (IsNigoriMigratedToKeystore(node.GetNigoriSpecifics()) &&
494 IsExplicitPassphrase(GetPassphraseType(trans.GetWrappedTrans()))) {
495 DecryptPendingKeysWithExplicitPassphrase(passphrase, &trans, &node);
496 return;
497 }
498
499 Cryptographer* cryptographer =
500 &UnlockVaultMutable(trans.GetWrappedTrans())->cryptographer;
501 if (!cryptographer->has_pending_keys()) {
502 // Note that this *can* happen in a rare situation where data is
503 // re-encrypted on another client while a SetDecryptionPassphrase() call is
504 // in-flight on this client. It is rare enough that we choose to do nothing.
505 NOTREACHED() << "Attempt to set decryption passphrase failed because there "
506 << "were no pending keys.";
507 return;
508 }
509
510 std::string bootstrap_token;
511 sync_pb::EncryptedData pending_keys;
512 pending_keys = cryptographer->GetPendingKeys();
513 bool success = false;
514
515 // There are three cases to handle here:
516 // 7. We're using the current GAIA password to decrypt the pending keys. This
517 // happens when signing in to an account with a previously set implicit
518 // passphrase, where the data is already encrypted with the newest GAIA
519 // password.
520 // 8. The user is providing an old GAIA password to decrypt the pending keys.
521 // In this case, the user is using an implicit passphrase, but has changed
522 // their password since they last encrypted their data, and therefore
523 // their current GAIA password was unable to decrypt the data. This will
524 // happen when the user is setting up a new profile with a previously
525 // encrypted account (after changing passwords).
526 // 9. The user is providing a previously set explicit passphrase to decrypt
527 // the pending keys.
528 if (!IsExplicitPassphrase(GetPassphraseType(trans.GetWrappedTrans()))) {
529 if (cryptographer->is_initialized()) {
530 // We only want to change the default encryption key to the pending
531 // one if the pending keybag already contains the current default.
532 // This covers the case where a different client re-encrypted
533 // everything with a newer gaia passphrase (and hence the keybag
534 // contains keys from all previously used gaia passphrases).
535 // Otherwise, we're in a situation where the pending keys are
536 // encrypted with an old gaia passphrase, while the default is the
537 // current gaia passphrase. In that case, we preserve the default.
538 Cryptographer temp_cryptographer(cryptographer->encryptor());
539 temp_cryptographer.SetPendingKeys(cryptographer->GetPendingKeys());
540 if (temp_cryptographer.DecryptPendingKeys(key_params)) {
541 // Check to see if the pending bag of keys contains the current
542 // default key.
543 sync_pb::EncryptedData encrypted;
544 cryptographer->GetKeys(&encrypted);
545 if (temp_cryptographer.CanDecrypt(encrypted)) {
546 DVLOG(1) << "Implicit user provided passphrase accepted for "
547 << "decryption, overwriting default.";
548 // Case 7. The pending keybag contains the current default. Go ahead
549 // and update the cryptographer, letting the default change.
550 cryptographer->DecryptPendingKeys(key_params);
551 cryptographer->GetBootstrapToken(&bootstrap_token);
552 success = true;
553 } else {
554 // Case 8. The pending keybag does not contain the current default
555 // encryption key. We decrypt the pending keys here, and in
556 // FinishSetPassphrase, re-encrypt everything with the current GAIA
557 // passphrase instead of the passphrase just provided by the user.
558 DVLOG(1) << "Implicit user provided passphrase accepted for "
559 << "decryption, restoring implicit internal passphrase "
560 << "as default.";
561 std::string bootstrap_token_from_current_key;
562 cryptographer->GetBootstrapToken(&bootstrap_token_from_current_key);
563 cryptographer->DecryptPendingKeys(key_params);
564 // Overwrite the default from the pending keys.
565 cryptographer->AddKeyFromBootstrapToken(
566 bootstrap_token_from_current_key);
567 success = true;
568 }
569 } else { // !temp_cryptographer.DecryptPendingKeys(..)
570 DVLOG(1) << "Implicit user provided passphrase failed to decrypt.";
571 success = false;
572 } // temp_cryptographer.DecryptPendingKeys(...)
573 } else { // cryptographer->is_initialized() == false
574 if (cryptographer->DecryptPendingKeys(key_params)) {
575 // This can happpen in two cases:
576 // - First time sync on android, where we'll never have a
577 // !user_provided passphrase.
578 // - This is a restart for a client that lost their bootstrap token.
579 // In both cases, we should go ahead and initialize the cryptographer
580 // and persist the new bootstrap token.
581 //
582 // Note: at this point, we cannot distinguish between cases 7 and 8
583 // above. This user provided passphrase could be the current or the
584 // old. But, as long as we persist the token, there's nothing more
585 // we can do.
586 cryptographer->GetBootstrapToken(&bootstrap_token);
587 DVLOG(1) << "Implicit user provided passphrase accepted, initializing"
588 << " cryptographer.";
589 success = true;
590 } else {
591 DVLOG(1) << "Implicit user provided passphrase failed to decrypt.";
592 success = false;
593 }
594 } // cryptographer->is_initialized()
595 } else { // nigori_has_explicit_passphrase == true
596 // Case 9. Encryption was done with an explicit passphrase, and we decrypt
597 // with the passphrase provided by the user.
598 if (cryptographer->DecryptPendingKeys(key_params)) {
599 DVLOG(1) << "Explicit passphrase accepted for decryption.";
600 cryptographer->GetBootstrapToken(&bootstrap_token);
601 success = true;
602 } else {
603 DVLOG(1) << "Explicit passphrase failed to decrypt.";
604 success = false;
605 }
606 } // nigori_has_explicit_passphrase
607
608 DVLOG_IF(1, !success)
609 << "Failure in SetDecryptionPassphrase; notifying and returning.";
610 DVLOG_IF(1, success)
611 << "Successfully set decryption passphrase; updating nigori and "
612 "reencrypting.";
613
614 FinishSetPassphrase(success, bootstrap_token, &trans, &node);
615 }
616
617 void SyncEncryptionHandlerImpl::EnableEncryptEverything() {
618 DCHECK(thread_checker_.CalledOnValidThread());
619 WriteTransaction trans(FROM_HERE, user_share_);
620 DVLOG(1) << "Enabling encrypt everything.";
621 if (encrypt_everything_)
622 return;
623 EnableEncryptEverythingImpl(trans.GetWrappedTrans());
624 WriteEncryptionStateToNigori(&trans);
625 if (UnlockVault(trans.GetWrappedTrans()).cryptographer.is_ready())
626 ReEncryptEverything(&trans);
627 }
628
629 bool SyncEncryptionHandlerImpl::IsEncryptEverythingEnabled() const {
630 DCHECK(thread_checker_.CalledOnValidThread());
631 return encrypt_everything_;
632 }
633
634 // Note: this is called from within a syncable transaction, so we need to post
635 // tasks if we want to do any work that creates a new sync_api transaction.
636 void SyncEncryptionHandlerImpl::ApplyNigoriUpdate(
637 const sync_pb::NigoriSpecifics& nigori,
638 syncable::BaseTransaction* const trans) {
639 DCHECK(thread_checker_.CalledOnValidThread());
640 DCHECK(trans);
641 if (!ApplyNigoriUpdateImpl(nigori, trans)) {
642 base::ThreadTaskRunnerHandle::Get()->PostTask(
643 FROM_HERE, base::Bind(&SyncEncryptionHandlerImpl::RewriteNigori,
644 weak_ptr_factory_.GetWeakPtr()));
645 }
646
647 FOR_EACH_OBSERVER(
648 SyncEncryptionHandler::Observer, observers_,
649 OnCryptographerStateChanged(&UnlockVaultMutable(trans)->cryptographer));
650 }
651
652 void SyncEncryptionHandlerImpl::UpdateNigoriFromEncryptedTypes(
653 sync_pb::NigoriSpecifics* nigori,
654 syncable::BaseTransaction* const trans) const {
655 DCHECK(thread_checker_.CalledOnValidThread());
656 syncable::UpdateNigoriFromEncryptedTypes(UnlockVault(trans).encrypted_types,
657 encrypt_everything_, nigori);
658 }
659
660 bool SyncEncryptionHandlerImpl::NeedKeystoreKey(
661 syncable::BaseTransaction* const trans) const {
662 DCHECK(thread_checker_.CalledOnValidThread());
663 return keystore_key_.empty();
664 }
665
666 bool SyncEncryptionHandlerImpl::SetKeystoreKeys(
667 const google::protobuf::RepeatedPtrField<google::protobuf::string>& keys,
668 syncable::BaseTransaction* const trans) {
669 DCHECK(thread_checker_.CalledOnValidThread());
670 if (keys.size() == 0)
671 return false;
672 // The last key in the vector is the current keystore key. The others are kept
673 // around for decryption only.
674 const std::string& raw_keystore_key = keys.Get(keys.size() - 1);
675 if (raw_keystore_key.empty())
676 return false;
677
678 // Note: in order to Pack the keys, they must all be base64 encoded (else
679 // JSON serialization fails).
680 base::Base64Encode(raw_keystore_key, &keystore_key_);
681
682 // Go through and save the old keystore keys. We always persist all keystore
683 // keys the server sends us.
684 old_keystore_keys_.resize(keys.size() - 1);
685 for (int i = 0; i < keys.size() - 1; ++i)
686 base::Base64Encode(keys.Get(i), &old_keystore_keys_[i]);
687
688 Cryptographer* cryptographer = &UnlockVaultMutable(trans)->cryptographer;
689
690 // Update the bootstrap token. If this fails, we persist an empty string,
691 // which will force us to download the keystore keys again on the next
692 // restart.
693 std::string keystore_bootstrap = PackKeystoreBootstrapToken(
694 old_keystore_keys_, keystore_key_, cryptographer->encryptor());
695
696 FOR_EACH_OBSERVER(
697 SyncEncryptionHandler::Observer, observers_,
698 OnBootstrapTokenUpdated(keystore_bootstrap, KEYSTORE_BOOTSTRAP_TOKEN));
699 DVLOG(1) << "Keystore bootstrap token updated.";
700
701 // If this is a first time sync, we get the encryption keys before we process
702 // the nigori node. Just return for now, ApplyNigoriUpdate will be invoked
703 // once we have the nigori node.
704 syncable::Entry entry(trans, syncable::GET_TYPE_ROOT, NIGORI);
705 if (!entry.good())
706 return true;
707
708 const sync_pb::NigoriSpecifics& nigori = entry.GetSpecifics().nigori();
709 if (cryptographer->has_pending_keys() && IsNigoriMigratedToKeystore(nigori) &&
710 !nigori.keystore_decryptor_token().blob().empty()) {
711 // If the nigori is already migrated and we have pending keys, we might
712 // be able to decrypt them using either the keystore decryptor token
713 // or the existing keystore keys.
714 DecryptPendingKeysWithKeystoreKey(nigori.keystore_decryptor_token(),
715 cryptographer);
716 }
717
718 // Note that triggering migration will have no effect if we're already
719 // properly migrated with the newest keystore keys.
720 if (ShouldTriggerMigration(nigori, *cryptographer,
721 GetPassphraseType(trans))) {
722 base::ThreadTaskRunnerHandle::Get()->PostTask(
723 FROM_HERE, base::Bind(&SyncEncryptionHandlerImpl::RewriteNigori,
724 weak_ptr_factory_.GetWeakPtr()));
725 }
726
727 return true;
728 }
729
730 ModelTypeSet SyncEncryptionHandlerImpl::GetEncryptedTypes(
731 syncable::BaseTransaction* const trans) const {
732 return UnlockVault(trans).encrypted_types;
733 }
734
735 PassphraseType SyncEncryptionHandlerImpl::GetPassphraseType(
736 syncable::BaseTransaction* const trans) const {
737 return UnlockVault(trans).passphrase_type;
738 }
739
740 Cryptographer* SyncEncryptionHandlerImpl::GetCryptographerUnsafe() {
741 DCHECK(thread_checker_.CalledOnValidThread());
742 return &vault_unsafe_.cryptographer;
743 }
744
745 ModelTypeSet SyncEncryptionHandlerImpl::GetEncryptedTypesUnsafe() {
746 DCHECK(thread_checker_.CalledOnValidThread());
747 return vault_unsafe_.encrypted_types;
748 }
749
750 bool SyncEncryptionHandlerImpl::MigratedToKeystore() {
751 DCHECK(thread_checker_.CalledOnValidThread());
752 ReadTransaction trans(FROM_HERE, user_share_);
753 ReadNode nigori_node(&trans);
754 if (nigori_node.InitTypeRoot(NIGORI) != BaseNode::INIT_OK)
755 return false;
756 return IsNigoriMigratedToKeystore(nigori_node.GetNigoriSpecifics());
757 }
758
759 base::Time SyncEncryptionHandlerImpl::migration_time() const {
760 return migration_time_;
761 }
762
763 base::Time SyncEncryptionHandlerImpl::custom_passphrase_time() const {
764 return custom_passphrase_time_;
765 }
766
767 void SyncEncryptionHandlerImpl::RestoreNigori(
768 const SyncEncryptionHandler::NigoriState& nigori_state) {
769 DCHECK(thread_checker_.CalledOnValidThread());
770
771 WriteTransaction trans(FROM_HERE, user_share_);
772
773 // Verify we don't already have a nigori node.
774 WriteNode nigori_node(&trans);
775 BaseNode::InitByLookupResult init_result = nigori_node.InitTypeRoot(NIGORI);
776 DCHECK(init_result == BaseNode::INIT_FAILED_ENTRY_NOT_GOOD);
777
778 // Create one.
779 syncable::ModelNeutralMutableEntry model_neutral_mutable_entry(
780 trans.GetWrappedWriteTrans(), syncable::CREATE_NEW_TYPE_ROOT, NIGORI);
781 DCHECK(model_neutral_mutable_entry.good());
782 model_neutral_mutable_entry.PutServerIsDir(true);
783 model_neutral_mutable_entry.PutUniqueServerTag(ModelTypeToRootTag(NIGORI));
784 model_neutral_mutable_entry.PutIsUnsynced(true);
785
786 // Update it with the saved nigori specifics.
787 syncable::MutableEntry mutable_entry(trans.GetWrappedWriteTrans(),
788 syncable::GET_TYPE_ROOT, NIGORI);
789 DCHECK(mutable_entry.good());
790 sync_pb::EntitySpecifics specifics;
791 specifics.mutable_nigori()->CopyFrom(nigori_state.nigori_specifics);
792 mutable_entry.PutSpecifics(specifics);
793
794 // Update our state based on the saved nigori node.
795 ApplyNigoriUpdate(nigori_state.nigori_specifics, trans.GetWrappedTrans());
796 }
797
798 // This function iterates over all encrypted types. There are many scenarios in
799 // which data for some or all types is not currently available. In that case,
800 // the lookup of the root node will fail and we will skip encryption for that
801 // type.
802 void SyncEncryptionHandlerImpl::ReEncryptEverything(WriteTransaction* trans) {
803 DCHECK(thread_checker_.CalledOnValidThread());
804 DCHECK(UnlockVault(trans->GetWrappedTrans()).cryptographer.is_ready());
805 for (ModelTypeSet::Iterator iter =
806 UnlockVault(trans->GetWrappedTrans()).encrypted_types.First();
807 iter.Good(); iter.Inc()) {
808 if (iter.Get() == PASSWORDS || IsControlType(iter.Get()))
809 continue; // These types handle encryption differently.
810
811 ReadNode type_root(trans);
812 if (type_root.InitTypeRoot(iter.Get()) != BaseNode::INIT_OK)
813 continue; // Don't try to reencrypt if the type's data is unavailable.
814
815 // Iterate through all children of this datatype.
816 std::queue<int64_t> to_visit;
817 int64_t child_id = type_root.GetFirstChildId();
818 to_visit.push(child_id);
819 while (!to_visit.empty()) {
820 child_id = to_visit.front();
821 to_visit.pop();
822 if (child_id == kInvalidId)
823 continue;
824
825 WriteNode child(trans);
826 if (child.InitByIdLookup(child_id) != BaseNode::INIT_OK)
827 continue; // Possible for locally deleted items.
828 if (child.GetIsFolder()) {
829 to_visit.push(child.GetFirstChildId());
830 }
831 if (!child.GetIsPermanentFolder()) {
832 // Rewrite the specifics of the node with encrypted data if necessary
833 // (only rewrite the non-unique folders).
834 child.ResetFromSpecifics();
835 }
836 to_visit.push(child.GetSuccessorId());
837 }
838 }
839
840 // Passwords are encrypted with their own legacy scheme. Passwords are always
841 // encrypted so we don't need to check GetEncryptedTypes() here.
842 ReadNode passwords_root(trans);
843 if (passwords_root.InitTypeRoot(PASSWORDS) == BaseNode::INIT_OK) {
844 int64_t child_id = passwords_root.GetFirstChildId();
845 while (child_id != kInvalidId) {
846 WriteNode child(trans);
847 if (child.InitByIdLookup(child_id) != BaseNode::INIT_OK)
848 break; // Possible if we failed to decrypt the data for some reason.
849 child.SetPasswordSpecifics(child.GetPasswordSpecifics());
850 child_id = child.GetSuccessorId();
851 }
852 }
853
854 DVLOG(1) << "Re-encrypt everything complete.";
855
856 // NOTE: We notify from within a transaction.
857 FOR_EACH_OBSERVER(SyncEncryptionHandler::Observer, observers_,
858 OnEncryptionComplete());
859 }
860
861 bool SyncEncryptionHandlerImpl::ApplyNigoriUpdateImpl(
862 const sync_pb::NigoriSpecifics& nigori,
863 syncable::BaseTransaction* const trans) {
864 DCHECK(thread_checker_.CalledOnValidThread());
865 DVLOG(1) << "Applying nigori node update.";
866 bool nigori_types_need_update =
867 !UpdateEncryptedTypesFromNigori(nigori, trans);
868
869 if (nigori.custom_passphrase_time() != 0) {
870 custom_passphrase_time_ = ProtoTimeToTime(nigori.custom_passphrase_time());
871 }
872 bool is_nigori_migrated = IsNigoriMigratedToKeystore(nigori);
873 PassphraseType* passphrase_type = &UnlockVaultMutable(trans)->passphrase_type;
874 if (is_nigori_migrated) {
875 migration_time_ = ProtoTimeToTime(nigori.keystore_migration_time());
876 PassphraseType nigori_passphrase_type =
877 ProtoPassphraseTypeToEnum(nigori.passphrase_type());
878
879 // Only update the local passphrase state if it's a valid transition:
880 // - implicit -> keystore
881 // - implicit -> frozen implicit
882 // - implicit -> custom
883 // - keystore -> custom
884 // Note: frozen implicit -> custom is not technically a valid transition,
885 // but we let it through here as well in case future versions do add support
886 // for this transition.
887 if (*passphrase_type != nigori_passphrase_type &&
888 nigori_passphrase_type != PassphraseType::IMPLICIT_PASSPHRASE &&
889 (*passphrase_type == PassphraseType::IMPLICIT_PASSPHRASE ||
890 nigori_passphrase_type == PassphraseType::CUSTOM_PASSPHRASE)) {
891 DVLOG(1) << "Changing passphrase state from "
892 << PassphraseTypeToString(*passphrase_type) << " to "
893 << PassphraseTypeToString(nigori_passphrase_type);
894 *passphrase_type = nigori_passphrase_type;
895 FOR_EACH_OBSERVER(
896 SyncEncryptionHandler::Observer, observers_,
897 OnPassphraseTypeChanged(*passphrase_type,
898 GetExplicitPassphraseTime(*passphrase_type)));
899 }
900 if (*passphrase_type == PassphraseType::KEYSTORE_PASSPHRASE &&
901 encrypt_everything_) {
902 // This is the case where another client that didn't support keystore
903 // encryption attempted to enable full encryption. We detect it
904 // and switch the passphrase type to frozen implicit passphrase instead
905 // due to full encryption not being compatible with keystore passphrase.
906 // Because the local passphrase type will not match the nigori passphrase
907 // type, we will trigger a rewrite and subsequently a re-migration.
908 DVLOG(1) << "Changing passphrase state to FROZEN_IMPLICIT_PASSPHRASE "
909 << "due to full encryption.";
910 *passphrase_type = PassphraseType::FROZEN_IMPLICIT_PASSPHRASE;
911 FOR_EACH_OBSERVER(
912 SyncEncryptionHandler::Observer, observers_,
913 OnPassphraseTypeChanged(*passphrase_type,
914 GetExplicitPassphraseTime(*passphrase_type)));
915 }
916 } else {
917 // It's possible that while we're waiting for migration a client that does
918 // not have keystore encryption enabled switches to a custom passphrase.
919 if (nigori.keybag_is_frozen() &&
920 *passphrase_type != PassphraseType::CUSTOM_PASSPHRASE) {
921 *passphrase_type = PassphraseType::CUSTOM_PASSPHRASE;
922 FOR_EACH_OBSERVER(
923 SyncEncryptionHandler::Observer, observers_,
924 OnPassphraseTypeChanged(*passphrase_type,
925 GetExplicitPassphraseTime(*passphrase_type)));
926 }
927 }
928
929 Cryptographer* cryptographer = &UnlockVaultMutable(trans)->cryptographer;
930 bool nigori_needs_new_keys = false;
931 if (!nigori.encryption_keybag().blob().empty()) {
932 // We only update the default key if this was a new explicit passphrase.
933 // Else, since it was decryptable, it must not have been a new key.
934 bool need_new_default_key = false;
935 if (is_nigori_migrated) {
936 need_new_default_key = IsExplicitPassphrase(
937 ProtoPassphraseTypeToEnum(nigori.passphrase_type()));
938 } else {
939 need_new_default_key = nigori.keybag_is_frozen();
940 }
941 if (!AttemptToInstallKeybag(nigori.encryption_keybag(),
942 need_new_default_key, cryptographer)) {
943 // Check to see if we can decrypt the keybag using the keystore decryptor
944 // token.
945 cryptographer->SetPendingKeys(nigori.encryption_keybag());
946 if (!nigori.keystore_decryptor_token().blob().empty() &&
947 !keystore_key_.empty()) {
948 if (DecryptPendingKeysWithKeystoreKey(nigori.keystore_decryptor_token(),
949 cryptographer)) {
950 nigori_needs_new_keys =
951 cryptographer->KeybagIsStale(nigori.encryption_keybag());
952 } else {
953 LOG(ERROR) << "Failed to decrypt pending keys using keystore "
954 << "bootstrap key.";
955 }
956 }
957 } else {
958 // Keybag was installed. We write back our local keybag into the nigori
959 // node if the nigori node's keybag either contains less keys or
960 // has a different default key.
961 nigori_needs_new_keys =
962 cryptographer->KeybagIsStale(nigori.encryption_keybag());
963 }
964 } else {
965 // The nigori node has an empty encryption keybag. Attempt to write our
966 // local encryption keys into it.
967 LOG(WARNING) << "Nigori had empty encryption keybag.";
968 nigori_needs_new_keys = true;
969 }
970
971 // If we've completed a sync cycle and the cryptographer isn't ready
972 // yet or has pending keys, prompt the user for a passphrase.
973 if (cryptographer->has_pending_keys()) {
974 DVLOG(1) << "OnPassphraseRequired Sent";
975 sync_pb::EncryptedData pending_keys = cryptographer->GetPendingKeys();
976 FOR_EACH_OBSERVER(SyncEncryptionHandler::Observer, observers_,
977 OnPassphraseRequired(REASON_DECRYPTION, pending_keys));
978 } else if (!cryptographer->is_ready()) {
979 DVLOG(1) << "OnPassphraseRequired sent because cryptographer is not "
980 << "ready";
981 FOR_EACH_OBSERVER(
982 SyncEncryptionHandler::Observer, observers_,
983 OnPassphraseRequired(REASON_ENCRYPTION, sync_pb::EncryptedData()));
984 }
985
986 // Check if the current local encryption state is stricter/newer than the
987 // nigori state. If so, we need to overwrite the nigori node with the local
988 // state.
989 bool passphrase_type_matches = true;
990 if (!is_nigori_migrated) {
991 DCHECK(*passphrase_type == PassphraseType::CUSTOM_PASSPHRASE ||
992 *passphrase_type == PassphraseType::IMPLICIT_PASSPHRASE);
993 passphrase_type_matches =
994 nigori.keybag_is_frozen() == IsExplicitPassphrase(*passphrase_type);
995 } else {
996 passphrase_type_matches =
997 (ProtoPassphraseTypeToEnum(nigori.passphrase_type()) ==
998 *passphrase_type);
999 }
1000 if (!passphrase_type_matches ||
1001 nigori.encrypt_everything() != encrypt_everything_ ||
1002 nigori_types_need_update || nigori_needs_new_keys) {
1003 DVLOG(1) << "Triggering nigori rewrite.";
1004 return false;
1005 }
1006 return true;
1007 }
1008
1009 void SyncEncryptionHandlerImpl::RewriteNigori() {
1010 DVLOG(1) << "Writing local encryption state into nigori.";
1011 DCHECK(thread_checker_.CalledOnValidThread());
1012 WriteTransaction trans(FROM_HERE, user_share_);
1013 WriteEncryptionStateToNigori(&trans);
1014 }
1015
1016 void SyncEncryptionHandlerImpl::WriteEncryptionStateToNigori(
1017 WriteTransaction* trans) {
1018 DCHECK(thread_checker_.CalledOnValidThread());
1019 WriteNode nigori_node(trans);
1020 // This can happen in tests that don't have nigori nodes.
1021 if (nigori_node.InitTypeRoot(NIGORI) != BaseNode::INIT_OK)
1022 return;
1023
1024 sync_pb::NigoriSpecifics nigori = nigori_node.GetNigoriSpecifics();
1025 const Cryptographer& cryptographer =
1026 UnlockVault(trans->GetWrappedTrans()).cryptographer;
1027
1028 // Will not do anything if we shouldn't or can't migrate. Otherwise
1029 // migrates, writing the full encryption state as it does.
1030 if (!AttemptToMigrateNigoriToKeystore(trans, &nigori_node)) {
1031 if (cryptographer.is_ready() &&
1032 nigori_overwrite_count_ < kNigoriOverwriteLimit) {
1033 // Does not modify the encrypted blob if the unencrypted data already
1034 // matches what is about to be written.
1035 sync_pb::EncryptedData original_keys = nigori.encryption_keybag();
1036 if (!cryptographer.GetKeys(nigori.mutable_encryption_keybag()))
1037 NOTREACHED();
1038
1039 if (nigori.encryption_keybag().SerializeAsString() !=
1040 original_keys.SerializeAsString()) {
1041 // We've updated the nigori node's encryption keys. In order to prevent
1042 // a possible looping of two clients constantly overwriting each other,
1043 // we limit the absolute number of overwrites per client instantiation.
1044 nigori_overwrite_count_++;
1045 UMA_HISTOGRAM_COUNTS("Sync.AutoNigoriOverwrites",
1046 nigori_overwrite_count_);
1047 }
1048
1049 // Note: we don't try to set keybag_is_frozen here since if that
1050 // is lost the user can always set it again (and we don't want to clobber
1051 // any migration state). The main goal at this point is to preserve
1052 // the encryption keys so all data remains decryptable.
1053 }
1054 syncable::UpdateNigoriFromEncryptedTypes(
1055 UnlockVault(trans->GetWrappedTrans()).encrypted_types,
1056 encrypt_everything_, &nigori);
1057 if (!custom_passphrase_time_.is_null()) {
1058 nigori.set_custom_passphrase_time(
1059 TimeToProtoTime(custom_passphrase_time_));
1060 }
1061
1062 // If nothing has changed, this is a no-op.
1063 nigori_node.SetNigoriSpecifics(nigori);
1064 }
1065 }
1066
1067 bool SyncEncryptionHandlerImpl::UpdateEncryptedTypesFromNigori(
1068 const sync_pb::NigoriSpecifics& nigori,
1069 syncable::BaseTransaction* const trans) {
1070 DCHECK(thread_checker_.CalledOnValidThread());
1071 ModelTypeSet* encrypted_types = &UnlockVaultMutable(trans)->encrypted_types;
1072 if (nigori.encrypt_everything()) {
1073 EnableEncryptEverythingImpl(trans);
1074 DCHECK(*encrypted_types == EncryptableUserTypes());
1075 return true;
1076 } else if (encrypt_everything_) {
1077 DCHECK(*encrypted_types == EncryptableUserTypes());
1078 return false;
1079 }
1080
1081 ModelTypeSet nigori_encrypted_types;
1082 nigori_encrypted_types = syncable::GetEncryptedTypesFromNigori(nigori);
1083 nigori_encrypted_types.PutAll(SensitiveTypes());
1084
1085 // If anything more than the sensitive types were encrypted, and
1086 // encrypt_everything is not explicitly set to false, we assume it means
1087 // a client intended to enable encrypt everything.
1088 if (!nigori.has_encrypt_everything() &&
1089 !Difference(nigori_encrypted_types, SensitiveTypes()).Empty()) {
1090 if (!encrypt_everything_) {
1091 encrypt_everything_ = true;
1092 *encrypted_types = EncryptableUserTypes();
1093 FOR_EACH_OBSERVER(
1094 Observer, observers_,
1095 OnEncryptedTypesChanged(*encrypted_types, encrypt_everything_));
1096 }
1097 DCHECK(*encrypted_types == EncryptableUserTypes());
1098 return false;
1099 }
1100
1101 MergeEncryptedTypes(nigori_encrypted_types, trans);
1102 return *encrypted_types == nigori_encrypted_types;
1103 }
1104
1105 void SyncEncryptionHandlerImpl::SetCustomPassphrase(
1106 const std::string& passphrase,
1107 WriteTransaction* trans,
1108 WriteNode* nigori_node) {
1109 DCHECK(thread_checker_.CalledOnValidThread());
1110 DCHECK(IsNigoriMigratedToKeystore(nigori_node->GetNigoriSpecifics()));
1111 KeyParams key_params = {"localhost", "dummy", passphrase};
1112
1113 if (GetPassphraseType(trans->GetWrappedTrans()) !=
1114 PassphraseType::KEYSTORE_PASSPHRASE) {
1115 DVLOG(1) << "Failing to set a custom passphrase because one has already "
1116 << "been set.";
1117 FinishSetPassphrase(false, std::string(), trans, nigori_node);
1118 return;
1119 }
1120
1121 Cryptographer* cryptographer =
1122 &UnlockVaultMutable(trans->GetWrappedTrans())->cryptographer;
1123 if (cryptographer->has_pending_keys()) {
1124 // This theoretically shouldn't happen, because the only way to have pending
1125 // keys after migrating to keystore support is if a custom passphrase was
1126 // set, which should update passpshrase_state_ and should be caught by the
1127 // if statement above. For the sake of safety though, we check for it in
1128 // case a client is misbehaving.
1129 LOG(ERROR) << "Failing to set custom passphrase because of pending keys.";
1130 FinishSetPassphrase(false, std::string(), trans, nigori_node);
1131 return;
1132 }
1133
1134 std::string bootstrap_token;
1135 if (!cryptographer->AddKey(key_params)) {
1136 NOTREACHED() << "Failed to add key to cryptographer.";
1137 return;
1138 }
1139
1140 DVLOG(1) << "Setting custom passphrase.";
1141 cryptographer->GetBootstrapToken(&bootstrap_token);
1142 PassphraseType* passphrase_type =
1143 &UnlockVaultMutable(trans->GetWrappedTrans())->passphrase_type;
1144 *passphrase_type = PassphraseType::CUSTOM_PASSPHRASE;
1145 custom_passphrase_time_ = base::Time::Now();
1146 FOR_EACH_OBSERVER(
1147 SyncEncryptionHandler::Observer, observers_,
1148 OnPassphraseTypeChanged(*passphrase_type,
1149 GetExplicitPassphraseTime(*passphrase_type)));
1150 FinishSetPassphrase(true, bootstrap_token, trans, nigori_node);
1151 }
1152
1153 void SyncEncryptionHandlerImpl::NotifyObserversOfLocalCustomPassphrase(
1154 WriteTransaction* trans) {
1155 WriteNode nigori_node(trans);
1156 BaseNode::InitByLookupResult init_result = nigori_node.InitTypeRoot(NIGORI);
1157 DCHECK_EQ(init_result, BaseNode::INIT_OK);
1158 NigoriState nigori_state;
1159 nigori_state.nigori_specifics = nigori_node.GetNigoriSpecifics();
1160 DCHECK(nigori_state.nigori_specifics.passphrase_type() ==
1161 sync_pb::NigoriSpecifics::CUSTOM_PASSPHRASE ||
1162 nigori_state.nigori_specifics.passphrase_type() ==
1163 sync_pb::NigoriSpecifics::FROZEN_IMPLICIT_PASSPHRASE);
1164 FOR_EACH_OBSERVER(SyncEncryptionHandler::Observer, observers_,
1165 OnLocalSetPassphraseEncryption(nigori_state));
1166 }
1167
1168 void SyncEncryptionHandlerImpl::DecryptPendingKeysWithExplicitPassphrase(
1169 const std::string& passphrase,
1170 WriteTransaction* trans,
1171 WriteNode* nigori_node) {
1172 DCHECK(thread_checker_.CalledOnValidThread());
1173 DCHECK(IsExplicitPassphrase(GetPassphraseType(trans->GetWrappedTrans())));
1174 KeyParams key_params = {"localhost", "dummy", passphrase};
1175
1176 Cryptographer* cryptographer =
1177 &UnlockVaultMutable(trans->GetWrappedTrans())->cryptographer;
1178 if (!cryptographer->has_pending_keys()) {
1179 // Note that this *can* happen in a rare situation where data is
1180 // re-encrypted on another client while a SetDecryptionPassphrase() call is
1181 // in-flight on this client. It is rare enough that we choose to do nothing.
1182 NOTREACHED() << "Attempt to set decryption passphrase failed because there "
1183 << "were no pending keys.";
1184 return;
1185 }
1186
1187 DCHECK(IsExplicitPassphrase(GetPassphraseType(trans->GetWrappedTrans())));
1188 bool success = false;
1189 std::string bootstrap_token;
1190 if (cryptographer->DecryptPendingKeys(key_params)) {
1191 DVLOG(1) << "Explicit passphrase accepted for decryption.";
1192 cryptographer->GetBootstrapToken(&bootstrap_token);
1193 success = true;
1194 } else {
1195 DVLOG(1) << "Explicit passphrase failed to decrypt.";
1196 success = false;
1197 }
1198 if (success && !keystore_key_.empty()) {
1199 // Should already be part of the encryption keybag, but we add it just
1200 // in case.
1201 KeyParams key_params = {"localhost", "dummy", keystore_key_};
1202 cryptographer->AddNonDefaultKey(key_params);
1203 }
1204 FinishSetPassphrase(success, bootstrap_token, trans, nigori_node);
1205 }
1206
1207 void SyncEncryptionHandlerImpl::FinishSetPassphrase(
1208 bool success,
1209 const std::string& bootstrap_token,
1210 WriteTransaction* trans,
1211 WriteNode* nigori_node) {
1212 DCHECK(thread_checker_.CalledOnValidThread());
1213 FOR_EACH_OBSERVER(
1214 SyncEncryptionHandler::Observer, observers_,
1215 OnCryptographerStateChanged(
1216 &UnlockVaultMutable(trans->GetWrappedTrans())->cryptographer));
1217
1218 // It's possible we need to change the bootstrap token even if we failed to
1219 // set the passphrase (for example if we need to preserve the new GAIA
1220 // passphrase).
1221 if (!bootstrap_token.empty()) {
1222 DVLOG(1) << "Passphrase bootstrap token updated.";
1223 FOR_EACH_OBSERVER(
1224 SyncEncryptionHandler::Observer, observers_,
1225 OnBootstrapTokenUpdated(bootstrap_token, PASSPHRASE_BOOTSTRAP_TOKEN));
1226 }
1227
1228 const Cryptographer& cryptographer =
1229 UnlockVault(trans->GetWrappedTrans()).cryptographer;
1230 if (!success) {
1231 if (cryptographer.is_ready()) {
1232 LOG(ERROR) << "Attempt to change passphrase failed while cryptographer "
1233 << "was ready.";
1234 } else if (cryptographer.has_pending_keys()) {
1235 FOR_EACH_OBSERVER(SyncEncryptionHandler::Observer, observers_,
1236 OnPassphraseRequired(REASON_DECRYPTION,
1237 cryptographer.GetPendingKeys()));
1238 } else {
1239 FOR_EACH_OBSERVER(
1240 SyncEncryptionHandler::Observer, observers_,
1241 OnPassphraseRequired(REASON_ENCRYPTION, sync_pb::EncryptedData()));
1242 }
1243 return;
1244 }
1245 DCHECK(success);
1246 DCHECK(cryptographer.is_ready());
1247
1248 // Will do nothing if we're already properly migrated or unable to migrate
1249 // (in otherwords, if ShouldTriggerMigration is false).
1250 // Otherwise will update the nigori node with the current migrated state,
1251 // writing all encryption state as it does.
1252 if (!AttemptToMigrateNigoriToKeystore(trans, nigori_node)) {
1253 sync_pb::NigoriSpecifics nigori(nigori_node->GetNigoriSpecifics());
1254 // Does not modify nigori.encryption_keybag() if the original decrypted
1255 // data was the same.
1256 if (!cryptographer.GetKeys(nigori.mutable_encryption_keybag()))
1257 NOTREACHED();
1258 if (IsNigoriMigratedToKeystore(nigori)) {
1259 DCHECK(keystore_key_.empty() ||
1260 IsExplicitPassphrase(GetPassphraseType(trans->GetWrappedTrans())));
1261 DVLOG(1) << "Leaving nigori migration state untouched after setting"
1262 << " passphrase.";
1263 } else {
1264 nigori.set_keybag_is_frozen(
1265 IsExplicitPassphrase(GetPassphraseType(trans->GetWrappedTrans())));
1266 }
1267 // If we set a new custom passphrase, store the timestamp.
1268 if (!custom_passphrase_time_.is_null()) {
1269 nigori.set_custom_passphrase_time(
1270 TimeToProtoTime(custom_passphrase_time_));
1271 }
1272 nigori_node->SetNigoriSpecifics(nigori);
1273 }
1274
1275 // Must do this after OnPassphraseTypeChanged, in order to ensure the PSS
1276 // checks the passphrase state after it has been set.
1277 FOR_EACH_OBSERVER(SyncEncryptionHandler::Observer, observers_,
1278 OnPassphraseAccepted());
1279
1280 // Does nothing if everything is already encrypted.
1281 // TODO(zea): If we just migrated and enabled encryption, this will be
1282 // redundant. Figure out a way to not do this unnecessarily.
1283 ReEncryptEverything(trans);
1284 }
1285
1286 void SyncEncryptionHandlerImpl::MergeEncryptedTypes(
1287 ModelTypeSet new_encrypted_types,
1288 syncable::BaseTransaction* const trans) {
1289 DCHECK(thread_checker_.CalledOnValidThread());
1290
1291 // Only UserTypes may be encrypted.
1292 DCHECK(EncryptableUserTypes().HasAll(new_encrypted_types));
1293
1294 ModelTypeSet* encrypted_types = &UnlockVaultMutable(trans)->encrypted_types;
1295 if (!encrypted_types->HasAll(new_encrypted_types)) {
1296 *encrypted_types = new_encrypted_types;
1297 FOR_EACH_OBSERVER(
1298 Observer, observers_,
1299 OnEncryptedTypesChanged(*encrypted_types, encrypt_everything_));
1300 }
1301 }
1302
1303 SyncEncryptionHandlerImpl::Vault* SyncEncryptionHandlerImpl::UnlockVaultMutable(
1304 syncable::BaseTransaction* const trans) {
1305 DCHECK_EQ(user_share_->directory.get(), trans->directory());
1306 return &vault_unsafe_;
1307 }
1308
1309 const SyncEncryptionHandlerImpl::Vault& SyncEncryptionHandlerImpl::UnlockVault(
1310 syncable::BaseTransaction* const trans) const {
1311 DCHECK_EQ(user_share_->directory.get(), trans->directory());
1312 return vault_unsafe_;
1313 }
1314
1315 bool SyncEncryptionHandlerImpl::ShouldTriggerMigration(
1316 const sync_pb::NigoriSpecifics& nigori,
1317 const Cryptographer& cryptographer,
1318 PassphraseType passphrase_type) const {
1319 DCHECK(thread_checker_.CalledOnValidThread());
1320 // Don't migrate if there are pending encryption keys (because data
1321 // encrypted with the pending keys will not be decryptable).
1322 if (cryptographer.has_pending_keys())
1323 return false;
1324 if (IsNigoriMigratedToKeystore(nigori)) {
1325 // If the nigori is already migrated but does not reflect the explicit
1326 // passphrase state, remigrate. Similarly, if the nigori has an explicit
1327 // passphrase but does not have full encryption, or the nigori has an
1328 // implicit passphrase but does have full encryption, re-migrate.
1329 // Note that this is to defend against other clients without keystore
1330 // encryption enabled transitioning to states that are no longer valid.
1331 if (passphrase_type != PassphraseType::KEYSTORE_PASSPHRASE &&
1332 nigori.passphrase_type() ==
1333 sync_pb::NigoriSpecifics::KEYSTORE_PASSPHRASE) {
1334 return true;
1335 } else if (IsExplicitPassphrase(passphrase_type) && !encrypt_everything_) {
1336 return true;
1337 } else if (passphrase_type == PassphraseType::KEYSTORE_PASSPHRASE &&
1338 encrypt_everything_) {
1339 return true;
1340 } else if (cryptographer.is_ready() &&
1341 !cryptographer.CanDecryptUsingDefaultKey(
1342 nigori.encryption_keybag())) {
1343 // We need to overwrite the keybag. This might involve overwriting the
1344 // keystore decryptor too.
1345 return true;
1346 } else if (old_keystore_keys_.size() > 0 && !keystore_key_.empty()) {
1347 // Check to see if a server key rotation has happened, but the nigori
1348 // node's keys haven't been rotated yet, and hence we should re-migrate.
1349 // Note that once a key rotation has been performed, we no longer
1350 // preserve backwards compatibility, and the keybag will therefore be
1351 // encrypted with the current keystore key.
1352 Cryptographer temp_cryptographer(cryptographer.encryptor());
1353 KeyParams keystore_params = {"localhost", "dummy", keystore_key_};
1354 temp_cryptographer.AddKey(keystore_params);
1355 if (!temp_cryptographer.CanDecryptUsingDefaultKey(
1356 nigori.encryption_keybag())) {
1357 return true;
1358 }
1359 }
1360 return false;
1361 } else if (keystore_key_.empty()) {
1362 // If we haven't already migrated, we don't want to do anything unless
1363 // a keystore key is available (so that those clients without keystore
1364 // encryption enabled aren't forced into new states, e.g. frozen implicit
1365 // passphrase).
1366 return false;
1367 }
1368 return true;
1369 }
1370
1371 bool SyncEncryptionHandlerImpl::AttemptToMigrateNigoriToKeystore(
1372 WriteTransaction* trans,
1373 WriteNode* nigori_node) {
1374 DCHECK(thread_checker_.CalledOnValidThread());
1375 const sync_pb::NigoriSpecifics& old_nigori =
1376 nigori_node->GetNigoriSpecifics();
1377 Cryptographer* cryptographer =
1378 &UnlockVaultMutable(trans->GetWrappedTrans())->cryptographer;
1379 PassphraseType* passphrase_type =
1380 &UnlockVaultMutable(trans->GetWrappedTrans())->passphrase_type;
1381 if (!ShouldTriggerMigration(old_nigori, *cryptographer, *passphrase_type))
1382 return false;
1383
1384 DVLOG(1) << "Starting nigori migration to keystore support.";
1385 sync_pb::NigoriSpecifics migrated_nigori(old_nigori);
1386
1387 PassphraseType new_passphrase_type =
1388 GetPassphraseType(trans->GetWrappedTrans());
1389 bool new_encrypt_everything = encrypt_everything_;
1390 if (encrypt_everything_ && !IsExplicitPassphrase(*passphrase_type)) {
1391 DVLOG(1) << "Switching to frozen implicit passphrase due to already having "
1392 << "full encryption.";
1393 new_passphrase_type = PassphraseType::FROZEN_IMPLICIT_PASSPHRASE;
1394 migrated_nigori.clear_keystore_decryptor_token();
1395 } else if (IsExplicitPassphrase(*passphrase_type)) {
1396 DVLOG_IF(1, !encrypt_everything_) << "Enabling encrypt everything due to "
1397 << "explicit passphrase";
1398 new_encrypt_everything = true;
1399 migrated_nigori.clear_keystore_decryptor_token();
1400 } else {
1401 DCHECK(!encrypt_everything_);
1402 new_passphrase_type = PassphraseType::KEYSTORE_PASSPHRASE;
1403 DVLOG(1) << "Switching to keystore passphrase state.";
1404 }
1405 migrated_nigori.set_encrypt_everything(new_encrypt_everything);
1406 migrated_nigori.set_passphrase_type(
1407 EnumPassphraseTypeToProto(new_passphrase_type));
1408 migrated_nigori.set_keybag_is_frozen(true);
1409
1410 if (!keystore_key_.empty()) {
1411 KeyParams key_params = {"localhost", "dummy", keystore_key_};
1412 if ((old_keystore_keys_.size() > 0 &&
1413 new_passphrase_type == PassphraseType::KEYSTORE_PASSPHRASE) ||
1414 !cryptographer->is_initialized()) {
1415 // Either at least one key rotation has been performed, so we no longer
1416 // care about backwards compatibility, or we're generating keystore-based
1417 // encryption keys without knowing the GAIA password (and therefore the
1418 // cryptographer is not initialized), so we can't support backwards
1419 // compatibility. Ensure the keystore key is the default key.
1420 DVLOG(1) << "Migrating keybag to keystore key.";
1421 bool cryptographer_was_ready = cryptographer->is_ready();
1422 if (!cryptographer->AddKey(key_params)) {
1423 LOG(ERROR) << "Failed to add keystore key as default key";
1424 UMA_HISTOGRAM_ENUMERATION("Sync.AttemptNigoriMigration",
1425 FAILED_TO_SET_DEFAULT_KEYSTORE,
1426 MIGRATION_RESULT_SIZE);
1427 return false;
1428 }
1429 if (!cryptographer_was_ready && cryptographer->is_ready()) {
1430 FOR_EACH_OBSERVER(SyncEncryptionHandler::Observer, observers_,
1431 OnPassphraseAccepted());
1432 }
1433 } else {
1434 // We're in backwards compatible mode -- either the account has an
1435 // explicit passphrase, or we want to preserve the current GAIA-based key
1436 // as the default because we can (there have been no key rotations since
1437 // the migration).
1438 DVLOG(1) << "Migrating keybag while preserving old key";
1439 if (!cryptographer->AddNonDefaultKey(key_params)) {
1440 LOG(ERROR) << "Failed to add keystore key as non-default key.";
1441 UMA_HISTOGRAM_ENUMERATION("Sync.AttemptNigoriMigration",
1442 FAILED_TO_SET_NONDEFAULT_KEYSTORE,
1443 MIGRATION_RESULT_SIZE);
1444 return false;
1445 }
1446 }
1447 }
1448 if (!old_keystore_keys_.empty()) {
1449 // Go through and add all the old keystore keys as non default keys, so
1450 // they'll be preserved in the encryption_keybag when we next write the
1451 // nigori node.
1452 for (std::vector<std::string>::const_iterator iter =
1453 old_keystore_keys_.begin();
1454 iter != old_keystore_keys_.end(); ++iter) {
1455 KeyParams key_params = {"localhost", "dummy", *iter};
1456 cryptographer->AddNonDefaultKey(key_params);
1457 }
1458 }
1459 if (new_passphrase_type == PassphraseType::KEYSTORE_PASSPHRASE &&
1460 !GetKeystoreDecryptor(
1461 *cryptographer, keystore_key_,
1462 migrated_nigori.mutable_keystore_decryptor_token())) {
1463 LOG(ERROR) << "Failed to extract keystore decryptor token.";
1464 UMA_HISTOGRAM_ENUMERATION("Sync.AttemptNigoriMigration",
1465 FAILED_TO_EXTRACT_DECRYPTOR,
1466 MIGRATION_RESULT_SIZE);
1467 return false;
1468 }
1469 if (!cryptographer->GetKeys(migrated_nigori.mutable_encryption_keybag())) {
1470 LOG(ERROR) << "Failed to extract encryption keybag.";
1471 UMA_HISTOGRAM_ENUMERATION("Sync.AttemptNigoriMigration",
1472 FAILED_TO_EXTRACT_KEYBAG, MIGRATION_RESULT_SIZE);
1473 return false;
1474 }
1475
1476 if (migration_time_.is_null())
1477 migration_time_ = base::Time::Now();
1478 migrated_nigori.set_keystore_migration_time(TimeToProtoTime(migration_time_));
1479
1480 if (!custom_passphrase_time_.is_null()) {
1481 migrated_nigori.set_custom_passphrase_time(
1482 TimeToProtoTime(custom_passphrase_time_));
1483 }
1484
1485 FOR_EACH_OBSERVER(SyncEncryptionHandler::Observer, observers_,
1486 OnCryptographerStateChanged(cryptographer));
1487 if (*passphrase_type != new_passphrase_type) {
1488 *passphrase_type = new_passphrase_type;
1489 FOR_EACH_OBSERVER(
1490 SyncEncryptionHandler::Observer, observers_,
1491 OnPassphraseTypeChanged(*passphrase_type,
1492 GetExplicitPassphraseTime(*passphrase_type)));
1493 }
1494
1495 if (new_encrypt_everything && !encrypt_everything_) {
1496 EnableEncryptEverythingImpl(trans->GetWrappedTrans());
1497 ReEncryptEverything(trans);
1498 } else if (!cryptographer->CanDecryptUsingDefaultKey(
1499 old_nigori.encryption_keybag())) {
1500 DVLOG(1) << "Rencrypting everything due to key rotation.";
1501 ReEncryptEverything(trans);
1502 }
1503
1504 DVLOG(1) << "Completing nigori migration to keystore support.";
1505 nigori_node->SetNigoriSpecifics(migrated_nigori);
1506
1507 if (new_encrypt_everything &&
1508 (new_passphrase_type == PassphraseType::FROZEN_IMPLICIT_PASSPHRASE ||
1509 new_passphrase_type == PassphraseType::CUSTOM_PASSPHRASE)) {
1510 NotifyObserversOfLocalCustomPassphrase(trans);
1511 }
1512
1513 switch (new_passphrase_type) {
1514 case PassphraseType::KEYSTORE_PASSPHRASE:
1515 if (old_keystore_keys_.size() > 0) {
1516 UMA_HISTOGRAM_ENUMERATION("Sync.AttemptNigoriMigration",
1517 MIGRATION_SUCCESS_KEYSTORE_NONDEFAULT,
1518 MIGRATION_RESULT_SIZE);
1519 } else {
1520 UMA_HISTOGRAM_ENUMERATION("Sync.AttemptNigoriMigration",
1521 MIGRATION_SUCCESS_KEYSTORE_DEFAULT,
1522 MIGRATION_RESULT_SIZE);
1523 }
1524 break;
1525 case PassphraseType::FROZEN_IMPLICIT_PASSPHRASE:
1526 UMA_HISTOGRAM_ENUMERATION("Sync.AttemptNigoriMigration",
1527 MIGRATION_SUCCESS_FROZEN_IMPLICIT,
1528 MIGRATION_RESULT_SIZE);
1529 break;
1530 case PassphraseType::CUSTOM_PASSPHRASE:
1531 UMA_HISTOGRAM_ENUMERATION("Sync.AttemptNigoriMigration",
1532 MIGRATION_SUCCESS_CUSTOM,
1533 MIGRATION_RESULT_SIZE);
1534 break;
1535 default:
1536 NOTREACHED();
1537 break;
1538 }
1539 return true;
1540 }
1541
1542 bool SyncEncryptionHandlerImpl::GetKeystoreDecryptor(
1543 const Cryptographer& cryptographer,
1544 const std::string& keystore_key,
1545 sync_pb::EncryptedData* encrypted_blob) {
1546 DCHECK(thread_checker_.CalledOnValidThread());
1547 DCHECK(!keystore_key.empty());
1548 DCHECK(cryptographer.is_ready());
1549 std::string serialized_nigori;
1550 serialized_nigori = cryptographer.GetDefaultNigoriKeyData();
1551 if (serialized_nigori.empty()) {
1552 LOG(ERROR) << "Failed to get cryptographer bootstrap token.";
1553 return false;
1554 }
1555 Cryptographer temp_cryptographer(cryptographer.encryptor());
1556 KeyParams key_params = {"localhost", "dummy", keystore_key};
1557 if (!temp_cryptographer.AddKey(key_params))
1558 return false;
1559 if (!temp_cryptographer.EncryptString(serialized_nigori, encrypted_blob))
1560 return false;
1561 return true;
1562 }
1563
1564 bool SyncEncryptionHandlerImpl::AttemptToInstallKeybag(
1565 const sync_pb::EncryptedData& keybag,
1566 bool update_default,
1567 Cryptographer* cryptographer) {
1568 if (!cryptographer->CanDecrypt(keybag))
1569 return false;
1570 cryptographer->InstallKeys(keybag);
1571 if (update_default)
1572 cryptographer->SetDefaultKey(keybag.key_name());
1573 return true;
1574 }
1575
1576 void SyncEncryptionHandlerImpl::EnableEncryptEverythingImpl(
1577 syncable::BaseTransaction* const trans) {
1578 ModelTypeSet* encrypted_types = &UnlockVaultMutable(trans)->encrypted_types;
1579 if (encrypt_everything_) {
1580 DCHECK_EQ(EncryptableUserTypes(), *encrypted_types);
1581 return;
1582 }
1583 encrypt_everything_ = true;
1584 *encrypted_types = EncryptableUserTypes();
1585 FOR_EACH_OBSERVER(
1586 Observer, observers_,
1587 OnEncryptedTypesChanged(*encrypted_types, encrypt_everything_));
1588 }
1589
1590 bool SyncEncryptionHandlerImpl::DecryptPendingKeysWithKeystoreKey(
1591 const sync_pb::EncryptedData& keystore_decryptor_token,
1592 Cryptographer* cryptographer) {
1593 DCHECK(cryptographer->has_pending_keys());
1594 if (keystore_decryptor_token.blob().empty())
1595 return false;
1596 Cryptographer temp_cryptographer(cryptographer->encryptor());
1597
1598 // First, go through and all all the old keystore keys to the temporary
1599 // cryptographer.
1600 for (size_t i = 0; i < old_keystore_keys_.size(); ++i) {
1601 KeyParams old_key_params = {"localhost", "dummy", old_keystore_keys_[i]};
1602 temp_cryptographer.AddKey(old_key_params);
1603 }
1604
1605 // Then add the current keystore key as the default key and see if we can
1606 // decrypt.
1607 KeyParams keystore_params = {"localhost", "dummy", keystore_key_};
1608 if (temp_cryptographer.AddKey(keystore_params) &&
1609 temp_cryptographer.CanDecrypt(keystore_decryptor_token)) {
1610 // Someone else migrated the nigori for us! How generous! Go ahead and
1611 // install both the keystore key and the new default encryption key
1612 // (i.e. the one provided by the keystore decryptor token) into the
1613 // cryptographer.
1614 // The keystore decryptor token is a keystore key encrypted blob containing
1615 // the current serialized default encryption key (and as such should be
1616 // able to decrypt the nigori node's encryption keybag).
1617 // Note: it's possible a key rotation has happened since the migration, and
1618 // we're decrypting using an old keystore key. In that case we need to
1619 // ensure we re-encrypt using the newest key.
1620 DVLOG(1) << "Attempting to decrypt pending keys using "
1621 << "keystore decryptor token.";
1622 std::string serialized_nigori =
1623 temp_cryptographer.DecryptToString(keystore_decryptor_token);
1624
1625 // This will decrypt the pending keys and add them if possible. The key
1626 // within |serialized_nigori| will be the default after.
1627 cryptographer->ImportNigoriKey(serialized_nigori);
1628
1629 if (!temp_cryptographer.CanDecryptUsingDefaultKey(
1630 keystore_decryptor_token)) {
1631 // The keystore decryptor token was derived from an old keystore key.
1632 // A key rotation is necessary, so set the current keystore key as the
1633 // default key (which will trigger a re-migration).
1634 DVLOG(1) << "Pending keys based on old keystore key. Setting newest "
1635 << "keystore key as default.";
1636 cryptographer->AddKey(keystore_params);
1637 } else {
1638 // Theoretically the encryption keybag should already contain the keystore
1639 // key. We explicitly add it as a safety measure.
1640 DVLOG(1) << "Pending keys based on newest keystore key.";
1641 cryptographer->AddNonDefaultKey(keystore_params);
1642 }
1643 if (cryptographer->is_ready()) {
1644 std::string bootstrap_token;
1645 cryptographer->GetBootstrapToken(&bootstrap_token);
1646 DVLOG(1) << "Keystore decryptor token decrypted pending keys.";
1647 FOR_EACH_OBSERVER(SyncEncryptionHandler::Observer, observers_,
1648 OnPassphraseAccepted());
1649 FOR_EACH_OBSERVER(
1650 SyncEncryptionHandler::Observer, observers_,
1651 OnBootstrapTokenUpdated(bootstrap_token, PASSPHRASE_BOOTSTRAP_TOKEN));
1652 FOR_EACH_OBSERVER(SyncEncryptionHandler::Observer, observers_,
1653 OnCryptographerStateChanged(cryptographer));
1654 return true;
1655 }
1656 }
1657 return false;
1658 }
1659
1660 base::Time SyncEncryptionHandlerImpl::GetExplicitPassphraseTime(
1661 PassphraseType passphrase_type) const {
1662 if (passphrase_type == PassphraseType::FROZEN_IMPLICIT_PASSPHRASE)
1663 return migration_time();
1664 else if (passphrase_type == PassphraseType::CUSTOM_PASSPHRASE)
1665 return custom_passphrase_time();
1666 return base::Time();
1667 }
1668
1669 } // namespace syncer
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698