// Copyright 2012 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. #ifndef SYNC_INTERNAL_API_PUBLIC_SYNC_ENCRYPTION_HANDLER_H_ #define SYNC_INTERNAL_API_PUBLIC_SYNC_ENCRYPTION_HANDLER_H_ #include #include "base/time/time.h" #include "sync/base/sync_export.h" #include "sync/internal_api/public/base/model_type.h" namespace sync_pb { class EncryptedData; } namespace syncer { class Cryptographer; // Reasons due to which Cryptographer might require a passphrase. enum PassphraseRequiredReason { REASON_PASSPHRASE_NOT_REQUIRED = 0, // Initial value. REASON_ENCRYPTION = 1, // The cryptographer requires a // passphrase for its first attempt at // encryption. Happens only during // migration or upgrade. REASON_DECRYPTION = 2, // The cryptographer requires a // passphrase for its first attempt at // decryption. }; // The different states for the encryption passphrase. These control if and how // the user should be prompted for a decryption passphrase. // Do not re-order or delete these entries; they are used in a UMA histogram. // Please edit SyncPassphraseType in histograms.xml if a value is added. enum PassphraseType { IMPLICIT_PASSPHRASE = 0, // GAIA-based passphrase (deprecated). KEYSTORE_PASSPHRASE = 1, // Keystore passphrase. FROZEN_IMPLICIT_PASSPHRASE = 2, // Frozen GAIA passphrase. CUSTOM_PASSPHRASE = 3, // User-provided passphrase. PASSPHRASE_TYPE_SIZE, // The size of this enum; keep last. }; // Enum used to distinguish which bootstrap encryption token is being updated. enum BootstrapTokenType { PASSPHRASE_BOOTSTRAP_TOKEN, KEYSTORE_BOOTSTRAP_TOKEN }; // Sync's encryption handler. Handles tracking encrypted types, ensuring the // cryptographer encrypts with the proper key and has the most recent keybag, // and keeps the nigori node up to date. // Implementations of this class must be assumed to be non-thread-safe. All // methods must be invoked on the sync thread. class SYNC_EXPORT SyncEncryptionHandler { public: // All Observer methods are done synchronously from within a transaction and // on the sync thread. class SYNC_EXPORT Observer { public: Observer(); // Called when user interaction is required to obtain a valid passphrase. // - If the passphrase is required for encryption, |reason| will be // REASON_ENCRYPTION. // - If the passphrase is required for the decryption of data that has // already been encrypted, |reason| will be REASON_DECRYPTION. // - If the passphrase is required because decryption failed, and a new // passphrase is required, |reason| will be REASON_SET_PASSPHRASE_FAILED. // // |pending_keys| is a copy of the cryptographer's pending keys, that may be // cached by the frontend for subsequent use by the UI. virtual void OnPassphraseRequired( PassphraseRequiredReason reason, const sync_pb::EncryptedData& pending_keys) = 0; // Called when the passphrase provided by the user has been accepted and is // now used to encrypt sync data. virtual void OnPassphraseAccepted() = 0; // |bootstrap_token| is an opaque base64 encoded representation of the key // generated by the current passphrase, and is provided to the observer for // persistence purposes and use in a future initialization of sync (e.g. // after restart). The boostrap token will always be derived from the most // recent GAIA password (for accounts with implicit passphrases), even if // the data is still encrypted with an older GAIA password. For accounts // with explicit passphrases, it will be the most recently seen custom // passphrase. virtual void OnBootstrapTokenUpdated( const std::string& bootstrap_token, BootstrapTokenType type) = 0; // Called when the set of encrypted types or the encrypt // everything flag has been changed. Note that encryption isn't // complete until the OnEncryptionComplete() notification has been // sent (see below). // // |encrypted_types| will always be a superset of // Cryptographer::SensitiveTypes(). If |encrypt_everything| is // true, |encrypted_types| will be the set of all known types. // // Until this function is called, observers can assume that the // set of encrypted types is Cryptographer::SensitiveTypes() and // that the encrypt everything flag is false. virtual void OnEncryptedTypesChanged( ModelTypeSet encrypted_types, bool encrypt_everything) = 0; // Called after we finish encrypting the current set of encrypted // types. virtual void OnEncryptionComplete() = 0; // The cryptographer has been updated. Listeners should check that their // own state matches the cryptographer. // Used primarily for debugging. virtual void OnCryptographerStateChanged(Cryptographer* cryptographer) = 0; // The passphrase type has changed. |type| is the new type, // |passphrase_time| is the time the passphrase was set (unset if |type| // is KEYSTORE_PASSPHRASE or the passphrase was set before we started // recording the time). virtual void OnPassphraseTypeChanged(PassphraseType type, base::Time passphrase_time) = 0; protected: virtual ~Observer(); }; SyncEncryptionHandler(); virtual ~SyncEncryptionHandler(); // Add/Remove SyncEncryptionHandler::Observers. virtual void AddObserver(Observer* observer) = 0; virtual void RemoveObserver(Observer* observer) = 0; // Reads the nigori node, updates internal state as needed, and, if an // empty/stale nigori node is detected, overwrites the existing // nigori node. Upon completion, if the cryptographer is still ready // attempts to re-encrypt all sync data. // Note: This method is expensive (it iterates through all encrypted types), // so should only be used sparingly (e.g. on startup). virtual void Init() = 0; // Attempts to re-encrypt encrypted data types using the passphrase provided. // Notifies observers of the result of the operation via OnPassphraseAccepted // or OnPassphraseRequired, updates the nigori node, and does re-encryption as // appropriate. If an explicit password has been set previously, we drop // subsequent requests to set a passphrase. If the cryptographer has pending // keys, and a new implicit passphrase is provided, we try decrypting the // pending keys with it, and if that fails, we cache the passphrase for // re-encryption once the pending keys are decrypted. virtual void SetEncryptionPassphrase(const std::string& passphrase, bool is_explicit) = 0; // Provides a passphrase for decrypting the user's existing sync data. // Notifies observers of the result of the operation via OnPassphraseAccepted // or OnPassphraseRequired, updates the nigori node, and does re-encryption as // appropriate if there is a previously cached encryption passphrase. It is an // error to call this when we don't have pending keys. virtual void SetDecryptionPassphrase(const std::string& passphrase) = 0; // Enables encryption of all datatypes. virtual void EnableEncryptEverything() = 0; // Whether encryption of all datatypes is enabled. If false, only sensitive // types are encrypted. virtual bool EncryptEverythingEnabled() const = 0; // Returns the current state of the passphrase needed to decrypt the // bag of encryption keys in the nigori node. virtual PassphraseType GetPassphraseType() const = 0; // The set of types that are always encrypted. static ModelTypeSet SensitiveTypes(); }; } // namespace syncer #endif // SYNC_INTERNAL_API_PUBLIC_SYNC_ENCRYPTION_HANDLER_H_