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

Side by Side Diff: sync/util/cryptographer.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/util/cryptographer.h" 5 #include "sync/util/cryptographer.h"
6 6
7 #include <algorithm> 7 #include <algorithm>
8 8
9 #include "base/base64.h" 9 #include "base/base64.h"
10 #include "base/basictypes.h"
10 #include "base/logging.h" 11 #include "base/logging.h"
11 #include "sync/protocol/nigori_specifics.pb.h" 12 #include "sync/protocol/nigori_specifics.pb.h"
12 #include "sync/util/encryptor.h" 13 #include "sync/util/encryptor.h"
13 14
14 namespace syncer { 15 namespace syncer {
15 16
16 const char kNigoriTag[] = "google_chrome_nigori"; 17 const char kNigoriTag[] = "google_chrome_nigori";
17 18
18 // We name a particular Nigori instance (ie. a triplet consisting of a hostname, 19 // We name a particular Nigori instance (ie. a triplet consisting of a hostname,
19 // a username, and a password) by calling Permute on this string. Since the 20 // a username, and a password) by calling Permute on this string. Since the
(...skipping 10 matching lines...) Expand all
30 31
31 32
32 void Cryptographer::Bootstrap(const std::string& restored_bootstrap_token) { 33 void Cryptographer::Bootstrap(const std::string& restored_bootstrap_token) {
33 if (is_initialized()) { 34 if (is_initialized()) {
34 NOTREACHED(); 35 NOTREACHED();
35 return; 36 return;
36 } 37 }
37 38
38 scoped_ptr<Nigori> nigori(UnpackBootstrapToken(restored_bootstrap_token)); 39 scoped_ptr<Nigori> nigori(UnpackBootstrapToken(restored_bootstrap_token));
39 if (nigori.get()) 40 if (nigori.get())
40 AddKeyImpl(nigori.Pass()); 41 AddKeyImpl(nigori.Pass(), true);
41 } 42 }
42 43
43 bool Cryptographer::CanDecrypt(const sync_pb::EncryptedData& data) const { 44 bool Cryptographer::CanDecrypt(const sync_pb::EncryptedData& data) const {
44 return nigoris_.end() != nigoris_.find(data.key_name()); 45 return nigoris_.end() != nigoris_.find(data.key_name());
45 } 46 }
46 47
47 bool Cryptographer::CanDecryptUsingDefaultKey( 48 bool Cryptographer::CanDecryptUsingDefaultKey(
48 const sync_pb::EncryptedData& data) const { 49 const sync_pb::EncryptedData& data) const {
49 return !default_nigori_name_.empty() && 50 return !default_nigori_name_.empty() &&
50 data.key_name() == default_nigori_name_; 51 data.key_name() == default_nigori_name_;
51 } 52 }
52 53
53 bool Cryptographer::Encrypt( 54 bool Cryptographer::Encrypt(
54 const ::google::protobuf::MessageLite& message, 55 const ::google::protobuf::MessageLite& message,
55 sync_pb::EncryptedData* encrypted) const { 56 sync_pb::EncryptedData* encrypted) const {
56 DCHECK(encrypted); 57 DCHECK(encrypted);
57 if (default_nigori_name_.empty()) { 58 if (default_nigori_name_.empty()) {
58 LOG(ERROR) << "Cryptographer not ready, failed to encrypt."; 59 LOG(ERROR) << "Cryptographer not ready, failed to encrypt.";
59 return false; 60 return false;
60 } 61 }
61 NigoriMap::const_iterator default_nigori =
62 nigoris_.find(default_nigori_name_);
63 if (default_nigori == nigoris_.end()) {
64 LOG(ERROR) << "Corrupt default key.";
65 return false;
66 }
67 62
68 std::string serialized; 63 std::string serialized;
69 if (!message.SerializeToString(&serialized)) { 64 if (!message.SerializeToString(&serialized)) {
70 LOG(ERROR) << "Message is invalid/missing a required field."; 65 LOG(ERROR) << "Message is invalid/missing a required field.";
71 return false; 66 return false;
72 } 67 }
73 68
69 return EncryptString(serialized, encrypted);
70 }
71
72 bool Cryptographer::EncryptString(
73 const std::string& serialized,
74 sync_pb::EncryptedData* encrypted) const {
74 if (CanDecryptUsingDefaultKey(*encrypted)) { 75 if (CanDecryptUsingDefaultKey(*encrypted)) {
75 const std::string& original_serialized = DecryptToString(*encrypted); 76 const std::string& original_serialized = DecryptToString(*encrypted);
76 if (original_serialized == serialized) { 77 if (original_serialized == serialized) {
77 DVLOG(2) << "Re-encryption unnecessary, encrypted data already matches."; 78 DVLOG(2) << "Re-encryption unnecessary, encrypted data already matches.";
78 return true; 79 return true;
79 } 80 }
80 } 81 }
81 82
83 NigoriMap::const_iterator default_nigori =
84 nigoris_.find(default_nigori_name_);
85 if (default_nigori == nigoris_.end()) {
86 LOG(ERROR) << "Corrupt default key.";
87 return false;
88 }
89
82 encrypted->set_key_name(default_nigori_name_); 90 encrypted->set_key_name(default_nigori_name_);
83 if (!default_nigori->second->Encrypt(serialized, 91 if (!default_nigori->second->Encrypt(serialized,
84 encrypted->mutable_blob())) { 92 encrypted->mutable_blob())) {
85 LOG(ERROR) << "Failed to encrypt data."; 93 LOG(ERROR) << "Failed to encrypt data.";
86 return false; 94 return false;
87 } 95 }
88 return true; 96 return true;
89 } 97 }
90 98
91 bool Cryptographer::Decrypt(const sync_pb::EncryptedData& encrypted, 99 bool Cryptographer::Decrypt(const sync_pb::EncryptedData& encrypted,
(...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after
133 141
134 bool Cryptographer::AddKey(const KeyParams& params) { 142 bool Cryptographer::AddKey(const KeyParams& params) {
135 // Create the new Nigori and make it the default encryptor. 143 // Create the new Nigori and make it the default encryptor.
136 scoped_ptr<Nigori> nigori(new Nigori); 144 scoped_ptr<Nigori> nigori(new Nigori);
137 if (!nigori->InitByDerivation(params.hostname, 145 if (!nigori->InitByDerivation(params.hostname,
138 params.username, 146 params.username,
139 params.password)) { 147 params.password)) {
140 NOTREACHED(); // Invalid username or password. 148 NOTREACHED(); // Invalid username or password.
141 return false; 149 return false;
142 } 150 }
143 return AddKeyImpl(nigori.Pass()); 151 return AddKeyImpl(nigori.Pass(), true);
152 }
153
154 bool Cryptographer::AddNonDefaultKey(const KeyParams& params) {
155 DCHECK(is_initialized());
156 // Create the new Nigori and add it to the keybag.
157 scoped_ptr<Nigori> nigori(new Nigori);
158 if (!nigori->InitByDerivation(params.hostname,
159 params.username,
160 params.password)) {
161 NOTREACHED(); // Invalid username or password.
162 return false;
163 }
164 return AddKeyImpl(nigori.Pass(), false);
144 } 165 }
145 166
146 bool Cryptographer::AddKeyFromBootstrapToken( 167 bool Cryptographer::AddKeyFromBootstrapToken(
147 const std::string restored_bootstrap_token) { 168 const std::string restored_bootstrap_token) {
148 // Create the new Nigori and make it the default encryptor. 169 // Create the new Nigori and make it the default encryptor.
149 scoped_ptr<Nigori> nigori(UnpackBootstrapToken(restored_bootstrap_token)); 170 scoped_ptr<Nigori> nigori(UnpackBootstrapToken(restored_bootstrap_token));
150 if (!nigori.get()) 171 if (!nigori.get())
151 return false; 172 return false;
152 return AddKeyImpl(nigori.Pass()); 173 return AddKeyImpl(nigori.Pass(), true);
153 } 174 }
154 175
155 bool Cryptographer::AddKeyImpl(scoped_ptr<Nigori> initialized_nigori) { 176 bool Cryptographer::AddKeyImpl(scoped_ptr<Nigori> initialized_nigori,
177 bool set_as_default) {
156 std::string name; 178 std::string name;
157 if (!initialized_nigori->Permute(Nigori::Password, kNigoriKeyName, &name)) { 179 if (!initialized_nigori->Permute(Nigori::Password, kNigoriKeyName, &name)) {
158 NOTREACHED(); 180 NOTREACHED();
159 return false; 181 return false;
160 } 182 }
183
161 nigoris_[name] = make_linked_ptr(initialized_nigori.release()); 184 nigoris_[name] = make_linked_ptr(initialized_nigori.release());
162 default_nigori_name_ = name; 185
186 // Check if the key we just added can decrypt the pending keys and add them
187 // too if so.
188 if (pending_keys_.get() && CanDecrypt(*pending_keys_)) {
189 sync_pb::NigoriKeyBag pending_bag;
190 Decrypt(*pending_keys_, &pending_bag);
191 InstallKeyBag(pending_bag);
192 SetDefaultKey(pending_keys_->key_name());
193 pending_keys_.reset();
194 }
195
196 // The just-added key takes priority over the pending keys as default.
197 if (set_as_default) SetDefaultKey(name);
163 return true; 198 return true;
164 } 199 }
165 200
166 void Cryptographer::InstallKeys(const sync_pb::EncryptedData& encrypted) { 201 void Cryptographer::InstallKeys(const sync_pb::EncryptedData& encrypted) {
167 DCHECK(CanDecrypt(encrypted)); 202 DCHECK(CanDecrypt(encrypted));
168 203
169 sync_pb::NigoriKeyBag bag; 204 sync_pb::NigoriKeyBag bag;
170 if (!Decrypt(encrypted, &bag)) 205 if (!Decrypt(encrypted, &bag))
171 return; 206 return;
172 InstallKeyBag(bag); 207 InstallKeyBag(bag);
(...skipping 127 matching lines...) Expand 10 before | Expand all | Expand 10 after
300 key.encryption_key(), 335 key.encryption_key(),
301 key.mac_key())) { 336 key.mac_key())) {
302 NOTREACHED(); 337 NOTREACHED();
303 continue; 338 continue;
304 } 339 }
305 nigoris_[key.name()] = make_linked_ptr(new_nigori.release()); 340 nigoris_[key.name()] = make_linked_ptr(new_nigori.release());
306 } 341 }
307 } 342 }
308 } 343 }
309 344
345 bool Cryptographer::KeybagIsStale(
346 const sync_pb::EncryptedData& encrypted_bag) const {
347 if (!is_ready())
348 return false;
349 if (encrypted_bag.blob().empty())
350 return true;
351 if (!CanDecrypt(encrypted_bag))
352 return false;
353 if (!CanDecryptUsingDefaultKey(encrypted_bag))
354 return true;
355 sync_pb::NigoriKeyBag bag;
356 if (!Decrypt(encrypted_bag, &bag)) {
357 LOG(ERROR) << "Failed to decrypt keybag for stale check. "
358 << "Assuming keybag is corrupted.";
359 return true;
360 }
361 if (static_cast<size_t>(bag.key_size()) < nigoris_.size())
362 return true;
363 return false;
364 }
365
310 } // namespace syncer 366 } // namespace syncer
OLDNEW
« sync/protocol/nigori_specifics.proto ('K') | « sync/util/cryptographer.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698