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

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

Issue 10827266: [Sync] Add SyncEncryptionHandler (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Address comments 2 Created 8 years, 4 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | 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 #ifndef SYNC_UTIL_CRYPTOGRAPHER_H_ 5 #ifndef SYNC_UTIL_CRYPTOGRAPHER_H_
6 #define SYNC_UTIL_CRYPTOGRAPHER_H_ 6 #define SYNC_UTIL_CRYPTOGRAPHER_H_
7 7
8 #include <map> 8 #include <map>
9 #include <string> 9 #include <string>
10 10
11 #include "base/gtest_prod_util.h" 11 #include "base/gtest_prod_util.h"
12 #include "base/memory/linked_ptr.h" 12 #include "base/memory/linked_ptr.h"
13 #include "base/memory/scoped_ptr.h" 13 #include "base/memory/scoped_ptr.h"
14 #include "base/observer_list.h"
15 #include "sync/internal_api/public/base/model_type.h" 14 #include "sync/internal_api/public/base/model_type.h"
16 #include "sync/protocol/encryption.pb.h" 15 #include "sync/protocol/encryption.pb.h"
17 #include "sync/protocol/nigori_specifics.pb.h"
18 #include "sync/util/nigori.h" 16 #include "sync/util/nigori.h"
19 17
18 namespace sync_pb {
19 class NigoriKeyBag;
20 class NigoriSpecifics;
21 }
22
20 namespace syncer { 23 namespace syncer {
21 24
22 class Encryptor; 25 class Encryptor;
23 26
27 namespace syncable {
28 class BaseTransaction;
29 class NigoriHandler;
30 }
31
24 extern const char kNigoriTag[]; 32 extern const char kNigoriTag[];
25 33
26 // The parameters used to initialize a Nigori instance. 34 // The parameters used to initialize a Nigori instance.
27 struct KeyParams { 35 struct KeyParams {
28 std::string hostname; 36 std::string hostname;
29 std::string username; 37 std::string username;
30 std::string password; 38 std::string password;
31 }; 39 };
32 40
33 // This class manages the Nigori objects used to encrypt and decrypt sensitive 41 // This class manages the Nigori objects used to encrypt and decrypt sensitive
34 // sync data (eg. passwords). Each Nigori object knows how to handle data 42 // sync data (eg. passwords). Each Nigori object knows how to handle data
35 // protected with a particular passphrase. 43 // protected with a particular passphrase.
36 // 44 //
37 // Whenever an update to the Nigori sync node is received from the server, 45 // Whenever an update to the Nigori sync node is received from the server,
38 // SetPendingKeys should be called with the encrypted contents of that node. 46 // SetPendingKeys should be called with the encrypted contents of that node.
39 // Most likely, an updated Nigori node means that a new passphrase has been set 47 // Most likely, an updated Nigori node means that a new passphrase has been set
40 // and that future node updates won't be decryptable. To remedy this, the user 48 // and that future node updates won't be decryptable. To remedy this, the user
41 // should be prompted for the new passphrase and DecryptPendingKeys be called. 49 // should be prompted for the new passphrase and DecryptPendingKeys be called.
42 // 50 //
43 // Whenever a update to an encrypted node is received from the server, 51 // Whenever a update to an encrypted node is received from the server,
44 // CanDecrypt should be used to verify whether the Cryptographer can decrypt 52 // CanDecrypt should be used to verify whether the Cryptographer can decrypt
45 // that node. If it cannot, then the application of that update should be 53 // that node. If it cannot, then the application of that update should be
46 // delayed until after it can be decrypted. 54 // delayed until after it can be decrypted.
47 class Cryptographer { 55 class Cryptographer {
48 public: 56 public:
49 // All Observer methods are done synchronously, so they're called
50 // under a transaction (since all Cryptographer operations are done
51 // under a transaction).
52 class Observer {
53 public:
54 // Called when the set of encrypted types or the encrypt
55 // everything flag has been changed. Note that this doesn't
56 // necessarily mean that encryption has completed for the given
57 // types.
58 //
59 // |encrypted_types| will always be a superset of
60 // SensitiveTypes(). If |encrypt_everything| is true,
61 // |encrypted_types| will be the set of all known types.
62 //
63 // Until this function is called, observers can assume that the
64 // set of encrypted types is SensitiveTypes() and that the encrypt
65 // everything flag is false.
66 virtual void OnEncryptedTypesChanged(
67 ModelTypeSet encrypted_types,
68 bool encrypt_everything) = 0;
69
70 protected:
71 virtual ~Observer();
72 };
73
74 // Does not take ownership of |encryptor|. 57 // Does not take ownership of |encryptor|.
75 explicit Cryptographer(Encryptor* encryptor); 58 explicit Cryptographer(Encryptor* encryptor);
76 ~Cryptographer(); 59 ~Cryptographer();
77 60
78 // When update on cryptographer is called this enum tells if the 61 // Set the sync nigori node handler.
79 // cryptographer was succesfully able to update using the nigori node or if 62 // TODO(zea): refactor so that Cryptographer doesn't need any connection
80 // it needs a key to decrypt the nigori node. 63 // to a NigoriHandler.
tim (not reviewing) 2012/08/15 00:23:30 This one could probably use a bug to track.
Nicolas Zea 2012/08/15 01:08:29 Done.
81 enum UpdateResult { 64 void SetNigoriHandler(syncable::NigoriHandler* delegate);
82 SUCCESS,
83 NEEDS_PASSPHRASE
84 };
85 65
86 // Manage observers. 66 // NigoriHandler delegator methods (passes through to delegate).
87 void AddObserver(Observer* observer); 67 void ApplyNigoriUpdate(const sync_pb::NigoriSpecifics& nigori,
88 void RemoveObserver(Observer* observer); 68 syncable::BaseTransaction* const trans);
69 void UpdateNigoriFromEncryptedTypes(
70 sync_pb::NigoriSpecifics* nigori,
71 syncable::BaseTransaction* const trans) const;
72 ModelTypeSet GetEncryptedTypes() const;
89 73
90 // |restored_bootstrap_token| can be provided via this method to bootstrap 74 // |restored_bootstrap_token| can be provided via this method to bootstrap
91 // Cryptographer instance into the ready state (is_ready will be true). 75 // Cryptographer instance into the ready state (is_ready will be true).
92 // It must be a string that was previously built by the 76 // It must be a string that was previously built by the
93 // GetSerializedBootstrapToken function. It is possible that the token is no 77 // GetSerializedBootstrapToken function. It is possible that the token is no
94 // longer valid (due to server key change), in which case the normal 78 // longer valid (due to server key change), in which case the normal
95 // decryption code paths will fail and the user will need to provide a new 79 // decryption code paths will fail and the user will need to provide a new
96 // passphrase. 80 // passphrase.
97 // It is an error to call this if is_ready() == true, though it is fair to 81 // It is an error to call this if is_ready() == true, though it is fair to
98 // never call Bootstrap at all. 82 // never call Bootstrap at all.
(...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after
135 // Creates a new Nigori instance using |params|. If successful, |params| will 119 // Creates a new Nigori instance using |params|. If successful, |params| will
136 // become the default encryption key and be used for all future calls to 120 // become the default encryption key and be used for all future calls to
137 // Encrypt. 121 // Encrypt.
138 bool AddKey(const KeyParams& params); 122 bool AddKey(const KeyParams& params);
139 123
140 // Same as AddKey(..), but builds the new Nigori from a previously persisted 124 // Same as AddKey(..), but builds the new Nigori from a previously persisted
141 // bootstrap token. This can be useful when consuming a bootstrap token 125 // bootstrap token. This can be useful when consuming a bootstrap token
142 // with a cryptographer that has already been initialized. 126 // with a cryptographer that has already been initialized.
143 bool AddKeyFromBootstrapToken(const std::string restored_bootstrap_token); 127 bool AddKeyFromBootstrapToken(const std::string restored_bootstrap_token);
144 128
129 // Decrypts |encrypted| and uses its contents to initialize Nigori instances.
130 // Returns true unless decryption of |encrypted| fails. The caller is
131 // responsible for checking that CanDecrypt(encrypted) == true.
132 // Does not update the default nigori.
133 void InstallKeys(const sync_pb::EncryptedData& encrypted);
134
135
145 // Makes a local copy of |encrypted| to later be decrypted by 136 // Makes a local copy of |encrypted| to later be decrypted by
146 // DecryptPendingKeys. This should only be used if CanDecrypt(encrypted) == 137 // DecryptPendingKeys. This should only be used if CanDecrypt(encrypted) ==
147 // false. 138 // false.
148 void SetPendingKeys(const sync_pb::EncryptedData& encrypted); 139 void SetPendingKeys(const sync_pb::EncryptedData& encrypted);
149 140
150 // Makes |pending_keys_| available to callers that may want to cache its 141 // Makes |pending_keys_| available to callers that may want to cache its
151 // value for later use on the UI thread. It is illegal to call this if the 142 // value for later use on the UI thread. It is illegal to call this if the
152 // cryptographer has no pending keys. Like other calls that access the 143 // cryptographer has no pending keys. Like other calls that access the
153 // cryptographer, this method must be called from within a transaction. 144 // cryptographer, this method must be called from within a transaction.
154 const sync_pb::EncryptedData& GetPendingKeys() const; 145 const sync_pb::EncryptedData& GetPendingKeys() const;
155 146
156 // Attempts to decrypt the set of keys that was copied in the previous call to 147 // Attempts to decrypt the set of keys that was copied in the previous call to
157 // SetPendingKeys using |params|. Returns true if the pending keys were 148 // SetPendingKeys using |params|. Returns true if the pending keys were
158 // successfully decrypted and installed. If successful, the default key 149 // successfully decrypted and installed. If successful, the default key
159 // is updated. 150 // is updated.
160 bool DecryptPendingKeys(const KeyParams& params); 151 bool DecryptPendingKeys(const KeyParams& params);
161 152
153 // Sets the default key to the nigori with name |key_name|. |key_name| must
154 // correspond to a nigori that has already been installed into the keybag.
155 void SetDefaultKey(const std::string& key_name);
156
162 bool is_initialized() const { return !nigoris_.empty() && default_nigori_; } 157 bool is_initialized() const { return !nigoris_.empty() && default_nigori_; }
163 158
164 // Returns whether this Cryptographer is ready to encrypt and decrypt data. 159 // Returns whether this Cryptographer is ready to encrypt and decrypt data.
165 bool is_ready() const { return is_initialized() && 160 bool is_ready() const { return is_initialized() &&
166 has_pending_keys() == false; } 161 has_pending_keys() == false; }
167 162
168 // Returns whether there is a pending set of keys that needs to be decrypted. 163 // Returns whether there is a pending set of keys that needs to be decrypted.
169 bool has_pending_keys() const { return NULL != pending_keys_.get(); } 164 bool has_pending_keys() const { return NULL != pending_keys_.get(); }
170 165
171 // Obtain a token that can be provided on construction to a future 166 // Obtain a token that can be provided on construction to a future
172 // Cryptographer instance to bootstrap itself. Returns false if such a token 167 // Cryptographer instance to bootstrap itself. Returns false if such a token
173 // can't be created (i.e. if this Cryptograhper doesn't have valid keys). 168 // can't be created (i.e. if this Cryptograhper doesn't have valid keys).
174 bool GetBootstrapToken(std::string* token) const; 169 bool GetBootstrapToken(std::string* token) const;
175 170
176 // Obtain the bootstrap token based on the keystore encryption key. 171 // Obtain the bootstrap token based on the keystore encryption key.
177 bool GetKeystoreKeyBootstrapToken(std::string* token) const; 172 bool GetKeystoreKeyBootstrapToken(std::string* token) const;
178 173
179 // Update the cryptographer based on the contents of the nigori specifics.
180 // This updates both the encryption keys and the set of encrypted types.
181 // Returns NEEDS_PASSPHRASE if was unable to decrypt the pending keys,
182 // SUCCESS otherwise.
183 // Note: will not change the default key. If the nigori's keybag
184 // is decryptable, all keys are added to the local keybag and the current
185 // default is preserved. If the nigori's keybag is not decryptable, it is
186 // stored in the |pending_keys_|.
187 UpdateResult Update(const sync_pb::NigoriSpecifics& nigori);
188
189 // Set the keystore-derived nigori from the provided key. 174 // Set the keystore-derived nigori from the provided key.
190 // Returns true if we succesfully create the keystore derived nigori from the 175 // Returns true if we succesfully create the keystore derived nigori from the
191 // provided key, false otherwise. 176 // provided key, false otherwise.
192 bool SetKeystoreKey(const std::string& keystore_key); 177 bool SetKeystoreKey(const std::string& keystore_key);
193 178
194 // Returns true if we currently have a keystore-derived nigori, false 179 // Returns true if we currently have a keystore-derived nigori, false
195 // otherwise. 180 // otherwise.
196 bool HasKeystoreKey() const; 181 bool HasKeystoreKey() const;
197 182
198 // The set of types that are always encrypted. 183 Encryptor* encryptor() const { return encryptor_; }
199 static ModelTypeSet SensitiveTypes();
200
201 // Reset our set of encrypted types based on the contents of the nigori
202 // specifics.
203 void UpdateEncryptedTypesFromNigori(const sync_pb::NigoriSpecifics& nigori);
204
205 // Update the nigori to reflect the current set of encrypted types.
206 void UpdateNigoriFromEncryptedTypes(sync_pb::NigoriSpecifics* nigori) const;
207
208 // Setter/getter for whether all current and future datatypes should
209 // be encrypted. Once set you cannot unset without reading from a
210 // new nigori node. set_encrypt_everything() emits a notification
211 // the first time it's called.
212 void set_encrypt_everything();
213 bool encrypt_everything() const;
214
215 // Return the set of encrypted types.
216 ModelTypeSet GetEncryptedTypes() const;
217
218 // Forwards to MergeEncryptedTypes.
219 void MergeEncryptedTypesForTest(ModelTypeSet encrypted_types);
220 184
221 private: 185 private:
222 FRIEND_TEST_ALL_PREFIXES(SyncCryptographerTest, PackUnpack); 186 FRIEND_TEST_ALL_PREFIXES(SyncCryptographerTest, PackUnpack);
187
223 typedef std::map<std::string, linked_ptr<const Nigori> > NigoriMap; 188 typedef std::map<std::string, linked_ptr<const Nigori> > NigoriMap;
224 189
225 // Merges the given set of encrypted types with the existing set and emits a
226 // notification if necessary.
227 void MergeEncryptedTypes(ModelTypeSet encrypted_types);
228
229 void EmitEncryptedTypesChangedNotification();
230
231 // Decrypts |encrypted| and uses its contents to initialize Nigori instances.
232 // Returns true unless decryption of |encrypted| fails. The caller is
233 // responsible for checking that CanDecrypt(encrypted) == true.
234 // Does not update the default nigori.
235 void InstallKeys(const sync_pb::EncryptedData& encrypted);
236
237 // Helper method to instantiate Nigori instances for each set of key 190 // Helper method to instantiate Nigori instances for each set of key
238 // parameters in |bag|. 191 // parameters in |bag|.
239 // Does not update the default nigori. 192 // Does not update the default nigori.
240 void InstallKeyBag(const sync_pb::NigoriKeyBag& bag); 193 void InstallKeyBag(const sync_pb::NigoriKeyBag& bag);
241 194
242 // Helper method to add a nigori as either the new default nigori or the new 195 // Helper method to add a nigori as either the new default nigori or the new
243 // keystore nigori. 196 // keystore nigori.
244 bool AddKeyImpl(Nigori* nigori, bool is_keystore_key); 197 bool AddKeyImpl(Nigori* nigori, bool is_keystore_key);
245 198
246 // Functions to serialize + encrypt a Nigori object in an opaque format for 199 // Functions to serialize + encrypt a Nigori object in an opaque format for
247 // persistence by sync infrastructure. 200 // persistence by sync infrastructure.
248 bool PackBootstrapToken(const Nigori* nigori, std::string* pack_into) const; 201 bool PackBootstrapToken(const Nigori* nigori, std::string* pack_into) const;
249 Nigori* UnpackBootstrapToken(const std::string& token) const; 202 Nigori* UnpackBootstrapToken(const std::string& token) const;
250 203
251 Encryptor* const encryptor_; 204 Encryptor* const encryptor_;
252 205
253 ObserverList<Observer> observers_;
254
255 NigoriMap nigoris_; // The Nigoris we know about, mapped by key name. 206 NigoriMap nigoris_; // The Nigoris we know about, mapped by key name.
256 NigoriMap::value_type* default_nigori_; // The Nigori used for encryption. 207 NigoriMap::value_type* default_nigori_; // The Nigori used for encryption.
257 NigoriMap::value_type* keystore_nigori_; // Nigori generated from keystore. 208 NigoriMap::value_type* keystore_nigori_; // Nigori generated from keystore.
258 209
259 scoped_ptr<sync_pb::EncryptedData> pending_keys_; 210 scoped_ptr<sync_pb::EncryptedData> pending_keys_;
260 211
261 ModelTypeSet encrypted_types_; 212 // The sync nigori node handler. Necessary until we decouple the encrypted
262 bool encrypt_everything_; 213 // types from the cryptographer.
214 syncable::NigoriHandler* nigori_node_handler_;
263 215
264 DISALLOW_COPY_AND_ASSIGN(Cryptographer); 216 DISALLOW_COPY_AND_ASSIGN(Cryptographer);
265 }; 217 };
266 218
267 } // namespace syncer 219 } // namespace syncer
268 220
269 #endif // SYNC_UTIL_CRYPTOGRAPHER_H_ 221 #endif // SYNC_UTIL_CRYPTOGRAPHER_H_
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698