// 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.

#include "sync/internal_api/sync_encryption_handler_impl.h"

#include <queue>
#include <string>

#include "base/base64.h"
#include "base/bind.h"
#include "base/json/json_string_value_serializer.h"
#include "base/message_loop/message_loop.h"
#include "base/metrics/histogram.h"
#include "base/time/time.h"
#include "base/tracked_objects.h"
#include "sync/internal_api/public/read_node.h"
#include "sync/internal_api/public/read_transaction.h"
#include "sync/internal_api/public/user_share.h"
#include "sync/internal_api/public/util/experiments.h"
#include "sync/internal_api/public/util/sync_string_conversions.h"
#include "sync/internal_api/public/write_node.h"
#include "sync/internal_api/public/write_transaction.h"
#include "sync/protocol/encryption.pb.h"
#include "sync/protocol/nigori_specifics.pb.h"
#include "sync/protocol/sync.pb.h"
#include "sync/syncable/directory.h"
#include "sync/syncable/entry.h"
#include "sync/syncable/nigori_util.h"
#include "sync/syncable/syncable_base_transaction.h"
#include "sync/util/cryptographer.h"
#include "sync/util/encryptor.h"
#include "sync/util/time.h"

namespace syncer {

namespace {

// The maximum number of times we will automatically overwrite the nigori node
// because the encryption keys don't match (per chrome instantiation).
// We protect ourselves against nigori rollbacks, but it's possible two
// different clients might have contrasting view of what the nigori node state
// should be, in which case they might ping pong (see crbug.com/119207).
static const int kNigoriOverwriteLimit = 10;

// Enumeration of nigori keystore migration results (for use in UMA stats).
enum NigoriMigrationResult {
  FAILED_TO_SET_DEFAULT_KEYSTORE,
  FAILED_TO_SET_NONDEFAULT_KEYSTORE,
  FAILED_TO_EXTRACT_DECRYPTOR,
  FAILED_TO_EXTRACT_KEYBAG,
  MIGRATION_SUCCESS_KEYSTORE_NONDEFAULT,
  MIGRATION_SUCCESS_KEYSTORE_DEFAULT,
  MIGRATION_SUCCESS_FROZEN_IMPLICIT,
  MIGRATION_SUCCESS_CUSTOM,
  MIGRATION_RESULT_SIZE,
};

enum NigoriMigrationState {
  MIGRATED,
  NOT_MIGRATED_CRYPTO_NOT_READY,
  NOT_MIGRATED_NO_KEYSTORE_KEY,
  NOT_MIGRATED_UNKNOWN_REASON,
  MIGRATION_STATE_SIZE,
};

// The new passphrase state is sufficient to determine whether a nigori node
// is migrated to support keystore encryption. In addition though, we also
// want to verify the conditions for proper keystore encryption functionality.
// 1. Passphrase state is set.
// 2. Migration time is set.
// 3. Frozen keybag is true
// 4. If passphrase state is keystore, keystore_decryptor_token is set.
bool IsNigoriMigratedToKeystore(const sync_pb::NigoriSpecifics& nigori) {
  if (!nigori.has_passphrase_type())
    return false;
  if (!nigori.has_keystore_migration_time())
    return false;
  if (!nigori.keybag_is_frozen())
    return false;
  if (nigori.passphrase_type() ==
          sync_pb::NigoriSpecifics::IMPLICIT_PASSPHRASE)
    return false;
  if (nigori.passphrase_type() ==
          sync_pb::NigoriSpecifics::KEYSTORE_PASSPHRASE &&
      nigori.keystore_decryptor_token().blob().empty())
    return false;
  if (!nigori.has_keystore_migration_time())
    return false;
  return true;
}

PassphraseType ProtoPassphraseTypeToEnum(
    sync_pb::NigoriSpecifics::PassphraseType type) {
  switch(type) {
    case sync_pb::NigoriSpecifics::IMPLICIT_PASSPHRASE:
      return IMPLICIT_PASSPHRASE;
    case sync_pb::NigoriSpecifics::KEYSTORE_PASSPHRASE:
      return KEYSTORE_PASSPHRASE;
    case sync_pb::NigoriSpecifics::CUSTOM_PASSPHRASE:
      return CUSTOM_PASSPHRASE;
    case sync_pb::NigoriSpecifics::FROZEN_IMPLICIT_PASSPHRASE:
      return FROZEN_IMPLICIT_PASSPHRASE;
    default:
      NOTREACHED();
      return IMPLICIT_PASSPHRASE;
  };
}

sync_pb::NigoriSpecifics::PassphraseType
EnumPassphraseTypeToProto(PassphraseType type) {
  switch(type) {
    case IMPLICIT_PASSPHRASE:
      return sync_pb::NigoriSpecifics::IMPLICIT_PASSPHRASE;
    case KEYSTORE_PASSPHRASE:
      return sync_pb::NigoriSpecifics::KEYSTORE_PASSPHRASE;
    case CUSTOM_PASSPHRASE:
      return sync_pb::NigoriSpecifics::CUSTOM_PASSPHRASE;
    case FROZEN_IMPLICIT_PASSPHRASE:
      return sync_pb::NigoriSpecifics::FROZEN_IMPLICIT_PASSPHRASE;
    default:
      NOTREACHED();
      return sync_pb::NigoriSpecifics::IMPLICIT_PASSPHRASE;
  };
}

bool IsExplicitPassphrase(PassphraseType type) {
  return type == CUSTOM_PASSPHRASE || type == FROZEN_IMPLICIT_PASSPHRASE;
}

// Keystore Bootstrap Token helper methods.
// The bootstrap is a base64 encoded, encrypted, ListValue of keystore key
// strings, with the current keystore key as the last value in the list.
std::string PackKeystoreBootstrapToken(
    const std::vector<std::string>& old_keystore_keys,
    const std::string& current_keystore_key,
    Encryptor* encryptor) {
  if (current_keystore_key.empty())
    return std::string();

  base::ListValue keystore_key_values;
  for (size_t i = 0; i < old_keystore_keys.size(); ++i)
    keystore_key_values.AppendString(old_keystore_keys[i]);
  keystore_key_values.AppendString(current_keystore_key);

  // Update the bootstrap token.
  // The bootstrap is a base64 encoded, encrypted, ListValue of keystore key
  // strings, with the current keystore key as the last value in the list.
  std::string serialized_keystores;
  JSONStringValueSerializer json(&serialized_keystores);
  json.Serialize(keystore_key_values);
  std::string encrypted_keystores;
  encryptor->EncryptString(serialized_keystores,
                           &encrypted_keystores);
  std::string keystore_bootstrap;
  base::Base64Encode(encrypted_keystores, &keystore_bootstrap);
  return keystore_bootstrap;
}

bool UnpackKeystoreBootstrapToken(
    const std::string& keystore_bootstrap_token,
    Encryptor* encryptor,
    std::vector<std::string>* old_keystore_keys,
    std::string* current_keystore_key) {
  if (keystore_bootstrap_token.empty())
    return false;
  std::string base64_decoded_keystore_bootstrap;
  if (!base::Base64Decode(keystore_bootstrap_token,
                          &base64_decoded_keystore_bootstrap)) {
    return false;
  }
  std::string decrypted_keystore_bootstrap;
  if (!encryptor->DecryptString(base64_decoded_keystore_bootstrap,
                                &decrypted_keystore_bootstrap)) {
    return false;
  }
  JSONStringValueSerializer json(&decrypted_keystore_bootstrap);
  scoped_ptr<base::Value> deserialized_keystore_keys(
      json.Deserialize(NULL, NULL));
  if (!deserialized_keystore_keys)
    return false;
  base::ListValue* internal_list_value = NULL;
  if (!deserialized_keystore_keys->GetAsList(&internal_list_value))
    return false;
  int number_of_keystore_keys = internal_list_value->GetSize();
  if (!internal_list_value->GetString(number_of_keystore_keys - 1,
                                      current_keystore_key)) {
    return false;
  }
  old_keystore_keys->resize(number_of_keystore_keys - 1);
  for (int i = 0; i < number_of_keystore_keys - 1; ++i)
    internal_list_value->GetString(i, &(*old_keystore_keys)[i]);
  return true;
}

}  // namespace

SyncEncryptionHandlerImpl::Vault::Vault(
    Encryptor* encryptor,
    ModelTypeSet encrypted_types)
    : cryptographer(encryptor),
      encrypted_types(encrypted_types) {
}

SyncEncryptionHandlerImpl::Vault::~Vault() {
}

SyncEncryptionHandlerImpl::SyncEncryptionHandlerImpl(
    UserShare* user_share,
    Encryptor* encryptor,
    const std::string& restored_key_for_bootstrapping,
    const std::string& restored_keystore_key_for_bootstrapping)
    : user_share_(user_share),
      vault_unsafe_(encryptor, SensitiveTypes()),
      encrypt_everything_(false),
      passphrase_type_(IMPLICIT_PASSPHRASE),
      nigori_overwrite_count_(0),
      weak_ptr_factory_(this) {
  // Restore the cryptographer's previous keys. Note that we don't add the
  // keystore keys into the cryptographer here, in case a migration was pending.
  vault_unsafe_.cryptographer.Bootstrap(restored_key_for_bootstrapping);

  // If this fails, we won't have a valid keystore key, and will simply request
  // new ones from the server on the next DownloadUpdates.
  UnpackKeystoreBootstrapToken(
      restored_keystore_key_for_bootstrapping,
      encryptor,
      &old_keystore_keys_,
      &keystore_key_);
}

SyncEncryptionHandlerImpl::~SyncEncryptionHandlerImpl() {}

void SyncEncryptionHandlerImpl::AddObserver(Observer* observer) {
  DCHECK(thread_checker_.CalledOnValidThread());
  DCHECK(!observers_.HasObserver(observer));
  observers_.AddObserver(observer);
}

void SyncEncryptionHandlerImpl::RemoveObserver(Observer* observer) {
  DCHECK(thread_checker_.CalledOnValidThread());
  DCHECK(observers_.HasObserver(observer));
  observers_.RemoveObserver(observer);
}

void SyncEncryptionHandlerImpl::Init() {
  DCHECK(thread_checker_.CalledOnValidThread());
  WriteTransaction trans(FROM_HERE, user_share_);
  WriteNode node(&trans);

  if (node.InitTypeRoot(NIGORI) != BaseNode::INIT_OK)
    return;
  if (!ApplyNigoriUpdateImpl(node.GetNigoriSpecifics(),
                             trans.GetWrappedTrans())) {
    WriteEncryptionStateToNigori(&trans);
  }

  bool has_pending_keys = UnlockVault(
      trans.GetWrappedTrans()).cryptographer.has_pending_keys();
  bool is_ready = UnlockVault(
      trans.GetWrappedTrans()).cryptographer.is_ready();
  // Log the state of the cryptographer regardless of migration state.
  UMA_HISTOGRAM_BOOLEAN("Sync.CryptographerReady", is_ready);
  UMA_HISTOGRAM_BOOLEAN("Sync.CryptographerPendingKeys", has_pending_keys);
  if (IsNigoriMigratedToKeystore(node.GetNigoriSpecifics())) {
    // This account has a nigori node that has been migrated to support
    // keystore.
    UMA_HISTOGRAM_ENUMERATION("Sync.NigoriMigrationState",
                              MIGRATED,
                              MIGRATION_STATE_SIZE);
    if (has_pending_keys && passphrase_type_ == KEYSTORE_PASSPHRASE) {
      // If this is happening, it means the keystore decryptor is either
      // undecryptable with the available keystore keys or does not match the
      // nigori keybag's encryption key. Otherwise we're simply missing the
      // keystore key.
      UMA_HISTOGRAM_BOOLEAN("Sync.KeystoreDecryptionFailed",
                            !keystore_key_.empty());
    }
  } else if (!is_ready) {
    // Migration cannot occur until the cryptographer is ready (initialized
    // with GAIA password and any pending keys resolved).
    UMA_HISTOGRAM_ENUMERATION("Sync.NigoriMigrationState",
                              NOT_MIGRATED_CRYPTO_NOT_READY,
                              MIGRATION_STATE_SIZE);
  } else if (keystore_key_.empty()) {
    // The client has no keystore key, either because it is not yet enabled or
    // the server is not sending a valid keystore key.
    UMA_HISTOGRAM_ENUMERATION("Sync.NigoriMigrationState",
                              NOT_MIGRATED_NO_KEYSTORE_KEY,
                              MIGRATION_STATE_SIZE);
  } else {
    // If the above conditions have been met and the nigori node is still not
    // migrated, something failed in the migration process.
    UMA_HISTOGRAM_ENUMERATION("Sync.NigoriMigrationState",
                              NOT_MIGRATED_UNKNOWN_REASON,
                              MIGRATION_STATE_SIZE);
  }


  // Always trigger an encrypted types and cryptographer state change event at
  // init time so observers get the initial values.
  FOR_EACH_OBSERVER(
      Observer, observers_,
      OnEncryptedTypesChanged(
          UnlockVault(trans.GetWrappedTrans()).encrypted_types,
          encrypt_everything_));
  FOR_EACH_OBSERVER(
      SyncEncryptionHandler::Observer,
      observers_,
      OnCryptographerStateChanged(
          &UnlockVaultMutable(trans.GetWrappedTrans())->cryptographer));

  // If the cryptographer is not ready (either it has pending keys or we
  // failed to initialize it), we don't want to try and re-encrypt the data.
  // If we had encrypted types, the DataTypeManager will block, preventing
  // sync from happening until the the passphrase is provided.
  if (UnlockVault(trans.GetWrappedTrans()).cryptographer.is_ready())
    ReEncryptEverything(&trans);
}

void SyncEncryptionHandlerImpl::SetEncryptionPassphrase(
    const std::string& passphrase,
    bool is_explicit) {
  DCHECK(thread_checker_.CalledOnValidThread());
  // We do not accept empty passphrases.
  if (passphrase.empty()) {
    NOTREACHED() << "Cannot encrypt with an empty passphrase.";
    return;
  }

  // All accesses to the cryptographer are protected by a transaction.
  WriteTransaction trans(FROM_HERE, user_share_);
  KeyParams key_params = {"localhost", "dummy", passphrase};
  WriteNode node(&trans);
  if (node.InitTypeRoot(NIGORI) != BaseNode::INIT_OK) {
    NOTREACHED();
    return;
  }

  Cryptographer* cryptographer =
      &UnlockVaultMutable(trans.GetWrappedTrans())->cryptographer;

  // Once we've migrated to keystore, the only way to set a passphrase for
  // encryption is to set a custom passphrase.
  if (IsNigoriMigratedToKeystore(node.GetNigoriSpecifics())) {
    if (!is_explicit) {
      // The user is setting a new implicit passphrase. At this point we don't
      // care, so drop it on the floor. This is safe because if we have a
      // migrated nigori node, then we don't need to create an initial
      // encryption key.
      LOG(WARNING) << "Ignoring new implicit passphrase. Keystore migration "
                   << "already performed.";
      return;
    }
    // Will fail if we already have an explicit passphrase or we have pending
    // keys.
    SetCustomPassphrase(passphrase, &trans, &node);

    // When keystore migration occurs, the "CustomEncryption" UMA stat must be
    // logged as true.
    UMA_HISTOGRAM_BOOLEAN("Sync.CustomEncryption", true);
    return;
  }

  std::string bootstrap_token;
  sync_pb::EncryptedData pending_keys;
  if (cryptographer->has_pending_keys())
    pending_keys = cryptographer->GetPendingKeys();
  bool success = false;

  // There are six cases to handle here:
  // 1. The user has no pending keys and is setting their current GAIA password
  //    as the encryption passphrase. This happens either during first time sync
  //    with a clean profile, or after re-authenticating on a profile that was
  //    already signed in with the cryptographer ready.
  // 2. The user has no pending keys, and is overwriting an (already provided)
  //    implicit passphrase with an explicit (custom) passphrase.
  // 3. The user has pending keys for an explicit passphrase that is somehow set
  //    to their current GAIA passphrase.
  // 4. The user has pending keys encrypted with their current GAIA passphrase
  //    and the caller passes in the current GAIA passphrase.
  // 5. The user has pending keys encrypted with an older GAIA passphrase
  //    and the caller passes in the current GAIA passphrase.
  // 6. The user has previously done encryption with an explicit passphrase.
  // Furthermore, we enforce the fact that the bootstrap encryption token will
  // always be derived from the newest GAIA password if the account is using
  // an implicit passphrase (even if the data is encrypted with an old GAIA
  // password). If the account is using an explicit (custom) passphrase, the
  // bootstrap token will be derived from the most recently provided explicit
  // passphrase (that was able to decrypt the data).
  if (!IsExplicitPassphrase(passphrase_type_)) {
    if (!cryptographer->has_pending_keys()) {
      if (cryptographer->AddKey(key_params)) {
        // Case 1 and 2. We set a new GAIA passphrase when there are no pending
        // keys (1), or overwriting an implicit passphrase with a new explicit
        // one (2) when there are no pending keys.
        if (is_explicit) {
          DVLOG(1) << "Setting explicit passphrase for encryption.";
          passphrase_type_ = CUSTOM_PASSPHRASE;
          custom_passphrase_time_ = base::Time::Now();
          FOR_EACH_OBSERVER(SyncEncryptionHandler::Observer, observers_,
                            OnPassphraseTypeChanged(
                                passphrase_type_,
                                GetExplicitPassphraseTime()));
        } else {
          DVLOG(1) << "Setting implicit passphrase for encryption.";
        }
        cryptographer->GetBootstrapToken(&bootstrap_token);

        // With M26, sync accounts can be in only one of two encryption states:
        // 1) Encrypt only passwords with an implicit passphrase.
        // 2) Encrypt all sync datatypes with an explicit passphrase.
        // We deprecate the "EncryptAllData" and "CustomPassphrase" histograms,
        // and keep track of an account's encryption state via the
        // "CustomEncryption" histogram. See http://crbug.com/131478.
        UMA_HISTOGRAM_BOOLEAN("Sync.CustomEncryption", is_explicit);

        success = true;
      } else {
        NOTREACHED() << "Failed to add key to cryptographer.";
        success = false;
      }
    } else {  // cryptographer->has_pending_keys() == true
      if (is_explicit) {
        // This can only happen if the nigori node is updated with a new
        // implicit passphrase while a client is attempting to set a new custom
        // passphrase (race condition).
        DVLOG(1) << "Failing because an implicit passphrase is already set.";
        success = false;
      } else {  // is_explicit == false
        if (cryptographer->DecryptPendingKeys(key_params)) {
          // Case 4. We successfully decrypted with the implicit GAIA passphrase
          // passed in.
          DVLOG(1) << "Implicit internal passphrase accepted for decryption.";
          cryptographer->GetBootstrapToken(&bootstrap_token);
          success = true;
        } else {
          // Case 5. Encryption was done with an old GAIA password, but we were
          // provided with the current GAIA password. We need to generate a new
          // bootstrap token to preserve it. We build a temporary cryptographer
          // to allow us to extract these params without polluting our current
          // cryptographer.
          DVLOG(1) << "Implicit internal passphrase failed to decrypt, adding "
                   << "anyways as default passphrase and persisting via "
                   << "bootstrap token.";
          Cryptographer temp_cryptographer(cryptographer->encryptor());
          temp_cryptographer.AddKey(key_params);
          temp_cryptographer.GetBootstrapToken(&bootstrap_token);
          // We then set the new passphrase as the default passphrase of the
          // real cryptographer, even though we have pending keys. This is safe,
          // as although Cryptographer::is_initialized() will now be true,
          // is_ready() will remain false due to having pending keys.
          cryptographer->AddKey(key_params);
          success = false;
        }
      }  // is_explicit
    }  // cryptographer->has_pending_keys()
  } else {  // IsExplicitPassphrase(passphrase_type_) == true.
    // Case 6. We do not want to override a previously set explicit passphrase,
    // so we return a failure.
    DVLOG(1) << "Failing because an explicit passphrase is already set.";
    success = false;
  }

  DVLOG_IF(1, !success)
      << "Failure in SetEncryptionPassphrase; notifying and returning.";
  DVLOG_IF(1, success)
      << "Successfully set encryption passphrase; updating nigori and "
         "reencrypting.";

  FinishSetPassphrase(success, bootstrap_token, &trans, &node);
}

void SyncEncryptionHandlerImpl::SetDecryptionPassphrase(
    const std::string& passphrase) {
  DCHECK(thread_checker_.CalledOnValidThread());
  // We do not accept empty passphrases.
  if (passphrase.empty()) {
    NOTREACHED() << "Cannot decrypt with an empty passphrase.";
    return;
  }

  // All accesses to the cryptographer are protected by a transaction.
  WriteTransaction trans(FROM_HERE, user_share_);
  KeyParams key_params = {"localhost", "dummy", passphrase};
  WriteNode node(&trans);
  if (node.InitTypeRoot(NIGORI) != BaseNode::INIT_OK) {
    NOTREACHED();
    return;
  }

  // Once we've migrated to keystore, we're only ever decrypting keys derived
  // from an explicit passphrase. But, for clients without a keystore key yet
  // (either not on by default or failed to download one), we still support
  // decrypting with a gaia passphrase, and therefore bypass the
  // DecryptPendingKeysWithExplicitPassphrase logic.
  if (IsNigoriMigratedToKeystore(node.GetNigoriSpecifics()) &&
      IsExplicitPassphrase(passphrase_type_)) {
    DecryptPendingKeysWithExplicitPassphrase(passphrase, &trans, &node);
    return;
  }

  Cryptographer* cryptographer =
      &UnlockVaultMutable(trans.GetWrappedTrans())->cryptographer;
  if (!cryptographer->has_pending_keys()) {
    // Note that this *can* happen in a rare situation where data is
    // re-encrypted on another client while a SetDecryptionPassphrase() call is
    // in-flight on this client. It is rare enough that we choose to do nothing.
    NOTREACHED() << "Attempt to set decryption passphrase failed because there "
                 << "were no pending keys.";
    return;
  }

  std::string bootstrap_token;
  sync_pb::EncryptedData pending_keys;
  pending_keys = cryptographer->GetPendingKeys();
  bool success = false;

  // There are three cases to handle here:
  // 7. We're using the current GAIA password to decrypt the pending keys. This
  //    happens when signing in to an account with a previously set implicit
  //    passphrase, where the data is already encrypted with the newest GAIA
  //    password.
  // 8. The user is providing an old GAIA password to decrypt the pending keys.
  //    In this case, the user is using an implicit passphrase, but has changed
  //    their password since they last encrypted their data, and therefore
  //    their current GAIA password was unable to decrypt the data. This will
  //    happen when the user is setting up a new profile with a previously
  //    encrypted account (after changing passwords).
  // 9. The user is providing a previously set explicit passphrase to decrypt
  //    the pending keys.
  if (!IsExplicitPassphrase(passphrase_type_)) {
    if (cryptographer->is_initialized()) {
      // We only want to change the default encryption key to the pending
      // one if the pending keybag already contains the current default.
      // This covers the case where a different client re-encrypted
      // everything with a newer gaia passphrase (and hence the keybag
      // contains keys from all previously used gaia passphrases).
      // Otherwise, we're in a situation where the pending keys are
      // encrypted with an old gaia passphrase, while the default is the
      // current gaia passphrase. In that case, we preserve the default.
      Cryptographer temp_cryptographer(cryptographer->encryptor());
      temp_cryptographer.SetPendingKeys(cryptographer->GetPendingKeys());
      if (temp_cryptographer.DecryptPendingKeys(key_params)) {
        // Check to see if the pending bag of keys contains the current
        // default key.
        sync_pb::EncryptedData encrypted;
        cryptographer->GetKeys(&encrypted);
        if (temp_cryptographer.CanDecrypt(encrypted)) {
          DVLOG(1) << "Implicit user provided passphrase accepted for "
                   << "decryption, overwriting default.";
          // Case 7. The pending keybag contains the current default. Go ahead
          // and update the cryptographer, letting the default change.
          cryptographer->DecryptPendingKeys(key_params);
          cryptographer->GetBootstrapToken(&bootstrap_token);
          success = true;
        } else {
          // Case 8. The pending keybag does not contain the current default
          // encryption key. We decrypt the pending keys here, and in
          // FinishSetPassphrase, re-encrypt everything with the current GAIA
          // passphrase instead of the passphrase just provided by the user.
          DVLOG(1) << "Implicit user provided passphrase accepted for "
                   << "decryption, restoring implicit internal passphrase "
                   << "as default.";
          std::string bootstrap_token_from_current_key;
          cryptographer->GetBootstrapToken(
              &bootstrap_token_from_current_key);
          cryptographer->DecryptPendingKeys(key_params);
          // Overwrite the default from the pending keys.
          cryptographer->AddKeyFromBootstrapToken(
              bootstrap_token_from_current_key);
          success = true;
        }
      } else {  // !temp_cryptographer.DecryptPendingKeys(..)
        DVLOG(1) << "Implicit user provided passphrase failed to decrypt.";
        success = false;
      }  // temp_cryptographer.DecryptPendingKeys(...)
    } else {  // cryptographer->is_initialized() == false
      if (cryptographer->DecryptPendingKeys(key_params)) {
        // This can happpen in two cases:
        // - First time sync on android, where we'll never have a
        //   !user_provided passphrase.
        // - This is a restart for a client that lost their bootstrap token.
        // In both cases, we should go ahead and initialize the cryptographer
        // and persist the new bootstrap token.
        //
        // Note: at this point, we cannot distinguish between cases 7 and 8
        // above. This user provided passphrase could be the current or the
        // old. But, as long as we persist the token, there's nothing more
        // we can do.
        cryptographer->GetBootstrapToken(&bootstrap_token);
        DVLOG(1) << "Implicit user provided passphrase accepted, initializing"
                 << " cryptographer.";
        success = true;
      } else {
        DVLOG(1) << "Implicit user provided passphrase failed to decrypt.";
        success = false;
      }
    }  // cryptographer->is_initialized()
  } else {  // nigori_has_explicit_passphrase == true
    // Case 9. Encryption was done with an explicit passphrase, and we decrypt
    // with the passphrase provided by the user.
    if (cryptographer->DecryptPendingKeys(key_params)) {
      DVLOG(1) << "Explicit passphrase accepted for decryption.";
      cryptographer->GetBootstrapToken(&bootstrap_token);
      success = true;
    } else {
      DVLOG(1) << "Explicit passphrase failed to decrypt.";
      success = false;
    }
  }  // nigori_has_explicit_passphrase

  DVLOG_IF(1, !success)
      << "Failure in SetDecryptionPassphrase; notifying and returning.";
  DVLOG_IF(1, success)
      << "Successfully set decryption passphrase; updating nigori and "
         "reencrypting.";

  FinishSetPassphrase(success, bootstrap_token, &trans, &node);
}

void SyncEncryptionHandlerImpl::EnableEncryptEverything() {
  DCHECK(thread_checker_.CalledOnValidThread());
  WriteTransaction trans(FROM_HERE, user_share_);
  DVLOG(1) << "Enabling encrypt everything.";
  if (encrypt_everything_)
    return;
  EnableEncryptEverythingImpl(trans.GetWrappedTrans());
  WriteEncryptionStateToNigori(&trans);
  if (UnlockVault(trans.GetWrappedTrans()).cryptographer.is_ready())
    ReEncryptEverything(&trans);
}

bool SyncEncryptionHandlerImpl::EncryptEverythingEnabled() const {
  DCHECK(thread_checker_.CalledOnValidThread());
  return encrypt_everything_;
}

PassphraseType SyncEncryptionHandlerImpl::GetPassphraseType() const {
  DCHECK(thread_checker_.CalledOnValidThread());
  return passphrase_type_;
}

// Note: this is called from within a syncable transaction, so we need to post
// tasks if we want to do any work that creates a new sync_api transaction.
void SyncEncryptionHandlerImpl::ApplyNigoriUpdate(
    const sync_pb::NigoriSpecifics& nigori,
    syncable::BaseTransaction* const trans) {
  DCHECK(thread_checker_.CalledOnValidThread());
  DCHECK(trans);
  if (!ApplyNigoriUpdateImpl(nigori, trans)) {
    base::MessageLoop::current()->PostTask(
        FROM_HERE,
        base::Bind(&SyncEncryptionHandlerImpl::RewriteNigori,
                   weak_ptr_factory_.GetWeakPtr()));
  }

  FOR_EACH_OBSERVER(
      SyncEncryptionHandler::Observer,
      observers_,
      OnCryptographerStateChanged(
          &UnlockVaultMutable(trans)->cryptographer));
}

void SyncEncryptionHandlerImpl::UpdateNigoriFromEncryptedTypes(
    sync_pb::NigoriSpecifics* nigori,
    syncable::BaseTransaction* const trans) const {
  DCHECK(thread_checker_.CalledOnValidThread());
  syncable::UpdateNigoriFromEncryptedTypes(UnlockVault(trans).encrypted_types,
                                           encrypt_everything_,
                                           nigori);
}

bool SyncEncryptionHandlerImpl::NeedKeystoreKey(
    syncable::BaseTransaction* const trans) const {
  DCHECK(thread_checker_.CalledOnValidThread());
  return keystore_key_.empty();
}

bool SyncEncryptionHandlerImpl::SetKeystoreKeys(
    const google::protobuf::RepeatedPtrField<google::protobuf::string>& keys,
    syncable::BaseTransaction* const trans) {
  DCHECK(thread_checker_.CalledOnValidThread());
  if (keys.size() == 0)
    return false;
  // The last key in the vector is the current keystore key. The others are kept
  // around for decryption only.
  const std::string& raw_keystore_key = keys.Get(keys.size() - 1);
  if (raw_keystore_key.empty())
    return false;

  // Note: in order to Pack the keys, they must all be base64 encoded (else
  // JSON serialization fails).
  base::Base64Encode(raw_keystore_key, &keystore_key_);

  // Go through and save the old keystore keys. We always persist all keystore
  // keys the server sends us.
  old_keystore_keys_.resize(keys.size() - 1);
  for (int i = 0; i < keys.size() - 1; ++i)
    base::Base64Encode(keys.Get(i), &old_keystore_keys_[i]);

  Cryptographer* cryptographer = &UnlockVaultMutable(trans)->cryptographer;

  // Update the bootstrap token. If this fails, we persist an empty string,
  // which will force us to download the keystore keys again on the next
  // restart.
  std::string keystore_bootstrap = PackKeystoreBootstrapToken(
      old_keystore_keys_,
      keystore_key_,
      cryptographer->encryptor());
  DCHECK_EQ(keystore_bootstrap.empty(), keystore_key_.empty());
  FOR_EACH_OBSERVER(SyncEncryptionHandler::Observer, observers_,
                    OnBootstrapTokenUpdated(keystore_bootstrap,
                                            KEYSTORE_BOOTSTRAP_TOKEN));
  DVLOG(1) << "Keystore bootstrap token updated.";

  // If this is a first time sync, we get the encryption keys before we process
  // the nigori node. Just return for now, ApplyNigoriUpdate will be invoked
  // once we have the nigori node.
  syncable::Entry entry(trans, syncable::GET_TYPE_ROOT, NIGORI);
  if (!entry.good())
    return true;

  const sync_pb::NigoriSpecifics& nigori =
      entry.GetSpecifics().nigori();
  if (cryptographer->has_pending_keys() &&
      IsNigoriMigratedToKeystore(nigori) &&
      !nigori.keystore_decryptor_token().blob().empty()) {
    // If the nigori is already migrated and we have pending keys, we might
    // be able to decrypt them using either the keystore decryptor token
    // or the existing keystore keys.
    DecryptPendingKeysWithKeystoreKey(keystore_key_,
                                      nigori.keystore_decryptor_token(),
                                      cryptographer);
  }

  // Note that triggering migration will have no effect if we're already
  // properly migrated with the newest keystore keys.
  if (ShouldTriggerMigration(nigori, *cryptographer)) {
    base::MessageLoop::current()->PostTask(
        FROM_HERE,
        base::Bind(&SyncEncryptionHandlerImpl::RewriteNigori,
                   weak_ptr_factory_.GetWeakPtr()));
  }

  return true;
}

ModelTypeSet SyncEncryptionHandlerImpl::GetEncryptedTypes(
    syncable::BaseTransaction* const trans) const {
  return UnlockVault(trans).encrypted_types;
}

Cryptographer* SyncEncryptionHandlerImpl::GetCryptographerUnsafe() {
  DCHECK(thread_checker_.CalledOnValidThread());
  return &vault_unsafe_.cryptographer;
}

ModelTypeSet SyncEncryptionHandlerImpl::GetEncryptedTypesUnsafe() {
  DCHECK(thread_checker_.CalledOnValidThread());
  return vault_unsafe_.encrypted_types;
}

bool SyncEncryptionHandlerImpl::MigratedToKeystore() {
  DCHECK(thread_checker_.CalledOnValidThread());
  ReadTransaction trans(FROM_HERE, user_share_);
  ReadNode nigori_node(&trans);
  if (nigori_node.InitTypeRoot(NIGORI) != BaseNode::INIT_OK)
    return false;
  return IsNigoriMigratedToKeystore(nigori_node.GetNigoriSpecifics());
}

base::Time SyncEncryptionHandlerImpl::migration_time() const {
  return migration_time_;
}

base::Time SyncEncryptionHandlerImpl::custom_passphrase_time() const {
  return custom_passphrase_time_;
}

// This function iterates over all encrypted types.  There are many scenarios in
// which data for some or all types is not currently available.  In that case,
// the lookup of the root node will fail and we will skip encryption for that
// type.
void SyncEncryptionHandlerImpl::ReEncryptEverything(
    WriteTransaction* trans) {
  DCHECK(thread_checker_.CalledOnValidThread());
  DCHECK(UnlockVault(trans->GetWrappedTrans()).cryptographer.is_ready());
  for (ModelTypeSet::Iterator iter =
           UnlockVault(trans->GetWrappedTrans()).encrypted_types.First();
       iter.Good(); iter.Inc()) {
    if (iter.Get() == PASSWORDS || IsControlType(iter.Get()))
      continue; // These types handle encryption differently.

    ReadNode type_root(trans);
    if (type_root.InitTypeRoot(iter.Get()) != BaseNode::INIT_OK)
      continue; // Don't try to reencrypt if the type's data is unavailable.

    // Iterate through all children of this datatype.
    std::queue<int64> to_visit;
    int64 child_id = type_root.GetFirstChildId();
    to_visit.push(child_id);
    while (!to_visit.empty()) {
      child_id = to_visit.front();
      to_visit.pop();
      if (child_id == kInvalidId)
        continue;

      WriteNode child(trans);
      if (child.InitByIdLookup(child_id) != BaseNode::INIT_OK)
        continue;  // Possible for locally deleted items.
      if (child.GetIsFolder()) {
        to_visit.push(child.GetFirstChildId());
      }
      if (child.GetEntry()->GetUniqueServerTag().empty()) {
      // Rewrite the specifics of the node with encrypted data if necessary
      // (only rewrite the non-unique folders).
        child.ResetFromSpecifics();
      }
      to_visit.push(child.GetSuccessorId());
    }
  }

  // Passwords are encrypted with their own legacy scheme.  Passwords are always
  // encrypted so we don't need to check GetEncryptedTypes() here.
  ReadNode passwords_root(trans);
  if (passwords_root.InitTypeRoot(PASSWORDS) == BaseNode::INIT_OK) {
    int64 child_id = passwords_root.GetFirstChildId();
    while (child_id != kInvalidId) {
      WriteNode child(trans);
      if (child.InitByIdLookup(child_id) != BaseNode::INIT_OK) {
        NOTREACHED();
        return;
      }
      child.SetPasswordSpecifics(child.GetPasswordSpecifics());
      child_id = child.GetSuccessorId();
    }
  }

  DVLOG(1) << "Re-encrypt everything complete.";

  // NOTE: We notify from within a transaction.
  FOR_EACH_OBSERVER(SyncEncryptionHandler::Observer, observers_,
                    OnEncryptionComplete());
}

bool SyncEncryptionHandlerImpl::ApplyNigoriUpdateImpl(
    const sync_pb::NigoriSpecifics& nigori,
    syncable::BaseTransaction* const trans) {
  DCHECK(thread_checker_.CalledOnValidThread());
  DVLOG(1) << "Applying nigori node update.";
  bool nigori_types_need_update = !UpdateEncryptedTypesFromNigori(nigori,
                                                                  trans);

  if (nigori.custom_passphrase_time() != 0) {
    custom_passphrase_time_ =
        ProtoTimeToTime(nigori.custom_passphrase_time());
  }
  bool is_nigori_migrated = IsNigoriMigratedToKeystore(nigori);
  if (is_nigori_migrated) {
    DCHECK(nigori.has_keystore_migration_time());
    migration_time_ = ProtoTimeToTime(nigori.keystore_migration_time());
    PassphraseType nigori_passphrase_type =
        ProtoPassphraseTypeToEnum(nigori.passphrase_type());

    // Only update the local passphrase state if it's a valid transition:
    // - implicit -> keystore
    // - implicit -> frozen implicit
    // - implicit -> custom
    // - keystore -> custom
    // Note: frozen implicit -> custom is not technically a valid transition,
    // but we let it through here as well in case future versions do add support
    // for this transition.
    if (passphrase_type_ != nigori_passphrase_type &&
        nigori_passphrase_type != IMPLICIT_PASSPHRASE &&
        (passphrase_type_ == IMPLICIT_PASSPHRASE ||
         nigori_passphrase_type == CUSTOM_PASSPHRASE)) {
      DVLOG(1) << "Changing passphrase state from "
               << PassphraseTypeToString(passphrase_type_)
               << " to "
               << PassphraseTypeToString(nigori_passphrase_type);
      passphrase_type_ = nigori_passphrase_type;
      FOR_EACH_OBSERVER(SyncEncryptionHandler::Observer, observers_,
                            OnPassphraseTypeChanged(
                                passphrase_type_,
                                GetExplicitPassphraseTime()));
    }
    if (passphrase_type_ == KEYSTORE_PASSPHRASE && encrypt_everything_) {
      // This is the case where another client that didn't support keystore
      // encryption attempted to enable full encryption. We detect it
      // and switch the passphrase type to frozen implicit passphrase instead
      // due to full encryption not being compatible with keystore passphrase.
      // Because the local passphrase type will not match the nigori passphrase
      // type, we will trigger a rewrite and subsequently a re-migration.
      DVLOG(1) << "Changing passphrase state to FROZEN_IMPLICIT_PASSPHRASE "
               << "due to full encryption.";
      passphrase_type_ = FROZEN_IMPLICIT_PASSPHRASE;
      FOR_EACH_OBSERVER(SyncEncryptionHandler::Observer, observers_,
                            OnPassphraseTypeChanged(
                                passphrase_type_,
                                GetExplicitPassphraseTime()));
    }
  } else {
    // It's possible that while we're waiting for migration a client that does
    // not have keystore encryption enabled switches to a custom passphrase.
    if (nigori.keybag_is_frozen() &&
        passphrase_type_ != CUSTOM_PASSPHRASE) {
      passphrase_type_ = CUSTOM_PASSPHRASE;
      FOR_EACH_OBSERVER(SyncEncryptionHandler::Observer, observers_,
                            OnPassphraseTypeChanged(
                                passphrase_type_,
                                GetExplicitPassphraseTime()));
    }
  }

  Cryptographer* cryptographer = &UnlockVaultMutable(trans)->cryptographer;
  bool nigori_needs_new_keys = false;
  if (!nigori.encryption_keybag().blob().empty()) {
    // We only update the default key if this was a new explicit passphrase.
    // Else, since it was decryptable, it must not have been a new key.
    bool need_new_default_key = false;
    if (is_nigori_migrated) {
      need_new_default_key = IsExplicitPassphrase(
          ProtoPassphraseTypeToEnum(nigori.passphrase_type()));
    } else {
      need_new_default_key = nigori.keybag_is_frozen();
    }
    if (!AttemptToInstallKeybag(nigori.encryption_keybag(),
                                need_new_default_key,
                                cryptographer)) {
      // Check to see if we can decrypt the keybag using the keystore decryptor
      // token.
      cryptographer->SetPendingKeys(nigori.encryption_keybag());
      if (!nigori.keystore_decryptor_token().blob().empty() &&
          !keystore_key_.empty()) {
        if (DecryptPendingKeysWithKeystoreKey(keystore_key_,
                                              nigori.keystore_decryptor_token(),
                                              cryptographer)) {
          nigori_needs_new_keys =
              cryptographer->KeybagIsStale(nigori.encryption_keybag());
        } else {
          LOG(ERROR) << "Failed to decrypt pending keys using keystore "
                     << "bootstrap key.";
        }
      }
    } else {
      // Keybag was installed. We write back our local keybag into the nigori
      // node if the nigori node's keybag either contains less keys or
      // has a different default key.
      nigori_needs_new_keys =
          cryptographer->KeybagIsStale(nigori.encryption_keybag());
    }
  } else {
    // The nigori node has an empty encryption keybag. Attempt to write our
    // local encryption keys into it.
    LOG(WARNING) << "Nigori had empty encryption keybag.";
    nigori_needs_new_keys = true;
  }

  // If we've completed a sync cycle and the cryptographer isn't ready
  // yet or has pending keys, prompt the user for a passphrase.
  if (cryptographer->has_pending_keys()) {
    DVLOG(1) << "OnPassphraseRequired Sent";
    sync_pb::EncryptedData pending_keys = cryptographer->GetPendingKeys();
    FOR_EACH_OBSERVER(SyncEncryptionHandler::Observer, observers_,
                      OnPassphraseRequired(REASON_DECRYPTION,
                                           pending_keys));
  } else if (!cryptographer->is_ready()) {
    DVLOG(1) << "OnPassphraseRequired sent because cryptographer is not "
             << "ready";
    FOR_EACH_OBSERVER(SyncEncryptionHandler::Observer, observers_,
                      OnPassphraseRequired(REASON_ENCRYPTION,
                                           sync_pb::EncryptedData()));
  }

  // Check if the current local encryption state is stricter/newer than the
  // nigori state. If so, we need to overwrite the nigori node with the local
  // state.
  bool passphrase_type_matches = true;
  if (!is_nigori_migrated) {
    DCHECK(passphrase_type_ == CUSTOM_PASSPHRASE ||
           passphrase_type_ == IMPLICIT_PASSPHRASE);
    passphrase_type_matches =
        nigori.keybag_is_frozen() == IsExplicitPassphrase(passphrase_type_);
  } else {
    passphrase_type_matches =
        (ProtoPassphraseTypeToEnum(nigori.passphrase_type()) ==
             passphrase_type_);
  }
  if (!passphrase_type_matches ||
      nigori.encrypt_everything() != encrypt_everything_ ||
      nigori_types_need_update ||
      nigori_needs_new_keys) {
    DVLOG(1) << "Triggering nigori rewrite.";
    return false;
  }
  return true;
}

void SyncEncryptionHandlerImpl::RewriteNigori() {
  DVLOG(1) << "Writing local encryption state into nigori.";
  DCHECK(thread_checker_.CalledOnValidThread());
  WriteTransaction trans(FROM_HERE, user_share_);
  WriteEncryptionStateToNigori(&trans);
}

void SyncEncryptionHandlerImpl::WriteEncryptionStateToNigori(
    WriteTransaction* trans) {
  DCHECK(thread_checker_.CalledOnValidThread());
  WriteNode nigori_node(trans);
  // This can happen in tests that don't have nigori nodes.
  if (nigori_node.InitTypeRoot(NIGORI) != BaseNode::INIT_OK)
    return;

  sync_pb::NigoriSpecifics nigori = nigori_node.GetNigoriSpecifics();
  const Cryptographer& cryptographer =
      UnlockVault(trans->GetWrappedTrans()).cryptographer;

  // Will not do anything if we shouldn't or can't migrate. Otherwise
  // migrates, writing the full encryption state as it does.
  if (!AttemptToMigrateNigoriToKeystore(trans, &nigori_node)) {
    if (cryptographer.is_ready() &&
        nigori_overwrite_count_ < kNigoriOverwriteLimit) {
      // Does not modify the encrypted blob if the unencrypted data already
      // matches what is about to be written.
      sync_pb::EncryptedData original_keys = nigori.encryption_keybag();
      if (!cryptographer.GetKeys(nigori.mutable_encryption_keybag()))
        NOTREACHED();

      if (nigori.encryption_keybag().SerializeAsString() !=
          original_keys.SerializeAsString()) {
        // We've updated the nigori node's encryption keys. In order to prevent
        // a possible looping of two clients constantly overwriting each other,
        // we limit the absolute number of overwrites per client instantiation.
        nigori_overwrite_count_++;
        UMA_HISTOGRAM_COUNTS("Sync.AutoNigoriOverwrites",
                             nigori_overwrite_count_);
      }

      // Note: we don't try to set keybag_is_frozen here since if that
      // is lost the user can always set it again (and we don't want to clobber
      // any migration state). The main goal at this point is to preserve
      // the encryption keys so all data remains decryptable.
    }
    syncable::UpdateNigoriFromEncryptedTypes(
        UnlockVault(trans->GetWrappedTrans()).encrypted_types,
        encrypt_everything_,
        &nigori);
    if (!custom_passphrase_time_.is_null()) {
      nigori.set_custom_passphrase_time(
          TimeToProtoTime(custom_passphrase_time_));
    }

    // If nothing has changed, this is a no-op.
    nigori_node.SetNigoriSpecifics(nigori);
  }
}

bool SyncEncryptionHandlerImpl::UpdateEncryptedTypesFromNigori(
    const sync_pb::NigoriSpecifics& nigori,
    syncable::BaseTransaction* const trans) {
  DCHECK(thread_checker_.CalledOnValidThread());
  ModelTypeSet* encrypted_types = &UnlockVaultMutable(trans)->encrypted_types;
  if (nigori.encrypt_everything()) {
    EnableEncryptEverythingImpl(trans);
    DCHECK(encrypted_types->Equals(EncryptableUserTypes()));
    return true;
  } else if (encrypt_everything_) {
    DCHECK(encrypted_types->Equals(EncryptableUserTypes()));
    return false;
  }

  ModelTypeSet nigori_encrypted_types;
  nigori_encrypted_types = syncable::GetEncryptedTypesFromNigori(nigori);
  nigori_encrypted_types.PutAll(SensitiveTypes());

  // If anything more than the sensitive types were encrypted, and
  // encrypt_everything is not explicitly set to false, we assume it means
  // a client intended to enable encrypt everything.
  if (!nigori.has_encrypt_everything() &&
      !Difference(nigori_encrypted_types, SensitiveTypes()).Empty()) {
    if (!encrypt_everything_) {
      encrypt_everything_ = true;
      *encrypted_types = EncryptableUserTypes();
      FOR_EACH_OBSERVER(
          Observer, observers_,
          OnEncryptedTypesChanged(*encrypted_types, encrypt_everything_));
    }
    DCHECK(encrypted_types->Equals(EncryptableUserTypes()));
    return false;
  }

  MergeEncryptedTypes(nigori_encrypted_types, trans);
  return encrypted_types->Equals(nigori_encrypted_types);
}

void SyncEncryptionHandlerImpl::SetCustomPassphrase(
    const std::string& passphrase,
    WriteTransaction* trans,
    WriteNode* nigori_node) {
  DCHECK(thread_checker_.CalledOnValidThread());
  DCHECK(IsNigoriMigratedToKeystore(nigori_node->GetNigoriSpecifics()));
  KeyParams key_params = {"localhost", "dummy", passphrase};

  if (passphrase_type_ != KEYSTORE_PASSPHRASE) {
    DVLOG(1) << "Failing to set a custom passphrase because one has already "
             << "been set.";
    FinishSetPassphrase(false, std::string(), trans, nigori_node);
    return;
  }

  Cryptographer* cryptographer =
      &UnlockVaultMutable(trans->GetWrappedTrans())->cryptographer;
  if (cryptographer->has_pending_keys()) {
    // This theoretically shouldn't happen, because the only way to have pending
    // keys after migrating to keystore support is if a custom passphrase was
    // set, which should update passpshrase_state_ and should be caught by the
    // if statement above. For the sake of safety though, we check for it in
    // case a client is misbehaving.
    LOG(ERROR) << "Failing to set custom passphrase because of pending keys.";
    FinishSetPassphrase(false, std::string(), trans, nigori_node);
    return;
  }

  std::string bootstrap_token;
  if (cryptographer->AddKey(key_params)) {
    DVLOG(1) << "Setting custom passphrase.";
    cryptographer->GetBootstrapToken(&bootstrap_token);
    passphrase_type_ = CUSTOM_PASSPHRASE;
    custom_passphrase_time_ = base::Time::Now();
    FOR_EACH_OBSERVER(SyncEncryptionHandler::Observer, observers_,
                            OnPassphraseTypeChanged(
                                passphrase_type_,
                                GetExplicitPassphraseTime()));
  } else {
    NOTREACHED() << "Failed to add key to cryptographer.";
    return;
  }
  FinishSetPassphrase(true, bootstrap_token, trans, nigori_node);
}

void SyncEncryptionHandlerImpl::DecryptPendingKeysWithExplicitPassphrase(
    const std::string& passphrase,
    WriteTransaction* trans,
    WriteNode* nigori_node) {
  DCHECK(thread_checker_.CalledOnValidThread());
  DCHECK(IsExplicitPassphrase(passphrase_type_));
  KeyParams key_params = {"localhost", "dummy", passphrase};

  Cryptographer* cryptographer =
      &UnlockVaultMutable(trans->GetWrappedTrans())->cryptographer;
  if (!cryptographer->has_pending_keys()) {
    // Note that this *can* happen in a rare situation where data is
    // re-encrypted on another client while a SetDecryptionPassphrase() call is
    // in-flight on this client. It is rare enough that we choose to do nothing.
    NOTREACHED() << "Attempt to set decryption passphrase failed because there "
                 << "were no pending keys.";
    return;
  }

  DCHECK(IsExplicitPassphrase(passphrase_type_));
  bool success = false;
  std::string bootstrap_token;
  if (cryptographer->DecryptPendingKeys(key_params)) {
    DVLOG(1) << "Explicit passphrase accepted for decryption.";
    cryptographer->GetBootstrapToken(&bootstrap_token);
    success = true;
  } else {
    DVLOG(1) << "Explicit passphrase failed to decrypt.";
    success = false;
  }
  if (success && !keystore_key_.empty()) {
    // Should already be part of the encryption keybag, but we add it just
    // in case.
    KeyParams key_params = {"localhost", "dummy", keystore_key_};
    cryptographer->AddNonDefaultKey(key_params);
  }
  FinishSetPassphrase(success, bootstrap_token, trans, nigori_node);
}

void SyncEncryptionHandlerImpl::FinishSetPassphrase(
    bool success,
    const std::string& bootstrap_token,
    WriteTransaction* trans,
    WriteNode* nigori_node) {
  DCHECK(thread_checker_.CalledOnValidThread());
  FOR_EACH_OBSERVER(
      SyncEncryptionHandler::Observer,
      observers_,
      OnCryptographerStateChanged(
          &UnlockVaultMutable(trans->GetWrappedTrans())->cryptographer));

  // It's possible we need to change the bootstrap token even if we failed to
  // set the passphrase (for example if we need to preserve the new GAIA
  // passphrase).
  if (!bootstrap_token.empty()) {
    DVLOG(1) << "Passphrase bootstrap token updated.";
    FOR_EACH_OBSERVER(SyncEncryptionHandler::Observer, observers_,
                      OnBootstrapTokenUpdated(bootstrap_token,
                                              PASSPHRASE_BOOTSTRAP_TOKEN));
  }

  const Cryptographer& cryptographer =
      UnlockVault(trans->GetWrappedTrans()).cryptographer;
  if (!success) {
    if (cryptographer.is_ready()) {
      LOG(ERROR) << "Attempt to change passphrase failed while cryptographer "
                 << "was ready.";
    } else if (cryptographer.has_pending_keys()) {
      FOR_EACH_OBSERVER(SyncEncryptionHandler::Observer, observers_,
                        OnPassphraseRequired(REASON_DECRYPTION,
                                             cryptographer.GetPendingKeys()));
    } else {
      FOR_EACH_OBSERVER(SyncEncryptionHandler::Observer, observers_,
                        OnPassphraseRequired(REASON_ENCRYPTION,
                                             sync_pb::EncryptedData()));
    }
    return;
  }
  DCHECK(success);
  DCHECK(cryptographer.is_ready());

  // Will do nothing if we're already properly migrated or unable to migrate
  // (in otherwords, if ShouldTriggerMigration is false).
  // Otherwise will update the nigori node with the current migrated state,
  // writing all encryption state as it does.
  if (!AttemptToMigrateNigoriToKeystore(trans, nigori_node)) {
    sync_pb::NigoriSpecifics nigori(nigori_node->GetNigoriSpecifics());
    // Does not modify nigori.encryption_keybag() if the original decrypted
    // data was the same.
    if (!cryptographer.GetKeys(nigori.mutable_encryption_keybag()))
      NOTREACHED();
    if (IsNigoriMigratedToKeystore(nigori)) {
      DCHECK(keystore_key_.empty() || IsExplicitPassphrase(passphrase_type_));
      DVLOG(1) << "Leaving nigori migration state untouched after setting"
               << " passphrase.";
    } else {
      nigori.set_keybag_is_frozen(
          IsExplicitPassphrase(passphrase_type_));
    }
    // If we set a new custom passphrase, store the timestamp.
    if (!custom_passphrase_time_.is_null()) {
      nigori.set_custom_passphrase_time(
          TimeToProtoTime(custom_passphrase_time_));
    }
    nigori_node->SetNigoriSpecifics(nigori);
  }

  // Must do this after OnPassphraseTypeChanged, in order to ensure the PSS
  // checks the passphrase state after it has been set.
  FOR_EACH_OBSERVER(SyncEncryptionHandler::Observer, observers_,
                    OnPassphraseAccepted());

  // Does nothing if everything is already encrypted.
  // TODO(zea): If we just migrated and enabled encryption, this will be
  // redundant. Figure out a way to not do this unnecessarily.
  ReEncryptEverything(trans);
}

void SyncEncryptionHandlerImpl::MergeEncryptedTypes(
    ModelTypeSet new_encrypted_types,
    syncable::BaseTransaction* const trans) {
  DCHECK(thread_checker_.CalledOnValidThread());

  // Only UserTypes may be encrypted.
  DCHECK(EncryptableUserTypes().HasAll(new_encrypted_types));

  ModelTypeSet* encrypted_types = &UnlockVaultMutable(trans)->encrypted_types;
  if (!encrypted_types->HasAll(new_encrypted_types)) {
    *encrypted_types = new_encrypted_types;
    FOR_EACH_OBSERVER(
        Observer, observers_,
        OnEncryptedTypesChanged(*encrypted_types, encrypt_everything_));
  }
}

SyncEncryptionHandlerImpl::Vault* SyncEncryptionHandlerImpl::UnlockVaultMutable(
    syncable::BaseTransaction* const trans) {
  DCHECK_EQ(user_share_->directory.get(), trans->directory());
  return &vault_unsafe_;
}

const SyncEncryptionHandlerImpl::Vault& SyncEncryptionHandlerImpl::UnlockVault(
    syncable::BaseTransaction* const trans) const {
  DCHECK_EQ(user_share_->directory.get(), trans->directory());
  return vault_unsafe_;
}

bool SyncEncryptionHandlerImpl::ShouldTriggerMigration(
    const sync_pb::NigoriSpecifics& nigori,
    const Cryptographer& cryptographer) const {
  DCHECK(thread_checker_.CalledOnValidThread());
  // Don't migrate if there are pending encryption keys (because data
  // encrypted with the pending keys will not be decryptable).
  if (cryptographer.has_pending_keys())
    return false;
  if (IsNigoriMigratedToKeystore(nigori)) {
    // If the nigori is already migrated but does not reflect the explicit
    // passphrase state, remigrate. Similarly, if the nigori has an explicit
    // passphrase but does not have full encryption, or the nigori has an
    // implicit passphrase but does have full encryption, re-migrate.
    // Note that this is to defend against other clients without keystore
    // encryption enabled transitioning to states that are no longer valid.
    if (passphrase_type_ != KEYSTORE_PASSPHRASE &&
        nigori.passphrase_type() ==
            sync_pb::NigoriSpecifics::KEYSTORE_PASSPHRASE) {
      return true;
    } else if (IsExplicitPassphrase(passphrase_type_) &&
               !encrypt_everything_) {
      return true;
    } else if (passphrase_type_ == KEYSTORE_PASSPHRASE &&
               encrypt_everything_) {
      return true;
    } else if (
        cryptographer.is_ready() &&
        !cryptographer.CanDecryptUsingDefaultKey(nigori.encryption_keybag())) {
      // We need to overwrite the keybag. This might involve overwriting the
      // keystore decryptor too.
      return true;
    } else if (old_keystore_keys_.size() > 0 && !keystore_key_.empty()) {
      // Check to see if a server key rotation has happened, but the nigori
      // node's keys haven't been rotated yet, and hence we should re-migrate.
      // Note that once a key rotation has been performed, we no longer
      // preserve backwards compatibility, and the keybag will therefore be
      // encrypted with the current keystore key.
      Cryptographer temp_cryptographer(cryptographer.encryptor());
      KeyParams keystore_params = {"localhost", "dummy", keystore_key_};
      temp_cryptographer.AddKey(keystore_params);
      if (!temp_cryptographer.CanDecryptUsingDefaultKey(
              nigori.encryption_keybag())) {
        return true;
      }
    }
    return false;
  } else if (keystore_key_.empty()) {
    // If we haven't already migrated, we don't want to do anything unless
    // a keystore key is available (so that those clients without keystore
    // encryption enabled aren't forced into new states, e.g. frozen implicit
    // passphrase).
    return false;
  }
  return true;
}

bool SyncEncryptionHandlerImpl::AttemptToMigrateNigoriToKeystore(
    WriteTransaction* trans,
    WriteNode* nigori_node) {
  DCHECK(thread_checker_.CalledOnValidThread());
  const sync_pb::NigoriSpecifics& old_nigori =
      nigori_node->GetNigoriSpecifics();
  Cryptographer* cryptographer =
      &UnlockVaultMutable(trans->GetWrappedTrans())->cryptographer;

  if (!ShouldTriggerMigration(old_nigori, *cryptographer))
    return false;

  DVLOG(1) << "Starting nigori migration to keystore support.";
  sync_pb::NigoriSpecifics migrated_nigori(old_nigori);

  PassphraseType new_passphrase_type = passphrase_type_;
  bool new_encrypt_everything = encrypt_everything_;
  if (encrypt_everything_ && !IsExplicitPassphrase(passphrase_type_)) {
    DVLOG(1) << "Switching to frozen implicit passphrase due to already having "
             << "full encryption.";
    new_passphrase_type = FROZEN_IMPLICIT_PASSPHRASE;
    migrated_nigori.clear_keystore_decryptor_token();
  } else if (IsExplicitPassphrase(passphrase_type_)) {
    DVLOG_IF(1, !encrypt_everything_) << "Enabling encrypt everything due to "
                                      << "explicit passphrase";
    new_encrypt_everything = true;
    migrated_nigori.clear_keystore_decryptor_token();
  } else {
    DCHECK(!encrypt_everything_);
    new_passphrase_type = KEYSTORE_PASSPHRASE;
    DVLOG(1) << "Switching to keystore passphrase state.";
  }
  migrated_nigori.set_encrypt_everything(new_encrypt_everything);
  migrated_nigori.set_passphrase_type(
      EnumPassphraseTypeToProto(new_passphrase_type));
  migrated_nigori.set_keybag_is_frozen(true);

  if (!keystore_key_.empty()) {
    KeyParams key_params = {"localhost", "dummy", keystore_key_};
    if ((old_keystore_keys_.size() > 0 &&
         new_passphrase_type == KEYSTORE_PASSPHRASE) ||
        !cryptographer->is_initialized()) {
      // Either at least one key rotation has been performed, so we no longer
      // care about backwards compatibility, or we're generating keystore-based
      // encryption keys without knowing the GAIA password (and therefore the
      // cryptographer is not initialized), so we can't support backwards
      // compatibility. Ensure the keystore key is the default key.
      DVLOG(1) << "Migrating keybag to keystore key.";
      bool cryptographer_was_ready = cryptographer->is_ready();
      if (!cryptographer->AddKey(key_params)) {
        LOG(ERROR) << "Failed to add keystore key as default key";
        UMA_HISTOGRAM_ENUMERATION("Sync.AttemptNigoriMigration",
                                  FAILED_TO_SET_DEFAULT_KEYSTORE,
                                  MIGRATION_RESULT_SIZE);
        return false;
      }
      if (!cryptographer_was_ready && cryptographer->is_ready()) {
        FOR_EACH_OBSERVER(
            SyncEncryptionHandler::Observer,
            observers_,
            OnPassphraseAccepted());
      }
    } else {
      // We're in backwards compatible mode -- either the account has an
      // explicit passphrase, or we want to preserve the current GAIA-based key
      // as the default because we can (there have been no key rotations since
      // the migration).
      DVLOG(1) << "Migrating keybag while preserving old key";
      if (!cryptographer->AddNonDefaultKey(key_params)) {
        LOG(ERROR) << "Failed to add keystore key as non-default key.";
        UMA_HISTOGRAM_ENUMERATION("Sync.AttemptNigoriMigration",
                                  FAILED_TO_SET_NONDEFAULT_KEYSTORE,
                                  MIGRATION_RESULT_SIZE);
        return false;
      }
    }
  }
  if (!old_keystore_keys_.empty()) {
    // Go through and add all the old keystore keys as non default keys, so
    // they'll be preserved in the encryption_keybag when we next write the
    // nigori node.
    for (std::vector<std::string>::const_iterator iter =
             old_keystore_keys_.begin(); iter != old_keystore_keys_.end();
         ++iter) {
      KeyParams key_params = {"localhost", "dummy", *iter};
      cryptographer->AddNonDefaultKey(key_params);
    }
  }
  if (new_passphrase_type == KEYSTORE_PASSPHRASE &&
      !GetKeystoreDecryptor(
          *cryptographer,
          keystore_key_,
          migrated_nigori.mutable_keystore_decryptor_token())) {
    LOG(ERROR) << "Failed to extract keystore decryptor token.";
    UMA_HISTOGRAM_ENUMERATION("Sync.AttemptNigoriMigration",
                              FAILED_TO_EXTRACT_DECRYPTOR,
                              MIGRATION_RESULT_SIZE);
    return false;
  }
  if (!cryptographer->GetKeys(migrated_nigori.mutable_encryption_keybag())) {
    LOG(ERROR) << "Failed to extract encryption keybag.";
    UMA_HISTOGRAM_ENUMERATION("Sync.AttemptNigoriMigration",
                              FAILED_TO_EXTRACT_KEYBAG,
                              MIGRATION_RESULT_SIZE);
    return false;
  }

  if (migration_time_.is_null())
    migration_time_ = base::Time::Now();
  migrated_nigori.set_keystore_migration_time(TimeToProtoTime(migration_time_));

  if (!custom_passphrase_time_.is_null()) {
    migrated_nigori.set_custom_passphrase_time(
        TimeToProtoTime(custom_passphrase_time_));
  }

  FOR_EACH_OBSERVER(
      SyncEncryptionHandler::Observer,
      observers_,
      OnCryptographerStateChanged(cryptographer));
  if (passphrase_type_ != new_passphrase_type) {
    passphrase_type_ = new_passphrase_type;
    FOR_EACH_OBSERVER(SyncEncryptionHandler::Observer, observers_,
                            OnPassphraseTypeChanged(
                                passphrase_type_,
                                GetExplicitPassphraseTime()));
  }

  if (new_encrypt_everything && !encrypt_everything_) {
    EnableEncryptEverythingImpl(trans->GetWrappedTrans());
    ReEncryptEverything(trans);
  } else if (!cryptographer->CanDecryptUsingDefaultKey(
                 old_nigori.encryption_keybag())) {
    DVLOG(1) << "Rencrypting everything due to key rotation.";
    ReEncryptEverything(trans);
  }

  DVLOG(1) << "Completing nigori migration to keystore support.";
  nigori_node->SetNigoriSpecifics(migrated_nigori);

  switch (new_passphrase_type) {
    case KEYSTORE_PASSPHRASE:
      if (old_keystore_keys_.size() > 0) {
        UMA_HISTOGRAM_ENUMERATION("Sync.AttemptNigoriMigration",
                                  MIGRATION_SUCCESS_KEYSTORE_NONDEFAULT,
                                  MIGRATION_RESULT_SIZE);
      } else {
        UMA_HISTOGRAM_ENUMERATION("Sync.AttemptNigoriMigration",
                                  MIGRATION_SUCCESS_KEYSTORE_DEFAULT,
                                  MIGRATION_RESULT_SIZE);
      }
      break;
    case FROZEN_IMPLICIT_PASSPHRASE:
      UMA_HISTOGRAM_ENUMERATION("Sync.AttemptNigoriMigration",
                                MIGRATION_SUCCESS_FROZEN_IMPLICIT,
                                MIGRATION_RESULT_SIZE);
      break;
    case CUSTOM_PASSPHRASE:
      UMA_HISTOGRAM_ENUMERATION("Sync.AttemptNigoriMigration",
                                MIGRATION_SUCCESS_CUSTOM,
                                MIGRATION_RESULT_SIZE);
      break;
    default:
      NOTREACHED();
      break;
  }
  return true;
}

bool SyncEncryptionHandlerImpl::GetKeystoreDecryptor(
    const Cryptographer& cryptographer,
    const std::string& keystore_key,
    sync_pb::EncryptedData* encrypted_blob) {
  DCHECK(thread_checker_.CalledOnValidThread());
  DCHECK(!keystore_key.empty());
  DCHECK(cryptographer.is_ready());
  std::string serialized_nigori;
  serialized_nigori = cryptographer.GetDefaultNigoriKeyData();
  if (serialized_nigori.empty()) {
    LOG(ERROR) << "Failed to get cryptographer bootstrap token.";
    return false;
  }
  Cryptographer temp_cryptographer(cryptographer.encryptor());
  KeyParams key_params = {"localhost", "dummy", keystore_key};
  if (!temp_cryptographer.AddKey(key_params))
    return false;
  if (!temp_cryptographer.EncryptString(serialized_nigori, encrypted_blob))
    return false;
  return true;
}

bool SyncEncryptionHandlerImpl::AttemptToInstallKeybag(
    const sync_pb::EncryptedData& keybag,
    bool update_default,
    Cryptographer* cryptographer) {
  if (!cryptographer->CanDecrypt(keybag))
    return false;
  cryptographer->InstallKeys(keybag);
  if (update_default)
    cryptographer->SetDefaultKey(keybag.key_name());
  return true;
}

void SyncEncryptionHandlerImpl::EnableEncryptEverythingImpl(
    syncable::BaseTransaction* const trans) {
  ModelTypeSet* encrypted_types = &UnlockVaultMutable(trans)->encrypted_types;
  if (encrypt_everything_) {
    DCHECK(encrypted_types->Equals(EncryptableUserTypes()));
    return;
  }
  encrypt_everything_ = true;
  *encrypted_types = EncryptableUserTypes();
  FOR_EACH_OBSERVER(
      Observer, observers_,
      OnEncryptedTypesChanged(*encrypted_types, encrypt_everything_));
}

bool SyncEncryptionHandlerImpl::DecryptPendingKeysWithKeystoreKey(
    const std::string& keystore_key,
    const sync_pb::EncryptedData& keystore_decryptor_token,
    Cryptographer* cryptographer) {
  DCHECK(cryptographer->has_pending_keys());
  if (keystore_decryptor_token.blob().empty())
    return false;
  Cryptographer temp_cryptographer(cryptographer->encryptor());

  // First, go through and all all the old keystore keys to the temporary
  // cryptographer.
  for (size_t i = 0; i < old_keystore_keys_.size(); ++i) {
    KeyParams old_key_params = {"localhost", "dummy", old_keystore_keys_[i]};
    temp_cryptographer.AddKey(old_key_params);
  }

  // Then add the current keystore key as the default key and see if we can
  // decrypt.
  KeyParams keystore_params = {"localhost", "dummy", keystore_key_};
  if (temp_cryptographer.AddKey(keystore_params) &&
      temp_cryptographer.CanDecrypt(keystore_decryptor_token)) {
    // Someone else migrated the nigori for us! How generous! Go ahead and
    // install both the keystore key and the new default encryption key
    // (i.e. the one provided by the keystore decryptor token) into the
    // cryptographer.
    // The keystore decryptor token is a keystore key encrypted blob containing
    // the current serialized default encryption key (and as such should be
    // able to decrypt the nigori node's encryption keybag).
    // Note: it's possible a key rotation has happened since the migration, and
    // we're decrypting using an old keystore key. In that case we need to
    // ensure we re-encrypt using the newest key.
    DVLOG(1) << "Attempting to decrypt pending keys using "
             << "keystore decryptor token.";
    std::string serialized_nigori =
        temp_cryptographer.DecryptToString(keystore_decryptor_token);

    // This will decrypt the pending keys and add them if possible. The key
    // within |serialized_nigori| will be the default after.
    cryptographer->ImportNigoriKey(serialized_nigori);

    if (!temp_cryptographer.CanDecryptUsingDefaultKey(
            keystore_decryptor_token)) {
      // The keystore decryptor token was derived from an old keystore key.
      // A key rotation is necessary, so set the current keystore key as the
      // default key (which will trigger a re-migration).
      DVLOG(1) << "Pending keys based on old keystore key. Setting newest "
               << "keystore key as default.";
      cryptographer->AddKey(keystore_params);
    } else {
      // Theoretically the encryption keybag should already contain the keystore
      // key. We explicitly add it as a safety measure.
      DVLOG(1) << "Pending keys based on newest keystore key.";
      cryptographer->AddNonDefaultKey(keystore_params);
    }
    if (cryptographer->is_ready()) {
      std::string bootstrap_token;
      cryptographer->GetBootstrapToken(&bootstrap_token);
      DVLOG(1) << "Keystore decryptor token decrypted pending keys.";
      FOR_EACH_OBSERVER(
          SyncEncryptionHandler::Observer,
          observers_,
          OnPassphraseAccepted());
      FOR_EACH_OBSERVER(
          SyncEncryptionHandler::Observer,
          observers_,
          OnBootstrapTokenUpdated(bootstrap_token,
                                  PASSPHRASE_BOOTSTRAP_TOKEN));
      FOR_EACH_OBSERVER(
          SyncEncryptionHandler::Observer,
          observers_,
          OnCryptographerStateChanged(cryptographer));
      return true;
    }
  }
  return false;
}

base::Time SyncEncryptionHandlerImpl::GetExplicitPassphraseTime() const {
  if (passphrase_type_ == FROZEN_IMPLICIT_PASSPHRASE)
    return migration_time();
  else if (passphrase_type_ == CUSTOM_PASSPHRASE)
    return custom_passphrase_time();
  return base::Time();
}

}  // namespace browser_sync
