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

Side by Side Diff: sync/util/cryptographer.cc

Issue 10878015: [Sync] Move keystore key handling to SyncEncryptionHandlerImpl (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Address comments 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
« no previous file with comments | « sync/util/cryptographer.h ('k') | sync/util/cryptographer_unittest.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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/logging.h" 10 #include "base/logging.h"
11 #include "sync/protocol/nigori_specifics.pb.h" 11 #include "sync/protocol/nigori_specifics.pb.h"
12 #include "sync/util/encryptor.h" 12 #include "sync/util/encryptor.h"
13 13
14 namespace syncer { 14 namespace syncer {
15 15
16 const char kNigoriTag[] = "google_chrome_nigori"; 16 const char kNigoriTag[] = "google_chrome_nigori";
17 17
18 // We name a particular Nigori instance (ie. a triplet consisting of a hostname, 18 // 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 19 // a username, and a password) by calling Permute on this string. Since the
20 // output of Permute is always the same for a given triplet, clients will always 20 // output of Permute is always the same for a given triplet, clients will always
21 // assign the same name to a particular triplet. 21 // assign the same name to a particular triplet.
22 const char kNigoriKeyName[] = "nigori-key"; 22 const char kNigoriKeyName[] = "nigori-key";
23 23
24 Cryptographer::Cryptographer(Encryptor* encryptor) 24 Cryptographer::Cryptographer(Encryptor* encryptor)
25 : encryptor_(encryptor), 25 : encryptor_(encryptor) {
26 default_nigori_(NULL),
27 keystore_nigori_(NULL) {
28 DCHECK(encryptor); 26 DCHECK(encryptor);
29 } 27 }
30 28
31 Cryptographer::~Cryptographer() {} 29 Cryptographer::~Cryptographer() {}
32 30
33 31
34 void Cryptographer::Bootstrap(const std::string& restored_bootstrap_token) { 32 void Cryptographer::Bootstrap(const std::string& restored_bootstrap_token) {
35 if (is_initialized()) { 33 if (is_initialized()) {
36 NOTREACHED(); 34 NOTREACHED();
37 return; 35 return;
38 } 36 }
39 37
40 scoped_ptr<Nigori> nigori(UnpackBootstrapToken(restored_bootstrap_token)); 38 scoped_ptr<Nigori> nigori(UnpackBootstrapToken(restored_bootstrap_token));
41 if (nigori.get()) 39 if (nigori.get())
42 AddKeyImpl(nigori.release(), false); 40 AddKeyImpl(nigori.Pass());
43 }
44
45 void Cryptographer::BootstrapKeystoreKey(
46 const std::string& restored_bootstrap_token) {
47 if (keystore_nigori_) {
48 NOTREACHED();
49 return;
50 }
51
52 scoped_ptr<Nigori> nigori(UnpackBootstrapToken(restored_bootstrap_token));
53 if (nigori.get())
54 AddKeyImpl(nigori.release(), true);
55 } 41 }
56 42
57 bool Cryptographer::CanDecrypt(const sync_pb::EncryptedData& data) const { 43 bool Cryptographer::CanDecrypt(const sync_pb::EncryptedData& data) const {
58 return nigoris_.end() != nigoris_.find(data.key_name()); 44 return nigoris_.end() != nigoris_.find(data.key_name());
59 } 45 }
60 46
61 bool Cryptographer::CanDecryptUsingDefaultKey( 47 bool Cryptographer::CanDecryptUsingDefaultKey(
62 const sync_pb::EncryptedData& data) const { 48 const sync_pb::EncryptedData& data) const {
63 return default_nigori_ && (data.key_name() == default_nigori_->first); 49 return default_nigori_.get() && (data.key_name() == default_nigori_name_);
64 } 50 }
65 51
66 bool Cryptographer::Encrypt( 52 bool Cryptographer::Encrypt(
67 const ::google::protobuf::MessageLite& message, 53 const ::google::protobuf::MessageLite& message,
68 sync_pb::EncryptedData* encrypted) const { 54 sync_pb::EncryptedData* encrypted) const {
69 DCHECK(encrypted); 55 DCHECK(encrypted);
70 if (!default_nigori_) { 56 if (!default_nigori_.get()) {
71 LOG(ERROR) << "Cryptographer not ready, failed to encrypt."; 57 LOG(ERROR) << "Cryptographer not ready, failed to encrypt.";
72 return false; 58 return false;
73 } 59 }
60 if (nigoris_.find(default_nigori_name_) == nigoris_.end() ||
akalin 2012/08/29 00:02:50 please decomp the iterator returned from find in a
Nicolas Zea 2012/08/29 19:32:20 Done.
61 default_nigori_.get() !=
akalin 2012/08/29 00:02:50 can you compare linked_ptrs directly? (not sure)
Nicolas Zea 2012/08/29 19:32:20 I'm comparing the pointer to the original object,
62 nigoris_.find(default_nigori_name_)->second.get()) {
63 LOG(ERROR) << "Corrupt default key.";
akalin 2012/08/29 00:02:50 wait a minute -- since this isn't a DCHECK anymore
Nicolas Zea 2012/08/29 19:32:20 Yeah, I suppose at this point I may as well go all
64 return false;
65 }
74 66
75 std::string serialized; 67 std::string serialized;
76 if (!message.SerializeToString(&serialized)) { 68 if (!message.SerializeToString(&serialized)) {
77 LOG(ERROR) << "Message is invalid/missing a required field."; 69 LOG(ERROR) << "Message is invalid/missing a required field.";
78 return false; 70 return false;
79 } 71 }
80 72
81 if (CanDecryptUsingDefaultKey(*encrypted)) { 73 if (CanDecryptUsingDefaultKey(*encrypted)) {
82 const std::string& original_serialized = DecryptToString(*encrypted); 74 const std::string& original_serialized = DecryptToString(*encrypted);
83 if (original_serialized == serialized) { 75 if (original_serialized == serialized) {
84 DVLOG(2) << "Re-encryption unnecessary, encrypted data already matches."; 76 DVLOG(2) << "Re-encryption unnecessary, encrypted data already matches.";
85 return true; 77 return true;
86 } 78 }
87 } 79 }
88 80
89 encrypted->set_key_name(default_nigori_->first); 81 encrypted->set_key_name(default_nigori_name_);
90 if (!default_nigori_->second->Encrypt(serialized, 82 if (!default_nigori_->Encrypt(serialized,
91 encrypted->mutable_blob())) { 83 encrypted->mutable_blob())) {
92 LOG(ERROR) << "Failed to encrypt data."; 84 LOG(ERROR) << "Failed to encrypt data.";
93 return false; 85 return false;
94 } 86 }
95 return true; 87 return true;
96 } 88 }
97 89
98 bool Cryptographer::Decrypt(const sync_pb::EncryptedData& encrypted, 90 bool Cryptographer::Decrypt(const sync_pb::EncryptedData& encrypted,
99 ::google::protobuf::MessageLite* message) const { 91 ::google::protobuf::MessageLite* message) const {
100 DCHECK(message); 92 DCHECK(message);
101 std::string plaintext = DecryptToString(encrypted); 93 std::string plaintext = DecryptToString(encrypted);
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after
140 132
141 bool Cryptographer::AddKey(const KeyParams& params) { 133 bool Cryptographer::AddKey(const KeyParams& params) {
142 // Create the new Nigori and make it the default encryptor. 134 // Create the new Nigori and make it the default encryptor.
143 scoped_ptr<Nigori> nigori(new Nigori); 135 scoped_ptr<Nigori> nigori(new Nigori);
144 if (!nigori->InitByDerivation(params.hostname, 136 if (!nigori->InitByDerivation(params.hostname,
145 params.username, 137 params.username,
146 params.password)) { 138 params.password)) {
147 NOTREACHED(); // Invalid username or password. 139 NOTREACHED(); // Invalid username or password.
148 return false; 140 return false;
149 } 141 }
150 return AddKeyImpl(nigori.release(), false); 142 return AddKeyImpl(nigori.Pass());
151 } 143 }
152 144
153 bool Cryptographer::AddKeyFromBootstrapToken( 145 bool Cryptographer::AddKeyFromBootstrapToken(
154 const std::string restored_bootstrap_token) { 146 const std::string restored_bootstrap_token) {
155 // Create the new Nigori and make it the default encryptor. 147 // Create the new Nigori and make it the default encryptor.
156 scoped_ptr<Nigori> nigori(UnpackBootstrapToken(restored_bootstrap_token)); 148 scoped_ptr<Nigori> nigori(UnpackBootstrapToken(restored_bootstrap_token));
157 if (!nigori.get()) 149 if (!nigori.get())
158 return false; 150 return false;
159 return AddKeyImpl(nigori.release(), false); 151 return AddKeyImpl(nigori.Pass());
160 } 152 }
161 153
162 bool Cryptographer::AddKeyImpl(Nigori* initialized_nigori, 154 bool Cryptographer::AddKeyImpl(scoped_ptr<Nigori> initialized_nigori) {
163 bool is_keystore_key) {
164 scoped_ptr<Nigori> nigori(initialized_nigori);
165 std::string name; 155 std::string name;
166 if (!nigori->Permute(Nigori::Password, kNigoriKeyName, &name)) { 156 if (!initialized_nigori->Permute(Nigori::Password, kNigoriKeyName, &name)) {
167 NOTREACHED(); 157 NOTREACHED();
168 return false; 158 return false;
169 } 159 }
170 nigoris_[name] = make_linked_ptr(nigori.release()); 160 default_nigori_ = make_linked_ptr(initialized_nigori.release());
171 if (is_keystore_key) 161 nigoris_[name] = default_nigori_;
172 keystore_nigori_ = &*nigoris_.find(name); 162 default_nigori_name_ = name;
173 else
174 default_nigori_ = &*nigoris_.find(name);
175 return true; 163 return true;
176 } 164 }
177 165
178 void Cryptographer::InstallKeys(const sync_pb::EncryptedData& encrypted) { 166 void Cryptographer::InstallKeys(const sync_pb::EncryptedData& encrypted) {
179 DCHECK(CanDecrypt(encrypted)); 167 DCHECK(CanDecrypt(encrypted));
180 168
181 sync_pb::NigoriKeyBag bag; 169 sync_pb::NigoriKeyBag bag;
182 if (!Decrypt(encrypted, &bag)) 170 if (!Decrypt(encrypted, &bag))
183 return; 171 return;
184 InstallKeyBag(bag); 172 InstallKeyBag(bag);
185 } 173 }
186 174
187 void Cryptographer::SetDefaultKey(const std::string& key_name) { 175 void Cryptographer::SetDefaultKey(const std::string& key_name) {
188 DCHECK(nigoris_.end() != nigoris_.find(key_name)); 176 DCHECK(nigoris_.end() != nigoris_.find(key_name));
189 default_nigori_ = &*nigoris_.find(key_name); 177 default_nigori_ = nigoris_.find(key_name)->second;
178 default_nigori_name_ = key_name;
190 } 179 }
191 180
192 void Cryptographer::SetPendingKeys(const sync_pb::EncryptedData& encrypted) { 181 void Cryptographer::SetPendingKeys(const sync_pb::EncryptedData& encrypted) {
193 DCHECK(!CanDecrypt(encrypted)); 182 DCHECK(!CanDecrypt(encrypted));
194 DCHECK(!encrypted.blob().empty()); 183 DCHECK(!encrypted.blob().empty());
195 pending_keys_.reset(new sync_pb::EncryptedData(encrypted)); 184 pending_keys_.reset(new sync_pb::EncryptedData(encrypted));
196 } 185 }
197 186
198 const sync_pb::EncryptedData& Cryptographer::GetPendingKeys() const { 187 const sync_pb::EncryptedData& Cryptographer::GetPendingKeys() const {
199 DCHECK(has_pending_keys()); 188 DCHECK(has_pending_keys());
(...skipping 13 matching lines...) Expand all
213 if (!nigori.Decrypt(pending_keys_->blob(), &plaintext)) 202 if (!nigori.Decrypt(pending_keys_->blob(), &plaintext))
214 return false; 203 return false;
215 204
216 sync_pb::NigoriKeyBag bag; 205 sync_pb::NigoriKeyBag bag;
217 if (!bag.ParseFromString(plaintext)) { 206 if (!bag.ParseFromString(plaintext)) {
218 NOTREACHED(); 207 NOTREACHED();
219 return false; 208 return false;
220 } 209 }
221 InstallKeyBag(bag); 210 InstallKeyBag(bag);
222 const std::string& new_default_key_name = pending_keys_->key_name(); 211 const std::string& new_default_key_name = pending_keys_->key_name();
223 DCHECK(nigoris_.end() != nigoris_.find(new_default_key_name)); 212 SetDefaultKey(new_default_key_name);
224 default_nigori_ = &*nigoris_.find(new_default_key_name);
225 pending_keys_.reset(); 213 pending_keys_.reset();
226 return true; 214 return true;
227 } 215 }
228 216
229 bool Cryptographer::GetBootstrapToken(std::string* token) const { 217 bool Cryptographer::GetBootstrapToken(std::string* token) const {
230 DCHECK(token); 218 DCHECK(token);
231 if (!is_initialized()) 219 if (!is_initialized())
232 return false; 220 return false;
233 221
234 return PackBootstrapToken(default_nigori_->second.get(), token); 222 return PackBootstrapToken(default_nigori_.get(), token);
235 }
236
237 bool Cryptographer::GetKeystoreKeyBootstrapToken(
238 std::string* token) const {
239 DCHECK(token);
240 if (!HasKeystoreKey())
241 return false;
242
243 return PackBootstrapToken(keystore_nigori_->second.get(), token);
244 } 223 }
245 224
246 bool Cryptographer::PackBootstrapToken(const Nigori* nigori, 225 bool Cryptographer::PackBootstrapToken(const Nigori* nigori,
247 std::string* pack_into) const { 226 std::string* pack_into) const {
248 DCHECK(pack_into); 227 DCHECK(pack_into);
249 DCHECK(nigori); 228 DCHECK(nigori);
250 229
251 sync_pb::NigoriKey key; 230 sync_pb::NigoriKey key;
252 if (!nigori->ExportKeys(key.mutable_user_key(), 231 if (!nigori->ExportKeys(key.mutable_user_key(),
253 key.mutable_encryption_key(), 232 key.mutable_encryption_key(),
(...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after
300 scoped_ptr<Nigori> nigori(new Nigori); 279 scoped_ptr<Nigori> nigori(new Nigori);
301 if (!nigori->InitByImport(key.user_key(), key.encryption_key(), 280 if (!nigori->InitByImport(key.user_key(), key.encryption_key(),
302 key.mac_key())) { 281 key.mac_key())) {
303 NOTREACHED(); 282 NOTREACHED();
304 return NULL; 283 return NULL;
305 } 284 }
306 285
307 return nigori.release(); 286 return nigori.release();
308 } 287 }
309 288
310 bool Cryptographer::SetKeystoreKey(const std::string& keystore_key) {
311 if (keystore_key.empty())
312 return false;
313 KeyParams params = {"localhost", "dummy", keystore_key};
314
315 // Create the new Nigori and make it the default keystore encryptor.
316 scoped_ptr<Nigori> nigori(new Nigori);
317 if (!nigori->InitByDerivation(params.hostname,
318 params.username,
319 params.password)) {
320 NOTREACHED(); // Invalid username or password.
321 return false;
322 }
323
324 return AddKeyImpl(nigori.release(), true);
325 }
326
327 bool Cryptographer::HasKeystoreKey() const {
328 return keystore_nigori_ != NULL;
329 }
330
331 void Cryptographer::InstallKeyBag(const sync_pb::NigoriKeyBag& bag) { 289 void Cryptographer::InstallKeyBag(const sync_pb::NigoriKeyBag& bag) {
332 int key_size = bag.key_size(); 290 int key_size = bag.key_size();
333 for (int i = 0; i < key_size; ++i) { 291 for (int i = 0; i < key_size; ++i) {
334 const sync_pb::NigoriKey key = bag.key(i); 292 const sync_pb::NigoriKey key = bag.key(i);
335 // Only use this key if we don't already know about it. 293 // Only use this key if we don't already know about it.
336 if (nigoris_.end() == nigoris_.find(key.name())) { 294 if (nigoris_.end() == nigoris_.find(key.name())) {
337 scoped_ptr<Nigori> new_nigori(new Nigori); 295 scoped_ptr<Nigori> new_nigori(new Nigori);
338 if (!new_nigori->InitByImport(key.user_key(), 296 if (!new_nigori->InitByImport(key.user_key(),
339 key.encryption_key(), 297 key.encryption_key(),
340 key.mac_key())) { 298 key.mac_key())) {
341 NOTREACHED(); 299 NOTREACHED();
342 continue; 300 continue;
343 } 301 }
344 nigoris_[key.name()] = make_linked_ptr(new_nigori.release()); 302 nigoris_[key.name()] = make_linked_ptr(new_nigori.release());
345 } 303 }
346 } 304 }
347 } 305 }
348 306
349 } // namespace syncer 307 } // namespace syncer
OLDNEW
« no previous file with comments | « sync/util/cryptographer.h ('k') | sync/util/cryptographer_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698