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