OLD | NEW |
| (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 | |
OLD | NEW |