1ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen// Copyright (c) 2011 The Chromium Authors. All rights reserved.
2c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// Use of this source code is governed by a BSD-style license that can be
3c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// found in the LICENSE file.
4c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
5c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#ifndef CHROME_BROWSER_SYNC_UTIL_CRYPTOGRAPHER_H_
6c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#define CHROME_BROWSER_SYNC_UTIL_CRYPTOGRAPHER_H_
73345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick#pragma once
8c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
9c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include <map>
10c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include <string>
11c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
123345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick#include "base/gtest_prod_util.h"
13ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen#include "base/memory/linked_ptr.h"
14ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen#include "base/memory/scoped_ptr.h"
15c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "chrome/browser/sync/protocol/nigori_specifics.pb.h"
16c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "chrome/browser/sync/util/nigori.h"
17c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
18c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochnamespace browser_sync {
19c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
20c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochextern const char kNigoriTag[];
21c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
22c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// The parameters used to initialize a Nigori instance.
23c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochstruct KeyParams {
24c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  std::string hostname;
25c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  std::string username;
26c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  std::string password;
27c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch};
28c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
29c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// This class manages the Nigori objects used to encrypt and decrypt sensitive
30c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// sync data (eg. passwords). Each Nigori object knows how to handle data
31c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// protected with a particular passphrase.
32c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch//
33c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// Whenever an update to the Nigori sync node is received from the server,
34c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// SetPendingKeys should be called with the encrypted contents of that node.
35c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// Most likely, an updated Nigori node means that a new passphrase has been set
36c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// and that future node updates won't be decryptable. To remedy this, the user
37c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// should be prompted for the new passphrase and DecryptPendingKeys be called.
38c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch//
39c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// Whenever a update to an encrypted node is received from the server,
40c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// CanDecrypt should be used to verify whether the Cryptographer can decrypt
41c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// that node. If it cannot, then the application of that update should be
42c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// delayed until after it can be decrypted.
43c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochclass Cryptographer {
44c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch public:
45c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  Cryptographer();
46731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  ~Cryptographer();
47c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
483345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  // |restored_bootstrap_token| can be provided via this method to bootstrap
493345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  // Cryptographer instance into the ready state (is_ready will be true).
503345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  // It must be a string that was previously built by the
513345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  // GetSerializedBootstrapToken function.  It is possible that the token is no
523345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  // longer valid (due to server key change), in which case the normal
533345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  // decryption code paths will fail and the user will need to provide a new
543345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  // passphrase.
553345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  // It is an error to call this if is_ready() == true, though it is fair to
563345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  // never call Bootstrap at all.
573345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  void Bootstrap(const std::string& restored_bootstrap_token);
583345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
59c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // Returns whether we can decrypt |encrypted| using the keys we currently know
60c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // about.
61c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  bool CanDecrypt(const sync_pb::EncryptedData& encrypted) const;
62c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
63ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  // Returns whether |encrypted| can be decrypted using the default encryption
64ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  // key.
65ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  bool CanDecryptUsingDefaultKey(const sync_pb::EncryptedData& encrypted) const;
66ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
67c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // Encrypts |message| into |encrypted|. Returns true unless encryption fails.
68c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // Note that encryption will fail if |message| isn't valid (eg. a required
69c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // field isn't set).
70c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  bool Encrypt(const ::google::protobuf::MessageLite& message,
71c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch               sync_pb::EncryptedData* encrypted) const;
72c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
73c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // Decrypts |encrypted| into |message|. Returns true unless decryption fails,
74c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // or |message| fails to parse the decrypted data.
75c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  bool Decrypt(const sync_pb::EncryptedData& encrypted,
76c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch               ::google::protobuf::MessageLite* message) const;
77c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
78dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  // Decrypts |encrypted| and returns plaintext decrypted data. If decryption
79dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  // fails, returns empty string.
80dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  std::string DecryptToString(const sync_pb::EncryptedData& encrypted) const;
81dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen
82c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // Encrypts the set of currently known keys into |encrypted|. Returns true if
83c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // successful.
84c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  bool GetKeys(sync_pb::EncryptedData* encrypted) const;
85c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
86c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // Creates a new Nigori instance using |params|. If successful, |params| will
87c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // become the default encryption key and be used for all future calls to
88c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // Encrypt.
89c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  bool AddKey(const KeyParams& params);
90c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
91c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // Decrypts |encrypted| and uses its contents to initialize Nigori instances.
92c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // Returns true unless decryption of |encrypted| fails. The caller is
93c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // responsible for checking that CanDecrypt(encrypted) == true.
94c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  bool SetKeys(const sync_pb::EncryptedData& encrypted);
95c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
96c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // Makes a local copy of |encrypted| to later be decrypted by
97c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // DecryptPendingKeys. This should only be used if CanDecrypt(encrypted) ==
98c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // false.
99c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  void SetPendingKeys(const sync_pb::EncryptedData& encrypted);
100c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
101ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  // Attempts to decrypt the set of keys that was copied in the previous call to
102c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // SetPendingKeys using |params|. Returns true if the pending keys were
103c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // successfully decrypted and installed.
104c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  bool DecryptPendingKeys(const KeyParams& params);
105c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
106c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // Returns whether this Cryptographer is ready to encrypt and decrypt data.
107c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  bool is_ready() const { return !nigoris_.empty() && default_nigori_; }
108c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
109c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // Returns whether there is a pending set of keys that needs to be decrypted.
110c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  bool has_pending_keys() const { return NULL != pending_keys_.get(); }
111c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
1123345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  // Obtain a token that can be provided on construction to a future
1133345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  // Cryptographer instance to bootstrap itself.  Returns false if such a token
1143345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  // can't be created (i.e. if this Cryptograhper doesn't have valid keys).
1153345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  bool GetBootstrapToken(std::string* token) const;
1163345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
117c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch private:
1183345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  FRIEND_TEST_ALL_PREFIXES(CryptographerTest, PackUnpack);
119c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  typedef std::map<std::string, linked_ptr<const Nigori> > NigoriMap;
120c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
1213345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  // Helper method to instantiate Nigori instances for each set of key
122c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // parameters in |bag| and setting the default encryption key to
123c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // |default_key_name|.
124c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  void InstallKeys(const std::string& default_key_name,
125c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                   const sync_pb::NigoriKeyBag& bag);
126c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
1273345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  bool AddKeyImpl(Nigori* nigori);
1283345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
1293345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  // Functions to serialize + encrypt a Nigori object in an opaque format for
1303345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  // persistence by sync infrastructure.
1313345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  bool PackBootstrapToken(const Nigori* nigori, std::string* pack_into) const;
1323345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  Nigori* UnpackBootstrapToken(const std::string& token) const;
1333345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
134c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  NigoriMap nigoris_;  // The Nigoris we know about, mapped by key name.
135c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  NigoriMap::value_type* default_nigori_;  // The Nigori used for encryption.
136c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
137c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  scoped_ptr<sync_pb::EncryptedData> pending_keys_;
138c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
139c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  DISALLOW_COPY_AND_ASSIGN(Cryptographer);
140c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch};
141c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
142c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}  // namespace browser_sync
143c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
144c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#endif  // CHROME_BROWSER_SYNC_UTIL_CRYPTOGRAPHER_H_
145