/*
 * Copyright 2014 Google Inc. All rights reserved.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

//
// This file is a partial implementation of the CryptoOps class.  The remaining
// functions are specified in a crypto-library specific continuation (e.g., the
// OpenSSL versions are in cryto_ops_openssl.cc
//

#include <stddef.h>

#include "securemessage/crypto_ops.h"
#include "securemessage/secure_message_wrapper.h"
#include "securemessage/util.h"

using std::unique_ptr;

// Maximum number of bytes in a 2's complement encoding of a NIST P-256 elliptic
// curve point.
static const size_t kMaxP256EncodingBytes = 33;

// Maximum number of bytes in a 2's complement encoding of a 2048 bit RSA
// key modulus.
static const size_t kMaxRsa2048ModulusEncodingBytes = 257;

// The expected byte size of a 2048 bit RSA key modulus. The modulus bit size
// is 8 * |kRsa2048ModulusByteSize|.
static const size_t kRsa2048ModulusByteSize = 256;

// TODO(aczeskis): get rid of as many uses of string as possible and move to
// using ByteBuffer because of secure wipe. If easier and less refactoring,
// make a custom string that wipes memory on deallocation
namespace securemessage {

// We have to initialize salt this way because C++ doesn't allow initialization
// and declaration in the same place... Go figure.
// The value below is SHA256("SecureMessage").  This is tested in the TestSalt
// test in crypto_ops_test
const uint8_t CryptoOps::kSalt[kSaltSize] = {
    0xbf, 0x9d, 0x2a, 0x53, 0xc6, 0x36, 0x16, 0xd7, 0x5d, 0xb0, 0xa7,
    0x16, 0x5b, 0x91, 0xc1, 0xef, 0x73, 0xe5, 0x37, 0xf2, 0x42, 0x74,
    0x05, 0xfa, 0x23, 0x61, 0x0a, 0x4b, 0xe6, 0x57, 0x64, 0x2e};

unique_ptr<ByteBuffer> CryptoOps::HkdfSha256Extract(
    const ByteBuffer& inputKeyMaterial,
    const ByteBuffer& salt) {
  // Computes an HMAC of the inputKeyMaterial keyed with the salt
  unique_ptr<ByteBuffer> result = Sha256hmac(salt, inputKeyMaterial);

  if (result == nullptr) {
    Util::LogError("HMAC returned null");
  }

  return result;
}

unique_ptr<ByteBuffer> CryptoOps::HkdfSha256Expand(
    const ByteBuffer& pseudoRandomKey,
    const ByteBuffer& info) {
  if (pseudoRandomKey.size() == 0) {
    Util::LogError("length of PseudoRandomKey is zero");
    return nullptr;
  }

  // Computes an HMAC of info || 0x01 (where || is concatenation)
  ByteBuffer extendedInfo = info;
  extendedInfo.Append(static_cast<size_t>(1), static_cast<uint8_t>(0x01));
  unique_ptr<ByteBuffer> result = Sha256hmac(pseudoRandomKey, extendedInfo);

  if (result == nullptr) {
    Util::LogError("HMAC returned null");
  }

  return result;
}

unique_ptr<string> CryptoOps::Hkdf(const string& inputKeyMaterial,
                                   const string& salt,
                                   const string& info) {
  unique_ptr<ByteBuffer> extracted_result =
      HkdfSha256Extract(ByteBuffer(inputKeyMaterial), ByteBuffer(salt));
  if (extracted_result == nullptr || extracted_result->size() == 0) {
    Util::LogError("HKDF_Extract returned an invalid result");
    return nullptr;
  }

  unique_ptr<ByteBuffer> expanded_result =
      HkdfSha256Expand(*extracted_result, ByteBuffer(info));

  if (expanded_result == nullptr) {
    Util::LogError("HkdfSha256Expand return an invalid result");
    return nullptr;
  }

  return unique_ptr<string>(new string(expanded_result->String()));
}

unique_ptr<CryptoOps::SecretKey> CryptoOps::DeriveAes256KeyFor(
    const CryptoOps::SecretKey& masterKey, const string& purpose) {
  string key_string(masterKey.data().String());
  string salt_string(reinterpret_cast<const char*>(kSalt), kSaltSize);
  unique_ptr<string> key_data = Hkdf(key_string, salt_string, purpose);

  if (key_data == nullptr || key_data->size() != kAesKeySize) {
    Util::LogError("HKDF returned invalid key");
    return nullptr;
  }

  unique_ptr<CryptoOps::SecretKey> derived_key =
      unique_ptr<CryptoOps::SecretKey>(
          new CryptoOps::SecretKey(*key_data, CryptoOps::AES_256_KEY));
  return derived_key;
}

unique_ptr<string> CryptoOps::Digest(const string& data) {
  unique_ptr<ByteBuffer> full_digest = Sha256(ByteBuffer(data));

  if (full_digest == nullptr || full_digest->size() != kSha256DigestSize) {
    return nullptr;
  }

  return unique_ptr<string>(
      new string(full_digest->SubArray(0, kDigestLength)->String()));
}

unique_ptr<string> CryptoOps::Decrypt(const CryptoOps::SecretKey& decryptionKey,
                                      CryptoOps::EncType encType,
                                      const string& iv,
                                      const string& ciphertext) {
  if (ciphertext.empty()) {
    Util::LogError("Cannot decrypt empty ciphertext");
    return nullptr;
  }
  if (decryptionKey.data().size() == 0) {
    Util::LogError("Cannot decrypt using empty decryption key");
    return nullptr;
  }
  if (iv.empty()) {
    Util::LogError("Cannot decrypt with empty iv");
    return nullptr;
  }

  unique_ptr<ByteBuffer> plaintext = nullptr;

  switch (encType) {
    case NONE: {
      plaintext = nullptr;
      break;
    }
    case AES_256_CBC: {
      unique_ptr<SecretKey> derived_key =
          CryptoOps::DeriveAes256KeyFor(decryptionKey, GetPurpose(encType));
      plaintext = Aes256CBCDecrypt(*derived_key, ByteBuffer(iv),
                                   ByteBuffer(ciphertext));
      break;
    }
    default:
      // This should never happen and might indicate an attack
      Util::LogError("Invalid encryption type");
      return nullptr;
  }

  if (plaintext == nullptr) {
    Util::LogError("Could not decrypt ciphertext");
    return nullptr;
  }

  return unique_ptr<string>(new string(plaintext->String()));
}

unique_ptr<string> CryptoOps::Encrypt(const CryptoOps::SecretKey& encryptionKey,
                                      CryptoOps::EncType encType,
                                      const string& iv,
                                      const string& plaintext) {
  if (encryptionKey.data().size() == 0) {
    Util::LogError("Cannot encrypt using empty encryption key");
    return nullptr;
  }

  unique_ptr<ByteBuffer> ciphertext = nullptr;

  switch (encType) {
    case NONE: {
      ciphertext = nullptr;
      break;
    }
    case AES_256_CBC: {
      unique_ptr<SecretKey> derived_key =
          CryptoOps::DeriveAes256KeyFor(encryptionKey, GetPurpose(encType));
      ciphertext =
          Aes256CBCEncrypt(*derived_key, ByteBuffer(iv), ByteBuffer(plaintext));
      break;
    }
    default:
      // This should never happen and might indicate an attack
      Util::LogError("Invalid encryption type");
      return nullptr;
  }

  if (ciphertext == nullptr) {
    Util::LogError("Could not encrypt plaintext");
    return nullptr;
  }

  return unique_ptr<string>(new string(ciphertext->String()));
}

unique_ptr<CryptoOps::SecretKey> CryptoOps::KeyAgreementSha256(
    const PrivateKey& private_key,
    const PublicKey& peer_key) {
  if (private_key.algorithm() != peer_key.algorithm()) {
    Util::LogError("Algorithms for public and private key must match");
    return nullptr;
  }
  if (private_key.algorithm() != ECDSA_KEY) {
    Util::LogError("Only ECDSA algorithms are supported for Key agreements");
    return nullptr;
  }

  unique_ptr<ByteBuffer> secret = EcdhKeyAgreement(private_key, peer_key);
  if (secret == nullptr) {
    Util::LogError("Error computing key agreement");
    return nullptr;
  }

  unique_ptr<ByteBuffer> secret_digest = Sha256(*secret);
  if (secret_digest == nullptr) {
    Util::LogError("Error computing Sha256");
    return nullptr;
  }

  return unique_ptr<SecretKey>(new SecretKey(*secret_digest, AES_256_KEY));
}

string CryptoOps::GetPurpose(EncType encType) {
  return "ENC:" +
      std::to_string(SecureMessageWrapper::GetEncScheme(encType));
}

string CryptoOps::GetPurpose(SigType sigType) {
  return "SIG:" +
      std::to_string(SecureMessageWrapper::GetSigScheme(sigType));
}

bool CryptoOps::IsPublicKeyScheme(SigType sigType) {
  switch (sigType) {
    case HMAC_SHA256:
      return false;
    case ECDSA_P256_SHA256:
      return true;
    case RSA2048_SHA256:
      return true;
    case SIG_TYPE_END:
      // Exists only for testing, should never actually be called.
      Util::LogErrorAndAbort("wrong sigtype");
  }

  // Control should never reach here, this is here to make the compiler happy
  Util::LogErrorAndAbort("wrong sigtype");
  return false;
}

unique_ptr<string> CryptoOps::Sign(SigType sigType, const Key& signingKey,
                                   const string& data) {
  if (signingKey.data().size() == 0) {
    Util::LogError("Signing Key cannot be empty!");
    return nullptr;
  }
  if (data.length() == 0) {
    Util::LogError("Cannot sign empty data");
    return nullptr;
  }

  unique_ptr<ByteBuffer> signature = nullptr;
  switch (sigType) {
    case HMAC_SHA256: {
      if (signingKey.type() != SECRET) {
        Util::LogError("Invalid signing key type");
        return nullptr;
      }
      unique_ptr<SecretKey> derived_key = DeriveAes256KeyFor(
          SecretKey(signingKey.data(), signingKey.algorithm()),
          GetPurpose(sigType));
      if (derived_key == nullptr) {
        Util::LogError("Invalid derived key");
        return nullptr;
      }
      signature = Sha256hmac(derived_key->data(), ByteBuffer(data));
      break;
    }
    case ECDSA_P256_SHA256: {
      if (signingKey.type() != PRIVATE) {
        Util::LogError("Expected a private key");
        return nullptr;
      }
      signature = EcdsaP256Sha256Sign(
          PrivateKey(signingKey.data(), signingKey.algorithm()),
          ByteBuffer(data));
      break;
    }
    case RSA2048_SHA256: {
      if (signingKey.type() != PRIVATE) {
        Util::LogError("Expected a private key");
        return nullptr;
      }
      signature = Rsa2048Sha256Sign(
          PrivateKey(signingKey.data(), signingKey.algorithm()),
          ByteBuffer(data));
      break;
    }
    case SIG_TYPE_END:
      // Case only exists for testing and is never expected to actually be
      // called.
     Util::LogErrorAndAbort("wrong sigtype");
  }

  if (signature == nullptr) {
    return nullptr;
  } else {
    return unique_ptr<string>(new string(signature->String()));
  }
}

bool CryptoOps::Verify(SigType sigType,
                       const Key& verificationKey,
                       const string& signature,
                       const string& data) {
  // Do some basic checks
  if (verificationKey.data().size() == 0) {
    Util::LogError("Verification Key cannot be empty!");
    return false;
  }
  if (signature.length() == 0) {
    Util::LogError("Signature cannot be empty");
    return false;
  }
  if (data.length() == 0) {
    Util::LogError("Cannot verify signature over empty data");
    return false;
  }

  // Decide what to do based on the signature type
  switch (sigType) {
    case HMAC_SHA256: {
      if (verificationKey.type() != SECRET) {
        Util::LogError("Invalid signing key type");
        return nullptr;
      }
      // Compute expected signature
      unique_ptr<SecretKey> derived_key = DeriveAes256KeyFor(
          SecretKey(verificationKey.data(), verificationKey.algorithm()),
          GetPurpose(sigType));
      if (derived_key == nullptr) {
        Util::LogError("Invalid derived key");
        return false;
      }
      unique_ptr<ByteBuffer> expected_signature =
          Sha256hmac(ByteBuffer(derived_key->data()), ByteBuffer(data));
      if (expected_signature == nullptr) {
        Util::LogError("Invalid expected signature");
        return false;
      }

      // Constant time array comparison
      return expected_signature->Equals(ByteBuffer(signature));
    }

    case ECDSA_P256_SHA256: {
      if (verificationKey.type() != PUBLIC) {
        Util::LogError("Expected a public key");
        return false;
      }
      if (verificationKey.algorithm() != KeyAlgorithm::ECDSA_KEY) {
        Util::LogError("Wrong key type");
        return false;
      }

      return EcdsaP256Sha256Verify(
          PublicKey(verificationKey.data(), verificationKey.algorithm()),
          ByteBuffer(signature), ByteBuffer(data));
    }

    case RSA2048_SHA256: {
      if (verificationKey.type() != PUBLIC) {
        Util::LogError("Expected a public key");
        return false;
      }
      if (verificationKey.algorithm() != KeyAlgorithm::RSA_KEY) {
        Util::LogError("Wrong key type");
        return false;
      }

      return Rsa2048Sha256Verify(
          PublicKey(verificationKey.data(), verificationKey.algorithm()),
          ByteBuffer(signature), ByteBuffer(data));
    }

    default:
      return false;
  }
}

bool CryptoOps::TaggedPlaintextRequired(const Key& signing_key,
                                        SigType sig_type,
                                        const Key& encryption_key) {
  // We need a tag if different keys are being used to "sign" vs. encrypt
  return IsPublicKeyScheme(sig_type) ||
      !signing_key.data().Equals(encryption_key.data());
}

bool CryptoOps::IsValidEcP256CoordinateEncoding(const string& bytes) {
  // The bytes must be between 1 and Max P256 encoding bytes, inclusive. If
  // the bytes are full, then the first byte must not be 0.
  return !(
      (bytes.size() == 0) ||
      (bytes.size() > kMaxP256EncodingBytes) ||
      (bytes.size() == kMaxP256EncodingBytes && bytes.data()[0] != 0));
}

bool CryptoOps::IsValidRsa2048ModulusEncoding(const string& bytes) {
  if (bytes.size() > kMaxRsa2048ModulusEncodingBytes)
    return false;

  if (bytes.size() < kRsa2048ModulusByteSize)
    return false;

  // Index at which the first non-zero byte in |bytes| should be.
  const size_t leading_byte_index = bytes.size() - kRsa2048ModulusByteSize;
  for (size_t i = 0; i < leading_byte_index; ++i) {
    if (bytes[i] != 0)
      return false;
  }

  // Make sure that the first non-zero byte has leading 1.
  return static_cast<uint8_t>(bytes[leading_byte_index]) & 0x80;
}

string CryptoOps::Int32BytesToString(int32_t value) {
  string result(sizeof(value), '\0');
  for (size_t i = sizeof(value); i > 0 && value != 0; --i) {
    result[i - 1] = static_cast<char>(value & 0xFF);
    value >>= 8;
  }
  return result;
}

bool CryptoOps::StringToInt32Bytes(const string& value, int32_t* result) {
  if (value.length() > sizeof(*result))
    return false;

  *result = 0;
  for (size_t i = 0; i < value.length(); ++i) {
    *result <<= 8;
    *result |= static_cast<uint8_t>(value[i]);
  }
  return true;
}

CryptoOps::~CryptoOps() {}

}  // namespace securemessage
