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

Side by Side Diff: sync/internal_api/sync_encryption_handler_impl.cc

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

Powered by Google App Engine
This is Rietveld 408576698