// Copyright (c) 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/util/nigori.h"

#include <sstream>
#include <vector>

#include "base/base64.h"
#include "base/logging.h"
#include "base/strings/string_util.h"
#include "base/sys_byteorder.h"
#include "crypto/encryptor.h"
#include "crypto/hmac.h"
#include "crypto/random.h"
#include "crypto/symmetric_key.h"

using base::Base64Encode;
using base::Base64Decode;
using crypto::Encryptor;
using crypto::HMAC;
using crypto::SymmetricKey;

namespace syncer {

// NigoriStream simplifies the concatenation operation of the Nigori protocol.
class NigoriStream {
 public:
  // Append the big-endian representation of the length of |value| with 32 bits,
  // followed by |value| itself to the stream.
  NigoriStream& operator<<(const std::string& value) {
    uint32 size = base::HostToNet32(value.size());
    stream_.write((char *) &size, sizeof(uint32));
    stream_ << value;
    return *this;
  }

  // Append the big-endian representation of the length of |type| with 32 bits,
  // followed by the big-endian representation of the value of |type|, with 32
  // bits, to the stream.
  NigoriStream& operator<<(const Nigori::Type type) {
    uint32 size = base::HostToNet32(sizeof(uint32));
    stream_.write((char *) &size, sizeof(uint32));
    uint32 value = base::HostToNet32(type);
    stream_.write((char *) &value, sizeof(uint32));
    return *this;
  }

  std::string str() {
    return stream_.str();
  }

