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

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

Issue 10916036: [Sync] Implement keystore migration support. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Self review Created 8 years, 3 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "sync/internal_api/sync_encryption_handler_impl.h" 5 #include "sync/internal_api/sync_encryption_handler_impl.h"
6 6
7 #include <queue> 7 #include <queue>
8 #include <string> 8 #include <string>
9 9
10 #include "base/bind.h" 10 #include "base/bind.h"
11 #include "base/message_loop.h" 11 #include "base/message_loop.h"
12 #include "base/time.h"
12 #include "base/tracked_objects.h" 13 #include "base/tracked_objects.h"
13 #include "base/metrics/histogram.h" 14 #include "base/metrics/histogram.h"
14 #include "sync/internal_api/public/read_node.h" 15 #include "sync/internal_api/public/read_node.h"
15 #include "sync/internal_api/public/read_transaction.h" 16 #include "sync/internal_api/public/read_transaction.h"
16 #include "sync/internal_api/public/user_share.h" 17 #include "sync/internal_api/public/user_share.h"
17 #include "sync/internal_api/public/util/experiments.h" 18 #include "sync/internal_api/public/util/experiments.h"
18 #include "sync/internal_api/public/write_node.h" 19 #include "sync/internal_api/public/write_node.h"
19 #include "sync/internal_api/public/write_transaction.h" 20 #include "sync/internal_api/public/write_transaction.h"
21 #include "sync/internal_api/public/util/sync_string_conversions.h"
20 #include "sync/protocol/encryption.pb.h" 22 #include "sync/protocol/encryption.pb.h"
21 #include "sync/protocol/nigori_specifics.pb.h" 23 #include "sync/protocol/nigori_specifics.pb.h"
22 #include "sync/protocol/sync.pb.h" 24 #include "sync/protocol/sync.pb.h"
23 #include "sync/syncable/base_transaction.h" 25 #include "sync/syncable/base_transaction.h"
24 #include "sync/syncable/directory.h" 26 #include "sync/syncable/directory.h"
25 #include "sync/syncable/entry.h" 27 #include "sync/syncable/entry.h"
26 #include "sync/syncable/nigori_util.h" 28 #include "sync/syncable/nigori_util.h"
27 #include "sync/util/cryptographer.h" 29 #include "sync/util/cryptographer.h"
30 #include "sync/util/time.h"
28 31
29 namespace syncer { 32 namespace syncer {
30 33
31 namespace { 34 namespace {
35
32 // The maximum number of times we will automatically overwrite the nigori node 36 // The maximum number of times we will automatically overwrite the nigori node
33 // because the encryption keys don't match (per chrome instantiation). 37 // because the encryption keys don't match (per chrome instantiation).
34 // We protect ourselves against nigori rollbacks, but it's possible two 38 // We protect ourselves against nigori rollbacks, but it's possible two
35 // different clients might have contrasting view of what the nigori node state 39 // different clients might have contrasting view of what the nigori node state
36 // should be, in which case they might ping pong (see crbug.com/119207). 40 // should be, in which case they might ping pong (see crbug.com/119207).
37 static const int kNigoriOverwriteLimit = 10; 41 static const int kNigoriOverwriteLimit = 10;
42
43 // The new passphrase state is sufficient to determine whether a nigori node
44 // is migrated to support keystore encryption. In addition though, we also
45 // want to verify the conditions for proper keystore encryption functionality.
46 // 1. Passphrase state is set.
47 // 2. Migration time is set.
48 // 3. Frozen keybag is true
49 // 4. If passphrase state is keystore, keystore_bootstrap_key is set.
50 bool IsNigoriMigratedToKeystore(const sync_pb::NigoriSpecifics& nigori) {
51 if (!nigori.has_passphrase_state())
52 return false;
53 if (!nigori.has_keystore_migration_time())
54 return false;
55 if (!nigori.frozen_keybag())
56 return false;
57 if (nigori.passphrase_state() ==
58 sync_pb::NigoriSpecifics::IMPLICIT_PASSPHRASE)
59 return false;
60 if (nigori.passphrase_state() ==
61 sync_pb::NigoriSpecifics::KEYSTORE_PASSPHRASE &&
62 nigori.keystore_bootstrap().blob().empty())
63 return false;
64 return true;
38 } 65 }
39 66
67 PassphraseState ProtoPassphraseStateToEnum(
68 sync_pb::NigoriSpecifics::PassphraseState state) {
69 switch(state) {
70 case sync_pb::NigoriSpecifics::IMPLICIT_PASSPHRASE:
71 return IMPLICIT_PASSPHRASE;
72 case sync_pb::NigoriSpecifics::KEYSTORE_PASSPHRASE:
73 return KEYSTORE_PASSPHRASE;
74 case sync_pb::NigoriSpecifics::CUSTOM_PASSPHRASE:
75 return CUSTOM_PASSPHRASE;
76 case sync_pb::NigoriSpecifics::FROZEN_IMPLICIT_PASSPHRASE:
77 return FROZEN_IMPLICIT_PASSPHRASE;
78 default:
79 NOTREACHED();
80 return IMPLICIT_PASSPHRASE;
81 };
82 }
83
84 sync_pb::NigoriSpecifics::PassphraseState
85 EnumPassphraseStateToProto(PassphraseState state) {
86 switch(state) {
87 case IMPLICIT_PASSPHRASE:
88 return sync_pb::NigoriSpecifics::IMPLICIT_PASSPHRASE;
89 case KEYSTORE_PASSPHRASE:
90 return sync_pb::NigoriSpecifics::KEYSTORE_PASSPHRASE;
91 case CUSTOM_PASSPHRASE:
92 return sync_pb::NigoriSpecifics::CUSTOM_PASSPHRASE;
93 case FROZEN_IMPLICIT_PASSPHRASE:
94 return sync_pb::NigoriSpecifics::FROZEN_IMPLICIT_PASSPHRASE;
95 default:
96 NOTREACHED();
97 return sync_pb::NigoriSpecifics::IMPLICIT_PASSPHRASE;;
98 };
99 }
100
101 bool IsExplicitPassphrase(PassphraseState state) {
102 return state == CUSTOM_PASSPHRASE || state == FROZEN_IMPLICIT_PASSPHRASE;
103 }
104
105 } // namespace
106
40 SyncEncryptionHandlerImpl::Vault::Vault( 107 SyncEncryptionHandlerImpl::Vault::Vault(
41 Encryptor* encryptor, 108 Encryptor* encryptor,
42 ModelTypeSet encrypted_types) 109 ModelTypeSet encrypted_types)
43 : cryptographer(encryptor), 110 : cryptographer(encryptor),
44 encrypted_types(encrypted_types) { 111 encrypted_types(encrypted_types) {
45 } 112 }
46 113
47 SyncEncryptionHandlerImpl::Vault::~Vault() { 114 SyncEncryptionHandlerImpl::Vault::~Vault() {
48 } 115 }
49 116
50 SyncEncryptionHandlerImpl::SyncEncryptionHandlerImpl( 117 SyncEncryptionHandlerImpl::SyncEncryptionHandlerImpl(
51 UserShare* user_share, 118 UserShare* user_share,
52 Encryptor* encryptor, 119 Encryptor* encryptor,
53 const std::string& restored_key_for_bootstrapping, 120 const std::string& restored_key_for_bootstrapping,
54 const std::string& restored_keystore_key_for_bootstrapping) 121 const std::string& restored_keystore_key_for_bootstrapping)
55 : weak_ptr_factory_(ALLOW_THIS_IN_INITIALIZER_LIST(this)), 122 : weak_ptr_factory_(ALLOW_THIS_IN_INITIALIZER_LIST(this)),
56 user_share_(user_share), 123 user_share_(user_share),
57 vault_unsafe_(encryptor, SensitiveTypes()), 124 vault_unsafe_(encryptor, SensitiveTypes()),
58 encrypt_everything_(false), 125 encrypt_everything_(false),
59 passphrase_state_(IMPLICIT_PASSPHRASE), 126 passphrase_state_(IMPLICIT_PASSPHRASE),
60 keystore_key_(restored_keystore_key_for_bootstrapping), 127 keystore_key_(restored_keystore_key_for_bootstrapping),
61 nigori_overwrite_count_(0) { 128 nigori_overwrite_count_(0),
129 migration_time_ms_(0) {
62 // We only bootstrap the user provided passphrase. The keystore key is handled 130 // We only bootstrap the user provided passphrase. The keystore key is handled
63 // at Init time once we're sure the nigori is downloaded. 131 // at Init time once we're sure the nigori is downloaded.
64 vault_unsafe_.cryptographer.Bootstrap(restored_key_for_bootstrapping); 132 vault_unsafe_.cryptographer.Bootstrap(restored_key_for_bootstrapping);
65 } 133 }
66 134
67 SyncEncryptionHandlerImpl::~SyncEncryptionHandlerImpl() {} 135 SyncEncryptionHandlerImpl::~SyncEncryptionHandlerImpl() {}
68 136
69 void SyncEncryptionHandlerImpl::AddObserver(Observer* observer) { 137 void SyncEncryptionHandlerImpl::AddObserver(Observer* observer) {
70 DCHECK(thread_checker_.CalledOnValidThread()); 138 DCHECK(thread_checker_.CalledOnValidThread());
71 DCHECK(!observers_.HasObserver(observer)); 139 DCHECK(!observers_.HasObserver(observer));
(...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after
123 191
124 // All accesses to the cryptographer are protected by a transaction. 192 // All accesses to the cryptographer are protected by a transaction.
125 WriteTransaction trans(FROM_HERE, user_share_); 193 WriteTransaction trans(FROM_HERE, user_share_);
126 KeyParams key_params = {"localhost", "dummy", passphrase}; 194 KeyParams key_params = {"localhost", "dummy", passphrase};
127 WriteNode node(&trans); 195 WriteNode node(&trans);
128 if (node.InitByTagLookup(kNigoriTag) != BaseNode::INIT_OK) { 196 if (node.InitByTagLookup(kNigoriTag) != BaseNode::INIT_OK) {
129 NOTREACHED(); 197 NOTREACHED();
130 return; 198 return;
131 } 199 }
132 200
133 bool nigori_has_explicit_passphrase = 201 Cryptographer* cryptographer =
134 node.GetNigoriSpecifics().using_explicit_passphrase(); 202 &UnlockVaultMutable(trans.GetWrappedTrans())->cryptographer;
203
204 // Once we've migrated to keystore, the only way to set a passphrase for
205 // encryption is to set a custom passphrase.
206 if (IsNigoriMigratedToKeystore(node.GetNigoriSpecifics())) {
207 if (!is_explicit) {
208 DCHECK(cryptographer->is_ready());
209 // The user is setting a new implicit passphrase. At this point we don't
210 // care, so drop it on the floor. This is safe because if we have a
211 // migrated nigori node, then we must at least have pending keys, and
tim (not reviewing) 2012/09/06 01:04:20 This confused me a bit. If we had pending keys, w
Nicolas Zea 2012/09/06 21:45:27 Done.
212 // therefore this is just the client attempting to update the gaia
213 // passphrase.
214 LOG(WARNING) << "Ignoring new implicit passphrase. Keystore migration "
215 << "already performed.";
216 return;
217 }
218 SetCustomPassphrase(passphrase, &trans, &node);
tim (not reviewing) 2012/09/06 01:04:20 Add comment (or cleverly rename) that this is tent
Nicolas Zea 2012/09/06 21:45:27 Done.
219 return;
220 }
221
135 std::string bootstrap_token; 222 std::string bootstrap_token;
136 sync_pb::EncryptedData pending_keys; 223 sync_pb::EncryptedData pending_keys;
137 Cryptographer* cryptographer =
138 &UnlockVaultMutable(trans.GetWrappedTrans())->cryptographer;
139 if (cryptographer->has_pending_keys()) 224 if (cryptographer->has_pending_keys())
140 pending_keys = cryptographer->GetPendingKeys(); 225 pending_keys = cryptographer->GetPendingKeys();
141 bool success = false; 226 bool success = false;
142 227
143 // There are six cases to handle here: 228 // There are six cases to handle here:
144 // 1. The user has no pending keys and is setting their current GAIA password 229 // 1. The user has no pending keys and is setting their current GAIA password
145 // as the encryption passphrase. This happens either during first time sync 230 // as the encryption passphrase. This happens either during first time sync
146 // with a clean profile, or after re-authenticating on a profile that was 231 // with a clean profile, or after re-authenticating on a profile that was
147 // already signed in with the cryptographer ready. 232 // already signed in with the cryptographer ready.
148 // 2. The user has no pending keys, and is overwriting an (already provided) 233 // 2. The user has no pending keys, and is overwriting an (already provided)
149 // implicit passphrase with an explicit (custom) passphrase. 234 // implicit passphrase with an explicit (custom) passphrase.
150 // 3. The user has pending keys for an explicit passphrase that is somehow set 235 // 3. The user has pending keys for an explicit passphrase that is somehow set
151 // to their current GAIA passphrase. 236 // to their current GAIA passphrase.
152 // 4. The user has pending keys encrypted with their current GAIA passphrase 237 // 4. The user has pending keys encrypted with their current GAIA passphrase
153 // and the caller passes in the current GAIA passphrase. 238 // and the caller passes in the current GAIA passphrase.
154 // 5. The user has pending keys encrypted with an older GAIA passphrase 239 // 5. The user has pending keys encrypted with an older GAIA passphrase
155 // and the caller passes in the current GAIA passphrase. 240 // and the caller passes in the current GAIA passphrase.
156 // 6. The user has previously done encryption with an explicit passphrase. 241 // 6. The user has previously done encryption with an explicit passphrase.
157 // Furthermore, we enforce the fact that the bootstrap encryption token will 242 // Furthermore, we enforce the fact that the bootstrap encryption token will
158 // always be derived from the newest GAIA password if the account is using 243 // always be derived from the newest GAIA password if the account is using
159 // an implicit passphrase (even if the data is encrypted with an old GAIA 244 // an implicit passphrase (even if the data is encrypted with an old GAIA
160 // password). If the account is using an explicit (custom) passphrase, the 245 // password). If the account is using an explicit (custom) passphrase, the
161 // bootstrap token will be derived from the most recently provided explicit 246 // bootstrap token will be derived from the most recently provided explicit
162 // passphrase (that was able to decrypt the data). 247 // passphrase (that was able to decrypt the data).
163 if (!nigori_has_explicit_passphrase) { 248 if (!IsExplicitPassphrase(passphrase_state_)) {
164 if (!cryptographer->has_pending_keys()) { 249 if (!cryptographer->has_pending_keys()) {
165 if (cryptographer->AddKey(key_params)) { 250 if (cryptographer->AddKey(key_params)) {
166 // Case 1 and 2. We set a new GAIA passphrase when there are no pending 251 // Case 1 and 2. We set a new GAIA passphrase when there are no pending
167 // keys (1), or overwriting an implicit passphrase with a new explicit 252 // keys (1), or overwriting an implicit passphrase with a new explicit
168 // one (2) when there are no pending keys. 253 // one (2) when there are no pending keys.
169 DVLOG(1) << "Setting " << (is_explicit ? "explicit" : "implicit" ) 254 if (is_explicit) {
170 << " passphrase for encryption."; 255 DVLOG(1) << "Setting explicit passphrase for encryption.";
256 passphrase_state_ = CUSTOM_PASSPHRASE;
257 FOR_EACH_OBSERVER(SyncEncryptionHandler::Observer, observers_,
258 OnPassphraseStateChanged(passphrase_state_));
259 } else {
260 DVLOG(1) << "Setting implicit passphrase for encryption.";
261 }
171 cryptographer->GetBootstrapToken(&bootstrap_token); 262 cryptographer->GetBootstrapToken(&bootstrap_token);
172 success = true; 263 success = true;
173 } else { 264 } else {
174 NOTREACHED() << "Failed to add key to cryptographer."; 265 NOTREACHED() << "Failed to add key to cryptographer.";
175 success = false; 266 success = false;
176 } 267 }
177 } else { // cryptographer->has_pending_keys() == true 268 } else { // cryptographer->has_pending_keys() == true
178 if (is_explicit) { 269 if (is_explicit) {
179 // This can only happen if the nigori node is updated with a new 270 // This can only happen if the nigori node is updated with a new
180 // implicit passphrase while a client is attempting to set a new custom 271 // implicit passphrase while a client is attempting to set a new custom
(...skipping 21 matching lines...) Expand all
202 temp_cryptographer.GetBootstrapToken(&bootstrap_token); 293 temp_cryptographer.GetBootstrapToken(&bootstrap_token);
203 // We then set the new passphrase as the default passphrase of the 294 // We then set the new passphrase as the default passphrase of the
204 // real cryptographer, even though we have pending keys. This is safe, 295 // real cryptographer, even though we have pending keys. This is safe,
205 // as although Cryptographer::is_initialized() will now be true, 296 // as although Cryptographer::is_initialized() will now be true,
206 // is_ready() will remain false due to having pending keys. 297 // is_ready() will remain false due to having pending keys.
207 cryptographer->AddKey(key_params); 298 cryptographer->AddKey(key_params);
208 success = false; 299 success = false;
209 } 300 }
210 } // is_explicit 301 } // is_explicit
211 } // cryptographer->has_pending_keys() 302 } // cryptographer->has_pending_keys()
212 } else { // nigori_has_explicit_passphrase == true 303 } else { // nigori_has_explicit_passphrase == true
tim (not reviewing) 2012/09/06 01:04:20 update this comment to reflect the if.
Nicolas Zea 2012/09/06 21:45:27 Done.
213 // Case 6. We do not want to override a previously set explicit passphrase, 304 // Case 6. We do not want to override a previously set explicit passphrase,
214 // so we return a failure. 305 // so we return a failure.
215 DVLOG(1) << "Failing because an explicit passphrase is already set."; 306 DVLOG(1) << "Failing because an explicit passphrase is already set.";
216 success = false; 307 success = false;
217 } 308 }
218 309
219 DVLOG_IF(1, !success) 310 DVLOG_IF(1, !success)
220 << "Failure in SetEncryptionPassphrase; notifying and returning."; 311 << "Failure in SetEncryptionPassphrase; notifying and returning.";
221 DVLOG_IF(1, success) 312 DVLOG_IF(1, success)
222 << "Successfully set encryption passphrase; updating nigori and " 313 << "Successfully set encryption passphrase; updating nigori and "
223 "reencrypting."; 314 "reencrypting.";
224 315
225 FinishSetPassphrase( 316 FinishSetPassphrase(success, bootstrap_token, &trans, &node);
226 success, bootstrap_token, is_explicit, &trans, &node);
227 } 317 }
228 318
229 void SyncEncryptionHandlerImpl::SetDecryptionPassphrase( 319 void SyncEncryptionHandlerImpl::SetDecryptionPassphrase(
230 const std::string& passphrase) { 320 const std::string& passphrase) {
231 DCHECK(thread_checker_.CalledOnValidThread()); 321 DCHECK(thread_checker_.CalledOnValidThread());
232 // We do not accept empty passphrases. 322 // We do not accept empty passphrases.
233 if (passphrase.empty()) { 323 if (passphrase.empty()) {
234 NOTREACHED() << "Cannot decrypt with an empty passphrase."; 324 NOTREACHED() << "Cannot decrypt with an empty passphrase.";
235 return; 325 return;
236 } 326 }
237 327
238 // All accesses to the cryptographer are protected by a transaction. 328 // All accesses to the cryptographer are protected by a transaction.
239 WriteTransaction trans(FROM_HERE, user_share_); 329 WriteTransaction trans(FROM_HERE, user_share_);
240 KeyParams key_params = {"localhost", "dummy", passphrase}; 330 KeyParams key_params = {"localhost", "dummy", passphrase};
241 WriteNode node(&trans); 331 WriteNode node(&trans);
242 if (node.InitByTagLookup(kNigoriTag) != BaseNode::INIT_OK) { 332 if (node.InitByTagLookup(kNigoriTag) != BaseNode::INIT_OK) {
243 NOTREACHED(); 333 NOTREACHED();
244 return; 334 return;
245 } 335 }
246 336
337 // Once we've migrated to keystore, we're only ever decrypting an explicit
tim (not reviewing) 2012/09/06 01:04:20 nit - decrypting keys derived from an explicit pas
Nicolas Zea 2012/09/06 21:45:27 Done.
338 // passphrase. But, for clients without a keystore key yet (either not on
339 // by default or failed to download one), we still support decrypting with
340 // a gaia passphrase, and therefore bypass the DecryptExplicitPassphrase
341 // logic.
342 if (IsNigoriMigratedToKeystore(node.GetNigoriSpecifics()) &&
343 IsExplicitPassphrase(passphrase_state_)) {
344 DecryptExplicitPassphrase(passphrase, &trans, &node);
tim (not reviewing) 2012/09/06 01:04:20 nit - DecryptPendingExplicitPassphraseKeys ?
Nicolas Zea 2012/09/06 21:45:27 Done.
345 return;
346 }
347
247 Cryptographer* cryptographer = 348 Cryptographer* cryptographer =
248 &UnlockVaultMutable(trans.GetWrappedTrans())->cryptographer; 349 &UnlockVaultMutable(trans.GetWrappedTrans())->cryptographer;
249 if (!cryptographer->has_pending_keys()) { 350 if (!cryptographer->has_pending_keys()) {
250 // Note that this *can* happen in a rare situation where data is 351 // Note that this *can* happen in a rare situation where data is
251 // re-encrypted on another client while a SetDecryptionPassphrase() call is 352 // re-encrypted on another client while a SetDecryptionPassphrase() call is
252 // in-flight on this client. It is rare enough that we choose to do nothing. 353 // in-flight on this client. It is rare enough that we choose to do nothing.
253 NOTREACHED() << "Attempt to set decryption passphrase failed because there " 354 NOTREACHED() << "Attempt to set decryption passphrase failed because there "
254 << "were no pending keys."; 355 << "were no pending keys.";
255 return; 356 return;
256 } 357 }
257 358
258 bool nigori_has_explicit_passphrase =
259 node.GetNigoriSpecifics().using_explicit_passphrase();
260 std::string bootstrap_token; 359 std::string bootstrap_token;
261 sync_pb::EncryptedData pending_keys; 360 sync_pb::EncryptedData pending_keys;
262 pending_keys = cryptographer->GetPendingKeys(); 361 pending_keys = cryptographer->GetPendingKeys();
263 bool success = false; 362 bool success = false;
264 363
265 // There are three cases to handle here: 364 // There are three cases to handle here:
266 // 7. We're using the current GAIA password to decrypt the pending keys. This 365 // 7. We're using the current GAIA password to decrypt the pending keys. This
267 // happens when signing in to an account with a previously set implicit 366 // happens when signing in to an account with a previously set implicit
268 // passphrase, where the data is already encrypted with the newest GAIA 367 // passphrase, where the data is already encrypted with the newest GAIA
269 // password. 368 // password.
270 // 8. The user is providing an old GAIA password to decrypt the pending keys. 369 // 8. The user is providing an old GAIA password to decrypt the pending keys.
271 // In this case, the user is using an implicit passphrase, but has changed 370 // In this case, the user is using an implicit passphrase, but has changed
272 // their password since they last encrypted their data, and therefore 371 // their password since they last encrypted their data, and therefore
273 // their current GAIA password was unable to decrypt the data. This will 372 // their current GAIA password was unable to decrypt the data. This will
274 // happen when the user is setting up a new profile with a previously 373 // happen when the user is setting up a new profile with a previously
275 // encrypted account (after changing passwords). 374 // encrypted account (after changing passwords).
276 // 9. The user is providing a previously set explicit passphrase to decrypt 375 // 9. The user is providing a previously set explicit passphrase to decrypt
277 // the pending keys. 376 // the pending keys.
278 if (!nigori_has_explicit_passphrase) { 377 if (!IsExplicitPassphrase(passphrase_state_)) {
279 if (cryptographer->is_initialized()) { 378 if (cryptographer->is_initialized()) {
280 // We only want to change the default encryption key to the pending 379 // We only want to change the default encryption key to the pending
281 // one if the pending keybag already contains the current default. 380 // one if the pending keybag already contains the current default.
282 // This covers the case where a different client re-encrypted 381 // This covers the case where a different client re-encrypted
283 // everything with a newer gaia passphrase (and hence the keybag 382 // everything with a newer gaia passphrase (and hence the keybag
284 // contains keys from all previously used gaia passphrases). 383 // contains keys from all previously used gaia passphrases).
285 // Otherwise, we're in a situation where the pending keys are 384 // Otherwise, we're in a situation where the pending keys are
286 // encrypted with an old gaia passphrase, while the default is the 385 // encrypted with an old gaia passphrase, while the default is the
287 // current gaia passphrase. In that case, we preserve the default. 386 // current gaia passphrase. In that case, we preserve the default.
288 Cryptographer temp_cryptographer(cryptographer->encryptor()); 387 Cryptographer temp_cryptographer(cryptographer->encryptor());
(...skipping 66 matching lines...) Expand 10 before | Expand all | Expand 10 after
355 success = false; 454 success = false;
356 } 455 }
357 } // nigori_has_explicit_passphrase 456 } // nigori_has_explicit_passphrase
358 457
359 DVLOG_IF(1, !success) 458 DVLOG_IF(1, !success)
360 << "Failure in SetDecryptionPassphrase; notifying and returning."; 459 << "Failure in SetDecryptionPassphrase; notifying and returning.";
361 DVLOG_IF(1, success) 460 DVLOG_IF(1, success)
362 << "Successfully set decryption passphrase; updating nigori and " 461 << "Successfully set decryption passphrase; updating nigori and "
363 "reencrypting."; 462 "reencrypting.";
364 463
365 FinishSetPassphrase(success, 464 FinishSetPassphrase(success, bootstrap_token, &trans, &node);
366 bootstrap_token,
367 nigori_has_explicit_passphrase,
368 &trans,
369 &node);
370 } 465 }
371 466
372 void SyncEncryptionHandlerImpl::EnableEncryptEverything() { 467 void SyncEncryptionHandlerImpl::EnableEncryptEverything() {
373 DCHECK(thread_checker_.CalledOnValidThread()); 468 DCHECK(thread_checker_.CalledOnValidThread());
374 WriteTransaction trans(FROM_HERE, user_share_); 469 WriteTransaction trans(FROM_HERE, user_share_);
375 ModelTypeSet* encrypted_types = 470 DVLOG(1) << "Enabling encrypt everything.";
376 &UnlockVaultMutable(trans.GetWrappedTrans())->encrypted_types; 471 if (encrypt_everything_)
377 if (encrypt_everything_) {
378 DCHECK(encrypted_types->Equals(ModelTypeSet::All()));
379 return; 472 return;
380 } 473 EnableEncryptEverythingImpl(trans.GetWrappedTrans());
381 DVLOG(1) << "Enabling encrypt everything.";
382 encrypt_everything_ = true;
383 // Change |encrypted_types_| directly to avoid sending more than one
384 // notification.
385 *encrypted_types = ModelTypeSet::All();
386 FOR_EACH_OBSERVER(
387 Observer, observers_,
388 OnEncryptedTypesChanged(*encrypted_types, encrypt_everything_));
389 WriteEncryptionStateToNigori(&trans); 474 WriteEncryptionStateToNigori(&trans);
390 if (UnlockVault(trans.GetWrappedTrans()).cryptographer.is_ready()) 475 if (UnlockVault(trans.GetWrappedTrans()).cryptographer.is_ready())
391 ReEncryptEverything(&trans); 476 ReEncryptEverything(&trans);
392 } 477 }
393 478
394 bool SyncEncryptionHandlerImpl::EncryptEverythingEnabled() const { 479 bool SyncEncryptionHandlerImpl::EncryptEverythingEnabled() const {
395 DCHECK(thread_checker_.CalledOnValidThread()); 480 DCHECK(thread_checker_.CalledOnValidThread());
396 return encrypt_everything_; 481 return encrypt_everything_;
397 } 482 }
398 483
(...skipping 19 matching lines...) Expand all
418 FOR_EACH_OBSERVER( 503 FOR_EACH_OBSERVER(
419 SyncEncryptionHandler::Observer, 504 SyncEncryptionHandler::Observer,
420 observers_, 505 observers_,
421 OnCryptographerStateChanged( 506 OnCryptographerStateChanged(
422 &UnlockVaultMutable(trans)->cryptographer)); 507 &UnlockVaultMutable(trans)->cryptographer));
423 } 508 }
424 509
425 void SyncEncryptionHandlerImpl::UpdateNigoriFromEncryptedTypes( 510 void SyncEncryptionHandlerImpl::UpdateNigoriFromEncryptedTypes(
426 sync_pb::NigoriSpecifics* nigori, 511 sync_pb::NigoriSpecifics* nigori,
427 syncable::BaseTransaction* const trans) const { 512 syncable::BaseTransaction* const trans) const {
513 DCHECK(thread_checker_.CalledOnValidThread());
428 syncable::UpdateNigoriFromEncryptedTypes(UnlockVault(trans).encrypted_types, 514 syncable::UpdateNigoriFromEncryptedTypes(UnlockVault(trans).encrypted_types,
429 encrypt_everything_, 515 encrypt_everything_,
430 nigori); 516 nigori);
431 } 517 }
432 518
433 bool SyncEncryptionHandlerImpl::NeedKeystoreKey( 519 bool SyncEncryptionHandlerImpl::NeedKeystoreKey(
434 syncable::BaseTransaction* const trans) const { 520 syncable::BaseTransaction* const trans) const {
521 DCHECK(thread_checker_.CalledOnValidThread());
435 return keystore_key_.empty(); 522 return keystore_key_.empty();
436 } 523 }
437 524
438 bool SyncEncryptionHandlerImpl::SetKeystoreKey( 525 bool SyncEncryptionHandlerImpl::SetKeystoreKey(
439 const std::string& key, 526 const std::string& key,
440 syncable::BaseTransaction* const trans) { 527 syncable::BaseTransaction* const trans) {
528 DCHECK(thread_checker_.CalledOnValidThread());
441 if (!keystore_key_.empty() || key.empty()) 529 if (!keystore_key_.empty() || key.empty())
442 return false; 530 return false;
443 keystore_key_ = key; 531 keystore_key_ = key;
444 532
445 // TODO(zea): trigger migration if necessary.
446
447 DVLOG(1) << "Keystore bootstrap token updated."; 533 DVLOG(1) << "Keystore bootstrap token updated.";
448 FOR_EACH_OBSERVER(SyncEncryptionHandler::Observer, observers_, 534 FOR_EACH_OBSERVER(SyncEncryptionHandler::Observer, observers_,
449 OnBootstrapTokenUpdated(key, 535 OnBootstrapTokenUpdated(key,
450 KEYSTORE_BOOTSTRAP_TOKEN)); 536 KEYSTORE_BOOTSTRAP_TOKEN));
537
538 Cryptographer* cryptographer = &UnlockVaultMutable(trans)->cryptographer;
539 syncable::Entry entry(trans, syncable::GET_BY_SERVER_TAG, kNigoriTag);
540 if (entry.good()) {
541 const sync_pb::NigoriSpecifics& nigori =
542 entry.Get(syncable::SPECIFICS).nigori();
543 if (cryptographer->has_pending_keys() &&
544 IsNigoriMigratedToKeystore(nigori) &&
545 !nigori.keystore_bootstrap().blob().empty()) {
546 // If the nigori is already migrated and we have pending keys, we might
547 // be able to decrypt them using the keystore bootstrap key.
548 DecryptPendingKeysWithKeystoreKey(keystore_key_,
549 nigori.keystore_bootstrap(),
550 cryptographer);
551 } else if (ShouldTriggerMigration(nigori, *cryptographer)) {
552 // We call rewrite nigori to attempt to trigger migration.
553 // Need to post a task to open a new sync_api transaction.
554 MessageLoop::current()->PostTask(
555 FROM_HERE,
556 base::Bind(&SyncEncryptionHandlerImpl::RewriteNigori,
557 weak_ptr_factory_.GetWeakPtr()));
558 }
559 }
560
451 return true; 561 return true;
452 } 562 }
453 563
454 ModelTypeSet SyncEncryptionHandlerImpl::GetEncryptedTypes( 564 ModelTypeSet SyncEncryptionHandlerImpl::GetEncryptedTypes(
455 syncable::BaseTransaction* const trans) const { 565 syncable::BaseTransaction* const trans) const {
456 return UnlockVault(trans).encrypted_types; 566 return UnlockVault(trans).encrypted_types;
457 } 567 }
458 568
459 Cryptographer* SyncEncryptionHandlerImpl::GetCryptographerUnsafe() { 569 Cryptographer* SyncEncryptionHandlerImpl::GetCryptographerUnsafe() {
460 DCHECK(thread_checker_.CalledOnValidThread()); 570 DCHECK(thread_checker_.CalledOnValidThread());
461 return &vault_unsafe_.cryptographer; 571 return &vault_unsafe_.cryptographer;
462 } 572 }
463 573
464 ModelTypeSet SyncEncryptionHandlerImpl::GetEncryptedTypesUnsafe() { 574 ModelTypeSet SyncEncryptionHandlerImpl::GetEncryptedTypesUnsafe() {
465 DCHECK(thread_checker_.CalledOnValidThread()); 575 DCHECK(thread_checker_.CalledOnValidThread());
466 return vault_unsafe_.encrypted_types; 576 return vault_unsafe_.encrypted_types;
467 } 577 }
468 578
579 bool SyncEncryptionHandlerImpl::MigratedToKeystore() {
580 DCHECK(thread_checker_.CalledOnValidThread());
581 ReadTransaction trans(FROM_HERE, user_share_);
582 ReadNode nigori_node(&trans);
583 if (nigori_node.InitByTagLookup(kNigoriTag) != BaseNode::INIT_OK)
584 return false;
585 return IsNigoriMigratedToKeystore(nigori_node.GetNigoriSpecifics());
586 }
587
469 // This function iterates over all encrypted types. There are many scenarios in 588 // This function iterates over all encrypted types. There are many scenarios in
470 // which data for some or all types is not currently available. In that case, 589 // which data for some or all types is not currently available. In that case,
471 // the lookup of the root node will fail and we will skip encryption for that 590 // the lookup of the root node will fail and we will skip encryption for that
472 // type. 591 // type.
473 void SyncEncryptionHandlerImpl::ReEncryptEverything( 592 void SyncEncryptionHandlerImpl::ReEncryptEverything(
474 WriteTransaction* trans) { 593 WriteTransaction* trans) {
475 DCHECK(thread_checker_.CalledOnValidThread()); 594 DCHECK(thread_checker_.CalledOnValidThread());
476 DCHECK(UnlockVault(trans->GetWrappedTrans()).cryptographer.is_ready()); 595 DCHECK(UnlockVault(trans->GetWrappedTrans()).cryptographer.is_ready());
477 for (ModelTypeSet::Iterator iter = 596 for (ModelTypeSet::Iterator iter =
478 UnlockVault(trans->GetWrappedTrans()).encrypted_types.First(); 597 UnlockVault(trans->GetWrappedTrans()).encrypted_types.First();
(...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after
537 OnEncryptionComplete()); 656 OnEncryptionComplete());
538 } 657 }
539 658
540 bool SyncEncryptionHandlerImpl::ApplyNigoriUpdateImpl( 659 bool SyncEncryptionHandlerImpl::ApplyNigoriUpdateImpl(
541 const sync_pb::NigoriSpecifics& nigori, 660 const sync_pb::NigoriSpecifics& nigori,
542 syncable::BaseTransaction* const trans) { 661 syncable::BaseTransaction* const trans) {
543 DCHECK(thread_checker_.CalledOnValidThread()); 662 DCHECK(thread_checker_.CalledOnValidThread());
544 DVLOG(1) << "Applying nigori node update."; 663 DVLOG(1) << "Applying nigori node update.";
545 bool nigori_types_need_update = !UpdateEncryptedTypesFromNigori(nigori, 664 bool nigori_types_need_update = !UpdateEncryptedTypesFromNigori(nigori,
546 trans); 665 trans);
547 if (nigori.using_explicit_passphrase() && 666 bool is_nigori_migrated = IsNigoriMigratedToKeystore(nigori);
548 passphrase_state_ != CUSTOM_PASSPHRASE) { 667 if (is_nigori_migrated) {
549 passphrase_state_ = CUSTOM_PASSPHRASE; 668 migration_time_ms_ = nigori.keystore_migration_time();
550 FOR_EACH_OBSERVER(SyncEncryptionHandler::Observer, observers_, 669 PassphraseState nigori_passphrase_state =
551 OnPassphraseStateChanged(passphrase_state_)); 670 ProtoPassphraseStateToEnum(nigori.passphrase_state());
671
672 // Only update the local passphrase state if it's a valid transition:
673 // - implicit -> keystore
674 // - implicit -> frozen implicit
675 // - implicit -> custom
676 // - keystore -> custom
677 if (passphrase_state_ != nigori_passphrase_state &&
678 nigori_passphrase_state != IMPLICIT_PASSPHRASE &&
679 (passphrase_state_ == IMPLICIT_PASSPHRASE ||
680 nigori_passphrase_state == CUSTOM_PASSPHRASE)) {
681 DVLOG(1) << "Changing passphrase state from "
682 << PassphraseStateToString(passphrase_state_)
683 << " to "
684 << PassphraseStateToString(nigori_passphrase_state);
685 passphrase_state_ = nigori_passphrase_state;
686 FOR_EACH_OBSERVER(SyncEncryptionHandler::Observer, observers_,
687 OnPassphraseStateChanged(passphrase_state_));
688 }
689 if (passphrase_state_ == KEYSTORE_PASSPHRASE && encrypt_everything_) {
690 DVLOG(1) << "Changing passphrase state to FROZEN_IMPLICIT_PASSPHRASE "
691 << "due to full encryption.";
692 passphrase_state_ = FROZEN_IMPLICIT_PASSPHRASE;
693 FOR_EACH_OBSERVER(SyncEncryptionHandler::Observer, observers_,
694 OnPassphraseStateChanged(passphrase_state_));
695 }
696 } else {
697 // It's possible that while we're waiting for migration another old
698 // client enables a custom passphrase.
699 if (nigori.frozen_keybag() &&
700 passphrase_state_ != CUSTOM_PASSPHRASE) {
701 passphrase_state_ = CUSTOM_PASSPHRASE;
702 FOR_EACH_OBSERVER(SyncEncryptionHandler::Observer, observers_,
703 OnPassphraseStateChanged(passphrase_state_));
704 }
552 } 705 }
553 706
554 Cryptographer* cryptographer = &UnlockVaultMutable(trans)->cryptographer; 707 Cryptographer* cryptographer = &UnlockVaultMutable(trans)->cryptographer;
555 bool nigori_needs_new_keys = false; 708 bool nigori_needs_new_keys = false;
556 if (!nigori.encrypted().blob().empty()) { 709 if (!nigori.encryption_keybag().blob().empty()) {
557 if (cryptographer->CanDecrypt(nigori.encrypted())) { 710 // We only update the default passphrase if this was a new explicit
558 cryptographer->InstallKeys(nigori.encrypted()); 711 // passphrase. Else, since it was decryptable, it must not have been a new
559 // We only update the default passphrase if this was a new explicit 712 // key.
560 // passphrase. Else, since it was decryptable, it must not have been a new 713 bool need_new_default = false;
714 if (is_nigori_migrated) {
715 need_new_default = IsExplicitPassphrase(
716 ProtoPassphraseStateToEnum(nigori.passphrase_state()));
717 } else {
718 need_new_default = nigori.frozen_keybag();
719 }
720 if (!AttemptToInstallKeybag(nigori.encryption_keybag(),
721 need_new_default,
722 cryptographer)) {
723 // Check to see if we can decrypt the keybag using the keystore bootstrap
561 // key. 724 // key.
562 if (nigori.using_explicit_passphrase()) 725 cryptographer->SetPendingKeys(nigori.encryption_keybag());
563 cryptographer->SetDefaultKey(nigori.encrypted().key_name()); 726 if (!nigori.keystore_bootstrap().blob().empty() &&
564 727 !keystore_key_.empty()) {
565 // Check if the cryptographer's keybag is newer than the nigori's 728 if (DecryptPendingKeysWithKeystoreKey(keystore_key_,
566 // keybag. If so, we need to overwrite the nigori node. 729 nigori.keystore_bootstrap(),
567 sync_pb::EncryptedData new_keys = nigori.encrypted(); 730 cryptographer)) {
568 if (!cryptographer->GetKeys(&new_keys)) 731 nigori_needs_new_keys =
569 NOTREACHED(); 732 cryptographer->KeybagIsStale(nigori.encryption_keybag());
570 if (nigori.encrypted().SerializeAsString() != 733 } else {
571 new_keys.SerializeAsString()) 734 LOG(ERROR) << "Failed to decrypt pending keys using keystore "
572 nigori_needs_new_keys = true; 735 << "bootstrap key.";
736 }
737 }
573 } else { 738 } else {
574 cryptographer->SetPendingKeys(nigori.encrypted()); 739 // Keybag was installed. We write back our local keybag into the nigori
740 // node if the nigori node's keybag either contains less keys or
741 // has a different default key.
742 nigori_needs_new_keys =
743 cryptographer->KeybagIsStale(nigori.encryption_keybag());
575 } 744 }
576 } else { 745 } else {
746 // The nigori node has an empty encryption keybag. Attempt to write our
747 // local encryption keys into it.
748 LOG(WARNING) << "Nigori had empty encryption keybag.";
577 nigori_needs_new_keys = true; 749 nigori_needs_new_keys = true;
578 } 750 }
579 751
580 // If we've completed a sync cycle and the cryptographer isn't ready 752 // If we've completed a sync cycle and the cryptographer isn't ready
581 // yet or has pending keys, prompt the user for a passphrase. 753 // yet or has pending keys, prompt the user for a passphrase.
582 if (cryptographer->has_pending_keys()) { 754 if (cryptographer->has_pending_keys()) {
583 DVLOG(1) << "OnPassphraseRequired Sent"; 755 DVLOG(1) << "OnPassphraseRequired Sent";
584 sync_pb::EncryptedData pending_keys = cryptographer->GetPendingKeys(); 756 sync_pb::EncryptedData pending_keys = cryptographer->GetPendingKeys();
585 FOR_EACH_OBSERVER(SyncEncryptionHandler::Observer, observers_, 757 FOR_EACH_OBSERVER(SyncEncryptionHandler::Observer, observers_,
586 OnPassphraseRequired(REASON_DECRYPTION, 758 OnPassphraseRequired(REASON_DECRYPTION,
587 pending_keys)); 759 pending_keys));
588 } else if (!cryptographer->is_ready()) { 760 } else if (!cryptographer->is_ready()) {
589 DVLOG(1) << "OnPassphraseRequired sent because cryptographer is not " 761 DVLOG(1) << "OnPassphraseRequired sent because cryptographer is not "
590 << "ready"; 762 << "ready";
591 FOR_EACH_OBSERVER(SyncEncryptionHandler::Observer, observers_, 763 FOR_EACH_OBSERVER(SyncEncryptionHandler::Observer, observers_,
592 OnPassphraseRequired(REASON_ENCRYPTION, 764 OnPassphraseRequired(REASON_ENCRYPTION,
593 sync_pb::EncryptedData())); 765 sync_pb::EncryptedData()));
594 } 766 }
595 767
596 // Check if the current local encryption state is stricter/newer than the 768 // Check if the current local encryption state is stricter/newer than the
597 // nigori state. If so, we need to overwrite the nigori node with the local 769 // nigori state. If so, we need to overwrite the nigori node with the local
598 // state. 770 // state.
599 bool explicit_passphrase = passphrase_state_ == CUSTOM_PASSPHRASE; 771 bool passphrase_state_matches = true;
600 if (nigori.using_explicit_passphrase() != explicit_passphrase || 772 if (!is_nigori_migrated) {
773 DCHECK(passphrase_state_ == CUSTOM_PASSPHRASE ||
774 passphrase_state_ == IMPLICIT_PASSPHRASE);
775 passphrase_state_matches =
776 nigori.frozen_keybag() == IsExplicitPassphrase(passphrase_state_);
777 } else {
778 passphrase_state_matches =
779 (ProtoPassphraseStateToEnum(nigori.passphrase_state()) ==
780 passphrase_state_);
781 }
782 if (!passphrase_state_matches ||
601 nigori.encrypt_everything() != encrypt_everything_ || 783 nigori.encrypt_everything() != encrypt_everything_ ||
602 nigori_types_need_update || 784 nigori_types_need_update ||
603 nigori_needs_new_keys) { 785 nigori_needs_new_keys) {
786 DVLOG(1) << "Triggering nigori rewrite.";
604 return false; 787 return false;
605 } 788 }
606 return true; 789 return true;
607 } 790 }
608 791
609 void SyncEncryptionHandlerImpl::RewriteNigori() { 792 void SyncEncryptionHandlerImpl::RewriteNigori() {
610 DVLOG(1) << "Overwriting stale nigori node."; 793 DVLOG(1) << "Writing local encryption state into nigori.";
611 DCHECK(thread_checker_.CalledOnValidThread()); 794 DCHECK(thread_checker_.CalledOnValidThread());
612 WriteTransaction trans(FROM_HERE, user_share_); 795 WriteTransaction trans(FROM_HERE, user_share_);
613 WriteEncryptionStateToNigori(&trans); 796 WriteEncryptionStateToNigori(&trans);
614 } 797 }
615 798
616 void SyncEncryptionHandlerImpl::WriteEncryptionStateToNigori( 799 void SyncEncryptionHandlerImpl::WriteEncryptionStateToNigori(
617 WriteTransaction* trans) { 800 WriteTransaction* trans) {
618 DCHECK(thread_checker_.CalledOnValidThread()); 801 DCHECK(thread_checker_.CalledOnValidThread());
619 WriteNode nigori_node(trans); 802 WriteNode nigori_node(trans);
620 // This can happen in tests that don't have nigori nodes. 803 // This can happen in tests that don't have nigori nodes.
621 if (nigori_node.InitByTagLookup(kNigoriTag) != BaseNode::INIT_OK) 804 if (nigori_node.InitByTagLookup(kNigoriTag) != BaseNode::INIT_OK)
622 return; 805 return;
806
623 sync_pb::NigoriSpecifics nigori = nigori_node.GetNigoriSpecifics(); 807 sync_pb::NigoriSpecifics nigori = nigori_node.GetNigoriSpecifics();
624 const Cryptographer& cryptographer = 808 const Cryptographer& cryptographer =
625 UnlockVault(trans->GetWrappedTrans()).cryptographer; 809 UnlockVault(trans->GetWrappedTrans()).cryptographer;
626 if (cryptographer.is_ready() &&
627 nigori_overwrite_count_ < kNigoriOverwriteLimit) {
628 // Does not modify the encrypted blob if the unencrypted data already
629 // matches what is about to be written.
630 sync_pb::EncryptedData original_keys = nigori.encrypted();
631 if (!cryptographer.GetKeys(nigori.mutable_encrypted()))
632 NOTREACHED();
633 810
634 if (nigori.encrypted().SerializeAsString() != 811 // Will not do anything if we shouldn't or can't migrate. Otherwise
635 original_keys.SerializeAsString()) { 812 // migrates, writing the full encryption state as it does.
636 // We've updated the nigori node's encryption keys. In order to prevent 813 if (!AttemptToMigrateNigoriToKeystore(trans, &nigori_node)) {
637 // a possible looping of two clients constantly overwriting each other, 814 if (cryptographer.is_ready() &&
638 // we limit the absolute number of overwrites per client instantiation. 815 nigori_overwrite_count_ < kNigoriOverwriteLimit) {
639 nigori_overwrite_count_++; 816 // Does not modify the encrypted blob if the unencrypted data already
640 UMA_HISTOGRAM_COUNTS("Sync.AutoNigoriOverwrites", 817 // matches what is about to be written.
641 nigori_overwrite_count_); 818 sync_pb::EncryptedData original_keys = nigori.encryption_keybag();
819 if (!cryptographer.GetKeys(nigori.mutable_encryption_keybag()))
820 NOTREACHED();
821
822 if (nigori.encryption_keybag().SerializeAsString() !=
823 original_keys.SerializeAsString()) {
824 // We've updated the nigori node's encryption keys. In order to prevent
825 // a possible looping of two clients constantly overwriting each other,
826 // we limit the absolute number of overwrites per client instantiation.
827 nigori_overwrite_count_++;
828 UMA_HISTOGRAM_COUNTS("Sync.AutoNigoriOverwrites",
829 nigori_overwrite_count_);
830 }
831
832 // Note: we don't try to set frozen_keybag here since if that
833 // is lost the user can always set it again (and we don't want to clobber
834 // any migration state). The main goal at this point is to preserve
835 // the encryption keys so all data remains decryptable.
642 } 836 }
837 syncable::UpdateNigoriFromEncryptedTypes(
838 UnlockVault(trans->GetWrappedTrans()).encrypted_types,
839 encrypt_everything_,
840 &nigori);
643 841
644 // Note: we don't try to set using_explicit_passphrase here since if that 842 // If nothing has changed, this is a no-op.
645 // is lost the user can always set it again. The main point is to preserve 843 nigori_node.SetNigoriSpecifics(nigori);
646 // the encryption keys so all data remains decryptable.
647 } 844 }
648 syncable::UpdateNigoriFromEncryptedTypes(
649 UnlockVault(trans->GetWrappedTrans()).encrypted_types,
650 encrypt_everything_,
651 &nigori);
652
653 // If nothing has changed, this is a no-op.
654 nigori_node.SetNigoriSpecifics(nigori);
655 } 845 }
656 846
657 bool SyncEncryptionHandlerImpl::UpdateEncryptedTypesFromNigori( 847 bool SyncEncryptionHandlerImpl::UpdateEncryptedTypesFromNigori(
658 const sync_pb::NigoriSpecifics& nigori, 848 const sync_pb::NigoriSpecifics& nigori,
659 syncable::BaseTransaction* const trans) { 849 syncable::BaseTransaction* const trans) {
660 DCHECK(thread_checker_.CalledOnValidThread()); 850 DCHECK(thread_checker_.CalledOnValidThread());
661 ModelTypeSet* encrypted_types = &UnlockVaultMutable(trans)->encrypted_types; 851 ModelTypeSet* encrypted_types = &UnlockVaultMutable(trans)->encrypted_types;
662 if (nigori.encrypt_everything()) { 852 if (nigori.encrypt_everything()) {
663 if (!encrypt_everything_) { 853 EnableEncryptEverythingImpl(trans);
664 encrypt_everything_ = true;
665 *encrypted_types = ModelTypeSet::All();
666 DVLOG(1) << "Enabling encrypt everything via nigori node update";
667 FOR_EACH_OBSERVER(
668 Observer, observers_,
669 OnEncryptedTypesChanged(*encrypted_types, encrypt_everything_));
670 }
671 DCHECK(encrypted_types->Equals(ModelTypeSet::All())); 854 DCHECK(encrypted_types->Equals(ModelTypeSet::All()));
672 return true; 855 return true;
856 } else if (encrypt_everything_) {
857 DCHECK(encrypted_types->Equals(ModelTypeSet::All()));
858 return false;
673 } 859 }
674 860
675 ModelTypeSet nigori_encrypted_types; 861 ModelTypeSet nigori_encrypted_types;
676 nigori_encrypted_types = syncable::GetEncryptedTypesFromNigori(nigori); 862 nigori_encrypted_types = syncable::GetEncryptedTypesFromNigori(nigori);
677 nigori_encrypted_types.PutAll(SensitiveTypes()); 863 nigori_encrypted_types.PutAll(SensitiveTypes());
678 864
679 // If anything more than the sensitive types were encrypted, and 865 // If anything more than the sensitive types were encrypted, and
680 // encrypt_everything is not explicitly set to false, we assume it means 866 // encrypt_everything is not explicitly set to false, we assume it means
681 // a client intended to enable encrypt everything. 867 // a client intended to enable encrypt everything.
682 if (!nigori.has_encrypt_everything() && 868 if (!nigori.has_encrypt_everything() &&
683 !Difference(nigori_encrypted_types, SensitiveTypes()).Empty()) { 869 !Difference(nigori_encrypted_types, SensitiveTypes()).Empty()) {
684 if (!encrypt_everything_) { 870 if (!encrypt_everything_) {
685 encrypt_everything_ = true; 871 encrypt_everything_ = true;
686 *encrypted_types = ModelTypeSet::All(); 872 *encrypted_types = ModelTypeSet::All();
687 FOR_EACH_OBSERVER( 873 FOR_EACH_OBSERVER(
688 Observer, observers_, 874 Observer, observers_,
689 OnEncryptedTypesChanged(*encrypted_types, encrypt_everything_)); 875 OnEncryptedTypesChanged(*encrypted_types, encrypt_everything_));
690 } 876 }
691 DCHECK(encrypted_types->Equals(ModelTypeSet::All())); 877 DCHECK(encrypted_types->Equals(ModelTypeSet::All()));
692 return false; 878 return false;
693 } 879 }
694 880
695 MergeEncryptedTypes(nigori_encrypted_types, trans); 881 MergeEncryptedTypes(nigori_encrypted_types, trans);
696 return encrypted_types->Equals(nigori_encrypted_types); 882 return encrypted_types->Equals(nigori_encrypted_types);
697 } 883 }
698 884
885 void SyncEncryptionHandlerImpl::SetCustomPassphrase(
886 const std::string& passphrase,
887 WriteTransaction* trans,
888 WriteNode* nigori_node) {
889 DCHECK(thread_checker_.CalledOnValidThread());
890 KeyParams key_params = {"localhost", "dummy", passphrase};
891
892 if (passphrase_state_ != KEYSTORE_PASSPHRASE) {
893 DVLOG(1) << "Failing to set a custom passphrase because one has already "
894 << "been set.";
895 FinishSetPassphrase(false, "", trans, nigori_node);
896 return;
897 }
898
899 Cryptographer* cryptographer =
900 &UnlockVaultMutable(trans->GetWrappedTrans())->cryptographer;
901 if (cryptographer->has_pending_keys()) {
902 // This theoretically shouldn't happen, because the only way to have pending
903 // keys after migrating to keystore support is if a custom passphrase was
tim (not reviewing) 2012/09/06 01:04:20 Is there an assertion we can make (DCHECK) that we
Nicolas Zea 2012/09/06 21:45:27 Done.
904 // set, which should update passpshrase_state_ and should be caught by the
905 // if statement above. For the sake of safety though, we check for it in
906 // case a client is misbehaving.
907 LOG(ERROR) << "Failing to set custom passphrase because of pending keys.";
908 FinishSetPassphrase(false, "", trans, nigori_node);
909 return;
910 }
911
912 std::string bootstrap_token;
913 if (cryptographer->AddKey(key_params)) {
914 DVLOG(1) << "Setting custom passphrase.";
915 cryptographer->GetBootstrapToken(&bootstrap_token);
916 passphrase_state_ = CUSTOM_PASSPHRASE;
917 FOR_EACH_OBSERVER(SyncEncryptionHandler::Observer, observers_,
918 OnPassphraseStateChanged(passphrase_state_));
919 } else {
920 NOTREACHED() << "Failed to add key to cryptographer.";
921 return;
922 }
923 FinishSetPassphrase(true, bootstrap_token, trans, nigori_node);
924 }
925
926 void SyncEncryptionHandlerImpl::DecryptExplicitPassphrase(
927 const std::string& passphrase,
928 WriteTransaction* trans,
929 WriteNode* nigori_node) {
930 DCHECK(thread_checker_.CalledOnValidThread());
931 DCHECK(IsExplicitPassphrase(passphrase_state_));
932 KeyParams key_params = {"localhost", "dummy", passphrase};
933
934 Cryptographer* cryptographer =
935 &UnlockVaultMutable(trans->GetWrappedTrans())->cryptographer;
936 if (!cryptographer->has_pending_keys()) {
937 // Note that this *can* happen in a rare situation where data is
938 // re-encrypted on another client while a SetDecryptionPassphrase() call is
939 // in-flight on this client. It is rare enough that we choose to do nothing.
940 NOTREACHED() << "Attempt to set decryption passphrase failed because there "
941 << "were no pending keys.";
942 return;
943 }
944
945 DCHECK(IsExplicitPassphrase(passphrase_state_));
946 bool success = false;
947 std::string bootstrap_token;
948 if (cryptographer->DecryptPendingKeys(key_params)) {
949 DVLOG(1) << "Explicit passphrase accepted for decryption.";
950 cryptographer->GetBootstrapToken(&bootstrap_token);
951 success = true;
952 } else {
953 DVLOG(1) << "Explicit passphrase failed to decrypt.";
954 success = false;
955 }
956 if (success && !keystore_key_.empty()) {
957 // Should already be part of the encryption keybag, but we add it just
958 // in case.
959 KeyParams key_params = {"localhost", "dummy", keystore_key_};
960 cryptographer->AddNonDefaultKey(key_params);
961 }
962 FinishSetPassphrase(success, bootstrap_token, trans, nigori_node);
963 }
964
699 void SyncEncryptionHandlerImpl::FinishSetPassphrase( 965 void SyncEncryptionHandlerImpl::FinishSetPassphrase(
700 bool success, 966 bool success,
701 const std::string& bootstrap_token, 967 const std::string& bootstrap_token,
tim (not reviewing) 2012/09/06 01:04:20 Why do we pass this in if we're poking around at t
Nicolas Zea 2012/09/06 21:45:27 Due to the old SetEncryptionPassphrase logic, we n
702 bool is_explicit,
703 WriteTransaction* trans, 968 WriteTransaction* trans,
704 WriteNode* nigori_node) { 969 WriteNode* nigori_node) {
705 DCHECK(thread_checker_.CalledOnValidThread()); 970 DCHECK(thread_checker_.CalledOnValidThread());
706 FOR_EACH_OBSERVER( 971 FOR_EACH_OBSERVER(
707 SyncEncryptionHandler::Observer, 972 SyncEncryptionHandler::Observer,
708 observers_, 973 observers_,
709 OnCryptographerStateChanged( 974 OnCryptographerStateChanged(
710 &UnlockVaultMutable(trans->GetWrappedTrans())->cryptographer)); 975 &UnlockVaultMutable(trans->GetWrappedTrans())->cryptographer));
711 976
712 // It's possible we need to change the bootstrap token even if we failed to 977 // It's possible we need to change the bootstrap token even if we failed to
713 // set the passphrase (for example if we need to preserve the new GAIA 978 // set the passphrase (for example if we need to preserve the new GAIA
714 // passphrase). 979 // passphrase).
tim (not reviewing) 2012/09/06 01:04:20 I guess this is still relevant...
Nicolas Zea 2012/09/06 21:45:27 Right, see my response above.
715 if (!bootstrap_token.empty()) { 980 if (!bootstrap_token.empty()) {
716 DVLOG(1) << "Passphrase bootstrap token updated."; 981 DVLOG(1) << "Passphrase bootstrap token updated.";
717 FOR_EACH_OBSERVER(SyncEncryptionHandler::Observer, observers_, 982 FOR_EACH_OBSERVER(SyncEncryptionHandler::Observer, observers_,
718 OnBootstrapTokenUpdated(bootstrap_token, 983 OnBootstrapTokenUpdated(bootstrap_token,
719 PASSPHRASE_BOOTSTRAP_TOKEN)); 984 PASSPHRASE_BOOTSTRAP_TOKEN));
720 } 985 }
721 986
722 const Cryptographer& cryptographer = 987 const Cryptographer& cryptographer =
723 UnlockVault(trans->GetWrappedTrans()).cryptographer; 988 UnlockVault(trans->GetWrappedTrans()).cryptographer;
724 if (!success) { 989 if (!success) {
725 if (cryptographer.is_ready()) { 990 if (cryptographer.is_ready()) {
726 LOG(ERROR) << "Attempt to change passphrase failed while cryptographer " 991 LOG(ERROR) << "Attempt to change passphrase failed while cryptographer "
727 << "was ready."; 992 << "was ready.";
728 } else if (cryptographer.has_pending_keys()) { 993 } else if (cryptographer.has_pending_keys()) {
729 FOR_EACH_OBSERVER(SyncEncryptionHandler::Observer, observers_, 994 FOR_EACH_OBSERVER(SyncEncryptionHandler::Observer, observers_,
730 OnPassphraseRequired(REASON_DECRYPTION, 995 OnPassphraseRequired(REASON_DECRYPTION,
731 cryptographer.GetPendingKeys())); 996 cryptographer.GetPendingKeys()));
732 } else { 997 } else {
733 FOR_EACH_OBSERVER(SyncEncryptionHandler::Observer, observers_, 998 FOR_EACH_OBSERVER(SyncEncryptionHandler::Observer, observers_,
734 OnPassphraseRequired(REASON_ENCRYPTION, 999 OnPassphraseRequired(REASON_ENCRYPTION,
735 sync_pb::EncryptedData())); 1000 sync_pb::EncryptedData()));
736 } 1001 }
737 return; 1002 return;
738 } 1003 }
739 1004 DCHECK(success);
740 DCHECK(cryptographer.is_ready()); 1005 DCHECK(cryptographer.is_ready());
741 1006
742 // TODO(zea): trigger migration if necessary. 1007 // Will do nothing if we're already properly migrated or unable to migrate.
743 1008 // Otherwise will update the nigori node with the current migrated state,
744 sync_pb::NigoriSpecifics specifics(nigori_node->GetNigoriSpecifics()); 1009 // writing all encryption state as it does.
745 // Does not modify specifics.encrypted() if the original decrypted data was 1010 if (!AttemptToMigrateNigoriToKeystore(trans, nigori_node)) {
746 // the same. 1011 sync_pb::NigoriSpecifics nigori(nigori_node->GetNigoriSpecifics());
747 if (!cryptographer.GetKeys(specifics.mutable_encrypted())) 1012 // Does not modify nigori.encryption_keybag() if the original decrypted
748 NOTREACHED(); 1013 // data was the same.
749 if (is_explicit && passphrase_state_ != CUSTOM_PASSPHRASE) { 1014 if (!cryptographer.GetKeys(nigori.mutable_encryption_keybag()))
750 passphrase_state_ = CUSTOM_PASSPHRASE; 1015 NOTREACHED();
751 FOR_EACH_OBSERVER(SyncEncryptionHandler::Observer, observers_, 1016 if (IsNigoriMigratedToKeystore(nigori)) {
752 OnPassphraseStateChanged(passphrase_state_)); 1017 DCHECK(keystore_key_.empty() || IsExplicitPassphrase(passphrase_state_));
1018 DVLOG(1) << "Leaving nigori migration state untouched after setting"
1019 << " passphrase.";
1020 } else {
1021 nigori.set_frozen_keybag(
1022 IsExplicitPassphrase(passphrase_state_));
1023 }
1024 nigori_node->SetNigoriSpecifics(nigori);
753 } 1025 }
754 specifics.set_using_explicit_passphrase(is_explicit);
755 nigori_node->SetNigoriSpecifics(specifics);
756 1026
757 // Must do this after OnPassphraseStateChanged, in order to ensure the PSS 1027 // Must do this after OnPassphraseStateChanged, in order to ensure the PSS
758 // checks the passphrase state after it has been set. 1028 // checks the passphrase state after it has been set.
759 FOR_EACH_OBSERVER(SyncEncryptionHandler::Observer, observers_, 1029 FOR_EACH_OBSERVER(SyncEncryptionHandler::Observer, observers_,
760 OnPassphraseAccepted()); 1030 OnPassphraseAccepted());
761 1031
762 // Does nothing if everything is already encrypted. 1032 // Does nothing if everything is already encrypted.
1033 // TODO(zea): If we just migrated and enabled encryption, this will be
1034 // redundant. Figure out a way to not do this unnecessarily.
763 ReEncryptEverything(trans); 1035 ReEncryptEverything(trans);
764 } 1036 }
765 1037
766 void SyncEncryptionHandlerImpl::MergeEncryptedTypes( 1038 void SyncEncryptionHandlerImpl::MergeEncryptedTypes(
767 ModelTypeSet new_encrypted_types, 1039 ModelTypeSet new_encrypted_types,
768 syncable::BaseTransaction* const trans) { 1040 syncable::BaseTransaction* const trans) {
769 DCHECK(thread_checker_.CalledOnValidThread()); 1041 DCHECK(thread_checker_.CalledOnValidThread());
770 ModelTypeSet* encrypted_types = &UnlockVaultMutable(trans)->encrypted_types; 1042 ModelTypeSet* encrypted_types = &UnlockVaultMutable(trans)->encrypted_types;
771 if (!encrypted_types->HasAll(new_encrypted_types)) { 1043 if (!encrypted_types->HasAll(new_encrypted_types)) {
772 *encrypted_types = new_encrypted_types; 1044 *encrypted_types = new_encrypted_types;
773 FOR_EACH_OBSERVER( 1045 FOR_EACH_OBSERVER(
774 Observer, observers_, 1046 Observer, observers_,
775 OnEncryptedTypesChanged(*encrypted_types, encrypt_everything_)); 1047 OnEncryptedTypesChanged(*encrypted_types, encrypt_everything_));
776 } 1048 }
777 } 1049 }
778 1050
779 SyncEncryptionHandlerImpl::Vault* SyncEncryptionHandlerImpl::UnlockVaultMutable( 1051 SyncEncryptionHandlerImpl::Vault* SyncEncryptionHandlerImpl::UnlockVaultMutable(
780 syncable::BaseTransaction* const trans) { 1052 syncable::BaseTransaction* const trans) {
781 DCHECK_EQ(user_share_->directory.get(), trans->directory()); 1053 DCHECK_EQ(user_share_->directory.get(), trans->directory());
782 return &vault_unsafe_; 1054 return &vault_unsafe_;
783 } 1055 }
784 1056
785 const SyncEncryptionHandlerImpl::Vault& SyncEncryptionHandlerImpl::UnlockVault( 1057 const SyncEncryptionHandlerImpl::Vault& SyncEncryptionHandlerImpl::UnlockVault(
786 syncable::BaseTransaction* const trans) const { 1058 syncable::BaseTransaction* const trans) const {
787 DCHECK_EQ(user_share_->directory.get(), trans->directory()); 1059 DCHECK_EQ(user_share_->directory.get(), trans->directory());
788 return vault_unsafe_; 1060 return vault_unsafe_;
789 } 1061 }
790 1062
1063 bool SyncEncryptionHandlerImpl::ShouldTriggerMigration(
1064 const sync_pb::NigoriSpecifics& nigori,
1065 const Cryptographer& cryptographer) const {
1066 DCHECK(thread_checker_.CalledOnValidThread());
1067 // TODO(zea): once we're willing to have the keystore key be the only
1068 // encryption key, change this to !has_pending_keys(). For now, we need the
1069 // cryptographer to be initialized with the current GAIA pass so that older
1070 // clients (that don't have keystore support) can decrypt the keybag.
1071 if (!cryptographer.is_ready())
1072 return false;
1073 if (IsNigoriMigratedToKeystore(nigori)) {
1074 // If the nigori is already migrated but has an old passphrase state,
1075 // re-migrate. Similarly, if the nigori has an explicit passphrase but
1076 // does not have full encryption, or the nigori has an implicit passphrase
1077 // but does have full encryption, re-migrate.
1078 if (passphrase_state_ != KEYSTORE_PASSPHRASE &&
1079 nigori.passphrase_state() ==
1080 sync_pb::NigoriSpecifics::KEYSTORE_PASSPHRASE) {
1081 return true;
1082 } else if (IsExplicitPassphrase(passphrase_state_) &&
1083 !encrypt_everything_) {
1084 return true;
1085 } else if (passphrase_state_ == KEYSTORE_PASSPHRASE &&
1086 encrypt_everything_) {
1087 return true;
1088 } else {
1089 return false;
1090 }
1091 } else if (keystore_key_.empty()) {
1092 // If we haven't already migrated, we don't want to do anything unless
1093 // a keystore key is available (so that those clients without keystore
1094 // encryption enabled aren't forced into new states, e.g. frozen implicit
1095 // passphrase).
1096 return false;
1097 }
1098 return true;
1099 }
1100
1101 bool SyncEncryptionHandlerImpl::AttemptToMigrateNigoriToKeystore(
1102 WriteTransaction* trans,
1103 WriteNode* nigori_node) {
1104 DCHECK(thread_checker_.CalledOnValidThread());
1105 const sync_pb::NigoriSpecifics& old_nigori =
1106 nigori_node->GetNigoriSpecifics();
1107 Cryptographer* cryptographer =
1108 &UnlockVaultMutable(trans->GetWrappedTrans())->cryptographer;
1109
1110 if (!ShouldTriggerMigration(old_nigori, *cryptographer))
1111 return false;
1112
1113 DVLOG(1) << "Starting nigori migration to keystore support.";
1114 if (migration_time_ms_ == 0)
1115 migration_time_ms_ = TimeToProtoTime(base::Time::Now());
1116 sync_pb::NigoriSpecifics migrated_nigori(old_nigori);
1117 migrated_nigori.set_keystore_migration_time(migration_time_ms_);
1118
1119 PassphraseState new_passphrase_state = passphrase_state_;
1120 bool new_encrypt_everything = encrypt_everything_;
1121 if (encrypt_everything_ && !IsExplicitPassphrase(passphrase_state_)) {
1122 DVLOG(1) << "Switching to frozen implicit passphrase due to already having "
1123 << "full encryption.";
1124 new_passphrase_state = FROZEN_IMPLICIT_PASSPHRASE;
1125 migrated_nigori.clear_keystore_bootstrap();
1126 } else if (IsExplicitPassphrase(passphrase_state_)) {
1127 DVLOG_IF(1, !encrypt_everything_) << "Enabling encrypt everything due to "
1128 << "explicit passphrase";
1129 new_encrypt_everything = true;
1130 migrated_nigori.clear_keystore_bootstrap();
1131 } else {
1132 DCHECK_EQ(passphrase_state_, IMPLICIT_PASSPHRASE);
1133 DCHECK(!encrypt_everything_);
1134 new_passphrase_state = KEYSTORE_PASSPHRASE;
1135 DVLOG(1) << "Switching to keystore passphrase state.";
1136 }
1137 migrated_nigori.set_encrypt_everything(new_encrypt_everything);
1138 migrated_nigori.set_passphrase_state(
1139 EnumPassphraseStateToProto(new_passphrase_state));
1140 migrated_nigori.set_frozen_keybag(true);
1141
1142 if (!keystore_key_.empty()) {
1143 KeyParams key_params = {"localhost", "dummy", keystore_key_};
1144 if (!cryptographer->AddNonDefaultKey(key_params)) {
1145 LOG(ERROR) << "Failed to add keystore key as non-default key.";
1146 return false;
1147 }
1148 }
1149 if (new_passphrase_state == KEYSTORE_PASSPHRASE &&
1150 !GetKeystoreBootstrapKey(
1151 *cryptographer,
1152 keystore_key_,
1153 migrated_nigori.mutable_keystore_bootstrap())) {
1154 LOG(ERROR) << "Failed to extract keystore bootstrap key.";
1155 return false;
1156 }
1157 if (!cryptographer->GetKeys(migrated_nigori.mutable_encryption_keybag())) {
1158 LOG(ERROR) << "Failed to extract encryption keybag.";
1159 return false;
1160 }
1161
1162 DVLOG(1) << "Completing nigori migration to keystore support.";
1163 nigori_node->SetNigoriSpecifics(migrated_nigori);
1164 if (passphrase_state_ != new_passphrase_state) {
1165 passphrase_state_ = new_passphrase_state;
1166 FOR_EACH_OBSERVER(SyncEncryptionHandler::Observer, observers_,
1167 OnPassphraseStateChanged(passphrase_state_));
1168 }
1169 if (new_encrypt_everything && !encrypt_everything_) {
1170 EnableEncryptEverythingImpl(trans->GetWrappedTrans());
1171 ReEncryptEverything(trans);
1172 }
1173 return true;
1174 }
1175
1176 bool SyncEncryptionHandlerImpl::GetKeystoreBootstrapKey(
1177 const Cryptographer& cryptographer,
1178 const std::string& keystore_key,
1179 sync_pb::EncryptedData* encrypted_blob) {
1180 DCHECK(thread_checker_.CalledOnValidThread());
1181 DCHECK(!keystore_key.empty());
1182 DCHECK(cryptographer.is_ready());
1183 std::string bootstrap_token;
1184 if (!cryptographer.GetBootstrapToken(&bootstrap_token)) {
1185 LOG(ERROR) << "Failed to get cryptographer bootstrap token.";
1186 return false;
1187 }
1188 Cryptographer temp_cryptographer(cryptographer.encryptor());
1189 KeyParams key_params = {"localhost", "dummy", keystore_key};
1190 if (!temp_cryptographer.AddKey(key_params))
1191 return false;
1192 if (!temp_cryptographer.EncryptString(bootstrap_token, encrypted_blob))
1193 return false;
1194 return true;
1195 }
1196
1197 bool SyncEncryptionHandlerImpl::AttemptToInstallKeybag(
1198 const sync_pb::EncryptedData& keybag,
1199 bool update_default,
1200 Cryptographer* cryptographer) {
1201 if (!cryptographer->CanDecrypt(keybag))
1202 return false;
1203 cryptographer->InstallKeys(keybag);
1204 if (update_default)
1205 cryptographer->SetDefaultKey(keybag.key_name());
1206 return true;
1207 }
1208
1209 void SyncEncryptionHandlerImpl::EnableEncryptEverythingImpl(
1210 syncable::BaseTransaction* const trans) {
1211 ModelTypeSet* encrypted_types = &UnlockVaultMutable(trans)->encrypted_types;
1212 if (encrypt_everything_) {
1213 DCHECK(encrypted_types->Equals(ModelTypeSet::All()));
1214 return;
1215 }
1216 encrypt_everything_ = true;
1217 *encrypted_types = ModelTypeSet::All();
1218 FOR_EACH_OBSERVER(
1219 Observer, observers_,
1220 OnEncryptedTypesChanged(*encrypted_types, encrypt_everything_));
1221 }
1222
1223 bool SyncEncryptionHandlerImpl::DecryptPendingKeysWithKeystoreKey(
1224 const std::string& keystore_key,
1225 const sync_pb::EncryptedData& keystore_bootstrap,
1226 Cryptographer* cryptographer) {
1227 DCHECK(cryptographer->has_pending_keys());
1228 if (keystore_bootstrap.blob().empty())
1229 return false;
tim (not reviewing) 2012/09/06 01:04:20 We don't need to notify if this fails because ther
Nicolas Zea 2012/09/06 21:45:27 If this fails, we'll remain in a pending keys stat
tim (not reviewing) 2012/09/10 20:41:52 How is the explicit passphrase UI triggered, then?
1230 Cryptographer temp_cryptographer(cryptographer->encryptor());
1231 KeyParams keystore_params = {"localhost", "dummy", keystore_key_};
1232 if (temp_cryptographer.AddKey(keystore_params) &&
1233 temp_cryptographer.CanDecrypt(keystore_bootstrap)) {
tim (not reviewing) 2012/09/06 01:04:20 "bootstrap tokens" as defined by Cryptographer are
Nicolas Zea 2012/09/06 21:45:27 Done.
1234 // Someone else migrated the nigori for us! How generous! Go ahead and
1235 // install both the keystore key and the new default encryption key
1236 // (i.e. the one provided by the bootstrap key) into the
1237 // cryptographer.
1238 // The keystore bootstrap is a keystore encrypted bootstrap token containing
1239 // the current default encryption key (and as such should be able to
1240 // decrypt the encryption keybag).
1241 DVLOG(1) << "Attempting to decrypt pending keys using "
1242 << "keystore bootstrap.";
1243 std::string temp_bootstrap =
1244 temp_cryptographer.DecryptToString(keystore_bootstrap);
1245 // This will decrypt the pending keys and add them if possible.
1246 // The encryption key within temp_bootstrap will be the default after.
1247 cryptographer->AddKeyFromBootstrapToken(temp_bootstrap);
1248 // Theoretically the encryption keybag should already contain the keystore
1249 // key. We explicitly add it as a safety measure.
1250 cryptographer->AddNonDefaultKey(keystore_params);
1251 if (cryptographer->is_ready()) {
1252 DVLOG(1) << "Keystore bootstrap decrypted pending keys.";
1253 FOR_EACH_OBSERVER(
1254 SyncEncryptionHandler::Observer,
1255 observers_,
1256 OnBootstrapTokenUpdated(temp_bootstrap,
1257 PASSPHRASE_BOOTSTRAP_TOKEN));
1258 FOR_EACH_OBSERVER(
1259 SyncEncryptionHandler::Observer,
1260 observers_,
1261 OnCryptographerStateChanged(cryptographer));
1262 return true;
1263 }
1264 }
1265 return false;
1266 }
1267
791 } // namespace browser_sync 1268 } // namespace browser_sync
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698