 private:
  std::ostringstream stream_;
};

// static
const char Nigori::kSaltSalt[] = "saltsalt";

Nigori::Nigori() {
}

Nigori::~Nigori() {
}

bool Nigori::InitByDerivation(const std::string& hostname,
                              const std::string& username,
                              const std::string& password) {
  NigoriStream salt_password;
  salt_password << username << hostname;

  // Suser = PBKDF2(Username || Servername, "saltsalt", Nsalt, 8)
  scoped_ptr<SymmetricKey> user_salt(SymmetricKey::DeriveKeyFromPassword(
      SymmetricKey::HMAC_SHA1, salt_password.str(),
      kSaltSalt,
      kSaltIterations,
      kSaltKeySizeInBits));
  DCHECK(user_salt.get());

  std::string raw_user_salt;
  if (!user_salt->GetRawKey(&raw_user_salt))
    return false;

  // Kuser = PBKDF2(P, Suser, Nuser, 16)
  user_key_.reset(SymmetricKey::DeriveKeyFromPassword(SymmetricKey::AES,
      password, raw_user_salt, kUserIterations, kDerivedKeySizeInBits));
  DCHECK(user_key_.get());

  // Kenc = PBKDF2(P, Suser, Nenc, 16)
  encryption_key_.reset(SymmetricKey::DeriveKeyFromPassword(SymmetricKey::AES,
      password, raw_user_salt, kEncryptionIterations, kDerivedKeySizeInBits));
  DCHECK(encryption_key_.get());

  // Kmac = PBKDF2(P, Suser, Nmac, 16)
  mac_key_.reset(SymmetricKey::DeriveKeyFromPassword(
      SymmetricKey::HMAC_SHA1, password, raw_user_salt, kSigningIterations,
      kDerivedKeySizeInBits));
  DCHECK(mac_key_.get());

  return user_key_.get() && encryption_key_.get() && mac_key_.get();
}

bool Nigori::InitByImport(const std::string& user_key,
                          const std::string& encryption_key,
                          const std::string& mac_key) {
  user_key_.reset(SymmetricKey::Import(SymmetricKey::AES, user_key));
  DCHECK(user_key_.get());

  encryption_key_.reset(SymmetricKey::Import(SymmetricKey::AES,
                                             encryption_key));
  DCHECK(encryption_key_.get());

  mac_key_.reset(SymmetricKey::Import(SymmetricKey::HMAC_SHA1, mac_key));
  DCHECK(mac_key_.get());

  return user_key_.get() && encryption_key_.get() && mac_key_.get();
}

// Permute[Kenc,Kmac](type || name)
bool Nigori::Permute(Type type, const std::string& name,
                     std::string* permuted) const {
  DCHECK_LT(0U, name.size());

  NigoriStream plaintext;
  plaintext << type << name;

  Encryptor encryptor;
  if (!encryptor.Init(encryption_key_.get(), Encryptor::CBC,
                      std::string(kIvSize, 0)))
    return false;

  std::string ciphertext;
  if (!encryptor.Encrypt(plaintext.str(), &ciphertext))
    return false;

  std::string raw_mac_key;
  if (!mac_key_->GetRawKey(&raw_mac_key))
    return false;

  HMAC hmac(HMAC::SHA256);
  if (!hmac.Init(raw_mac_key))
    return false;

  std::vector<unsigned char> hash(kHashSize);
  if (!hmac.Sign(ciphertext, &hash[0], hash.size()))
    return false;

  std::string output;
  output.assign(ciphertext);
  output.append(hash.begin(), hash.end());

  Base64Encode(output, permuted);
  return true;
}

// Enc[Kenc,Kmac](value)
bool Nigori::Encrypt(const std::string& value, std::string* encrypted) const {
  if (0U >= value.size())
    return false;

  std::string iv;
  crypto::RandBytes(WriteInto(&iv, kIvSize + 1), kIvSize);

  Encryptor encryptor;
  if (!encryptor.Init(encryption_key_.get(), Encryptor::CBC, iv))
    return false;

  std::string ciphertext;
  if (!encryptor.Encrypt(value, &ciphertext))
    return false;

  std::string raw_mac_key;
  if (!mac_key_->GetRawKey(&raw_mac_key))
    return false;

  HMAC hmac(HMAC::SHA256);
  if (!hmac.Init(raw_mac_key))
    return false;

  std::vector<unsigned char> hash(kHashSize);
  if (!hmac.Sign(ciphertext, &hash[0], hash.size()))
    return false;

  std::string output;
  output.assign(iv);
  output.append(ciphertext);
  output.append(hash.begin(), hash.end());

  Base64Encode(output, encrypted);
  return true;
}

bool Nigori::Decrypt(const std::string& encrypted, std::string* value) const {
  std::string input;
  if (!Base64Decode(encrypted, &input))
    return false;

  if (input.size() < kIvSize * 2 + kHashSize)
    return false;

  // The input is:
  // * iv (16 bytes)
  // * ciphertext (multiple of 16 bytes)
  // * hash (32 bytes)
  std::string iv(input.substr(0, kIvSize));
  std::string ciphertext(input.substr(kIvSize,
                                      input.size() - (kIvSize + kHashSize)));
  std::string hash(input.substr(input.size() - kHashSize, kHashSize));

  std::string raw_mac_key;
  if (!mac_key_->GetRawKey(&raw_mac_key))
    return false;

  HMAC hmac(HMAC::SHA256);
  if (!hmac.Init(raw_mac_key))
    return false;

  std::vector<unsigned char> expected(kHashSize);
  if (!hmac.Sign(ciphertext, &expected[0], expected.size()))
    return false;

  if (hash.compare(0, hash.size(),
                   reinterpret_cast<char *>(&expected[0]),
                   expected.size()))
    return false;

  Encryptor encryptor;
  if (!encryptor.Init(encryption_key_.get(), Encryptor::CBC, iv))
    return false;

  if (!encryptor.Decrypt(ciphertext, value))
    return false;

  return true;
}

bool Nigori::ExportKeys(std::string* user_key,
                        std::string* encryption_key,
                        std::string* mac_key) const {
  DCHECK(user_key);
  DCHECK(encryption_key);
  DCHECK(mac_key);

  return user_key_->GetRawKey(user_key) &&
      encryption_key_->GetRawKey(encryption_key) &&
      mac_key_->GetRawKey(mac_key);
}

}  // namespace syncer
