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

#include <openssl/aes.h>
#include <openssl/bn.h>
#include <openssl/ec.h>
#include <openssl/ecdsa.h>
#include <openssl/evp.h>
#include <openssl/obj_mac.h>
#include <openssl/ossl_typ.h>
#include <openssl/rand.h>
#include <openssl/rsa.h>
#include <openssl/x509.h>

#include <stddef.h>
#include <climits>
#include <cstdint>
#include <memory>
#include <string>

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

using std::unique_ptr;

class EvpKeyPtr : public std::unique_ptr<EVP_PKEY, void (*)(EVP_PKEY *)> {
 public:
  explicit EvpKeyPtr(EVP_PKEY *pkp)
      : std::unique_ptr<EVP_PKEY, void (*)(EVP_PKEY *)>(pkp, EVP_PKEY_free) {}
};

namespace securemessage {

static unique_ptr<ByteBuffer> PublicKeyToBytes(EC_KEY *eckey) {
  int pub_key_len = i2d_EC_PUBKEY(eckey, NULL);
  if (pub_key_len <= 0) {
    Util::LogError("Unexpected pub key length for generated key");
    return nullptr;
  }

  unsigned char *pub_key_buffer = NULL;
  int return_code = i2d_EC_PUBKEY(eckey, &pub_key_buffer);
  if (return_code != pub_key_len) {
    if (pub_key_buffer != NULL) {
      free(pub_key_buffer);
    }
    Util::LogErrorAndAbort("i2d_EC_PUBKEY returned an unexpected value");
    return nullptr;
  }

  auto public_key_bytes = unique_ptr<ByteBuffer>(new ByteBuffer(
      pub_key_buffer, pub_key_len));
  free(pub_key_buffer);
  return public_key_bytes;
}

// Create an EVP_PKEY structure using exported data for a private key.
static EvpKeyPtr CreateEvpPrivateKey(const CryptoOps::PrivateKey& key) {
  // Extract key from storage.
  const unsigned char *stored_priv_key = key.data().ImmutableUChar();
  PKCS8_PRIV_KEY_INFO *extracted_pkcs8 =
      d2i_PKCS8_PRIV_KEY_INFO(NULL, &stored_priv_key, key.data().size());
  if (extracted_pkcs8 == NULL) {
    Util::LogError("could not extract pkcs8 key");
    return EvpKeyPtr(NULL);
  }

  // Put it into an EVP structure.
  EvpKeyPtr extracted_evpkey(EVP_PKCS82PKEY(extracted_pkcs8));
  // Careful to free this before we return null anywhere.
  PKCS8_PRIV_KEY_INFO_free(extracted_pkcs8);

  if (extracted_evpkey.get() == NULL) {
    Util::LogError("could not stuff extracted key into evp structure");
    return EvpKeyPtr(NULL);
  }

  return extracted_evpkey;
}

// Create an EVP_PKEY structure using exported data for a public key.
static EvpKeyPtr CreateEvpPublicKey(const CryptoOps::PublicKey& key) {
  const unsigned char *pub_key_ptr = key.data().ImmutableUChar();
  EvpKeyPtr extracted_public_evpkey(
      d2i_PUBKEY(NULL, &pub_key_ptr, key.data().size()));

  if (extracted_public_evpkey == nullptr) {
    Util::LogError("could not import public key");
    return EvpKeyPtr(NULL);
  }

  return extracted_public_evpkey;
}

unique_ptr<ByteBuffer> CryptoOps::Sha256(const ByteBuffer& message) {
  if (message.size() == 0) {
    Util::LogError("Message too short");
    return nullptr;
  }

  // Create an empty digest with enough space. OpenSSL will tell us how much it
  // actually wrote.
  uint8_t md_value[EVP_MAX_MD_SIZE];
  unsigned int md_length = 0;
  int return_code;

  // Create a new message digest context and initialize it
  unique_ptr<EVP_MD_CTX, void (*)(EVP_MD_CTX *)> mdctx(EVP_MD_CTX_create(),
                                                       EVP_MD_CTX_destroy);

  // Initialize the digest context
  return_code = EVP_DigestInit_ex(mdctx.get(), EVP_sha256(), NULL);
  if (return_code != 1) {
    Util::LogErrorAndAbort("Could not initialize SHA256");
    return nullptr;
  }

  // Set the message
  return_code = EVP_DigestUpdate(mdctx.get(), message.ImmutableUInt8(),
                                 message.size());
  if (return_code != 1) {
    Util::LogErrorAndAbort("Could not set message to hash in SHA256");
    return nullptr;
  }

  // Execute the digest
  return_code = EVP_DigestFinal_ex(mdctx.get(), md_value, &md_length);
  if (return_code != 1) {
    Util::LogErrorAndAbort("Could not set execute SHA256");
    return nullptr;
  }

  return unique_ptr<ByteBuffer>(new ByteBuffer(md_value, md_length));
}

unique_ptr<ByteBuffer> CryptoOps::Sha256hmac(const ByteBuffer& key,
                                             const ByteBuffer& message) {
  // Sanity check
  if (key.size() == 0 || message.size() == 0) {
    Util::LogError("Hmac key or message too short");
    return nullptr;
  }

  // Overflow check because of EVP_PKEY_new_mac_key function signature
  if (key.size() > INT_MAX) {
    Util::LogError("Key too big");
    return nullptr;
  }

  // Create an empty digest with enough space. OpenSSL will tell us how much it
  // actually wrote.
  uint8_t md_value[kSha256DigestSize];
  size_t md_length = 0;

  int return_code;  // Used to check all of OpenSSL's return codes

  // Create the HMAC key structure
  EvpKeyPtr hmacKey(
      EVP_PKEY_new_mac_key(EVP_PKEY_HMAC, NULL, key.ImmutableUInt8(),
                           static_cast<int>(key.size())));
  if (hmacKey.get() == NULL) {
    Util::LogErrorAndAbort("Could not create HMAC PKEY");
    return nullptr;
  }

  // Create a new message digest context and initialize it
  unique_ptr<EVP_MD_CTX, void (*)(EVP_MD_CTX *)> mdctx(EVP_MD_CTX_create(),
                                                       EVP_MD_CTX_destroy);
  return_code =
      EVP_DigestSignInit(mdctx.get(), NULL, EVP_sha256(), NULL, hmacKey.get());
  if (return_code != 1) {
    Util::LogErrorAndAbort("Could not initialize HMAC");
    return nullptr;
  }

  // Set the message to digest
  return_code = EVP_DigestSignUpdate(mdctx.get(), message.ImmutableUInt8(),
                                     message.size());
  if (return_code != 1) {
    Util::LogErrorAndAbort("Could not set data to HMAC");
    return nullptr;
  }

  // Compute the digest length and populate the md_length value.  This lets us
  // sanity check the expected digest length.
  return_code = EVP_DigestSignFinal(mdctx.get(), NULL, &md_length);
  if (return_code != 1) {
    Util::LogErrorAndAbort("Could not determine HMAC length");
    return nullptr;
  }
  if (md_length != kSha256DigestSize) {
    Util::LogErrorAndAbort("HMAC returned an unexpected result");
    return nullptr;
  }

  // Finally, compute the digest.
  return_code = EVP_DigestSignFinal(mdctx.get(), md_value, &md_length);
  if (return_code != 1) {
    Util::LogErrorAndAbort("Could not execute HMAC");
    return nullptr;
  }

  return unique_ptr<ByteBuffer>(new ByteBuffer(md_value, kSha256DigestSize));
}

unique_ptr<ByteBuffer> CryptoOps::Aes256CBCDecrypt(
    const CryptoOps::SecretKey& decryptionKey,
    const ByteBuffer& iv,
    const ByteBuffer& ciphertext) {
  if (decryptionKey.type() != SECRET) {
    Util::LogError("AES Decrypt only works with SECRET keys");
    return nullptr;
  }
  if (decryptionKey.algorithm() != AES_256_KEY) {
    Util::LogError("AES Decrypt only works with AES 256 keys");
    return nullptr;
  }
  if (decryptionKey.data().size() != kAesKeySize) {
    Util::LogError("AES 256 key should be 32 bytes long");
    return nullptr;
  }
  if (iv.size() != AES_BLOCK_SIZE) {
    Util::LogError("Incorrect IV size");
    return nullptr;
  }
  if (ciphertext.size() > INT_MAX) {
    Util::LogError("Ciphertext too large to decrypt");
    return nullptr;
  }

  ByteBuffer plaintext(ciphertext.size());  // Allocate space for plaintext
  int return_code;                          // OpenSSL error checking

  // Initialize the cipher context
  EVP_CIPHER_CTX ctx;
  EVP_CIPHER_CTX_init(&ctx);
  return_code = EVP_DecryptInit_ex(&ctx, EVP_aes_256_cbc(), NULL,
                                   decryptionKey.data().ImmutableUInt8(),
                                   iv.ImmutableUInt8());
  if (return_code != 1) {
    Util::LogErrorAndAbort("Could not initialize AES decryption");
    return nullptr;
  }

  // Decrypt data
  int plaintext_bytes_written = 0;
  return_code =
      EVP_DecryptUpdate(&ctx,
                        plaintext.MutableUInt8(),
                        &plaintext_bytes_written,
                        ciphertext.ImmutableUInt8(),
                        static_cast<int>(ciphertext.size()));
  if (return_code != 1) {
    Util::LogError("Could not decrypt data using AES");
    EVP_CIPHER_CTX_cleanup(&ctx);
    return nullptr;
  }

  // Handle the last block and padding
  int last_block_bytes_written = 0;
  return_code = EVP_DecryptFinal_ex(
      &ctx, plaintext.MutableUInt8() + plaintext_bytes_written,
      &last_block_bytes_written);
  if (return_code != 1) {
    Util::LogError("Could not decrypt data using AES; likely a padding error");
    EVP_CIPHER_CTX_cleanup(&ctx);
    return nullptr;
  }

  // Check that the correct number of bytes were written
  if (plaintext_bytes_written > INT_MAX - last_block_bytes_written ||
      static_cast<size_t>(plaintext_bytes_written + last_block_bytes_written) >
          plaintext.size()) {
    Util::LogErrorAndAbort("Unexpected amount of bytes written by AES Encrypt");
    return nullptr;
  }

  // Cleanup
  EVP_CIPHER_CTX_cleanup(&ctx);

  return unique_ptr<ByteBuffer>(
      new ByteBuffer(plaintext.ImmutableUInt8(),
                     plaintext_bytes_written + last_block_bytes_written));
}

unique_ptr<ByteBuffer> CryptoOps::Aes256CBCEncrypt(
    const CryptoOps::SecretKey& encryptionKey,
    const ByteBuffer& iv,
    const ByteBuffer& plaintext) {
  if (encryptionKey.type() != SECRET) {
    Util::LogError("AES Encrypt only works with SECRET keys");
    return nullptr;
  }
  if (encryptionKey.algorithm() != AES_256_KEY) {
    Util::LogError("AES Encrypt only works with AES 256 keys");
    return nullptr;
  }
  if (encryptionKey.data().size() != kAesKeySize) {
    Util::LogError("AES 256 key should be 32 bytes long");
    return nullptr;
  }
  if (iv.size() != AES_BLOCK_SIZE) {
    Util::LogError("Incorrect IV size");
    return nullptr;
  }

  // Calculate PKCS #5 padding size
  size_t padding_size = AES_BLOCK_SIZE - (plaintext.size() % AES_BLOCK_SIZE);

  // Paranoid bounds check to make sure that the static_cast<int> for
  // EVP_EncryptUpdate doesn't cause an overflow
  if (plaintext.size() > INT_MAX) {
    Util::LogError("Plaintext is too large");
    return nullptr;
  }

  // Allocate space for the ciphertext
  unique_ptr<ByteBuffer> ciphertext(
      new ByteBuffer(plaintext.size() + padding_size));

  // Initialize the cipher context
  EVP_CIPHER_CTX ctx;
  EVP_CIPHER_CTX_init(&ctx);
  int return_code = EVP_EncryptInit_ex(&ctx, EVP_aes_256_cbc(), NULL,
                                       encryptionKey.data().ImmutableUInt8(),
                                       iv.ImmutableUInt8());
  if (return_code != 1) {
    Util::LogErrorAndAbort("Could not initialize encryption");
    return nullptr;
  }

  // Encrypt data
  int full_block_bytes_written = 0;
  int last_block_bytes_written = 0;
  return_code = EVP_EncryptUpdate(
      &ctx, ciphertext->MutableUInt8(), &full_block_bytes_written,
      plaintext.ImmutableUInt8(), static_cast<int>(plaintext.size()));
  if (return_code != 1) {
    Util::LogErrorAndAbort("Error during encryption");
    return nullptr;
  }

  return_code = EVP_EncryptFinal_ex(
      &ctx, ciphertext->MutableUInt8() + full_block_bytes_written,
      &last_block_bytes_written);
  if (return_code != 1) {
    Util::LogErrorAndAbort("Error during encryption");
    return nullptr;
  }

  // Check that the correct number of bytes were written
  if (full_block_bytes_written > INT_MAX - last_block_bytes_written ||
      static_cast<size_t>(full_block_bytes_written +
                          last_block_bytes_written) != ciphertext->size()) {
    Util::LogErrorAndAbort("Unexpected amount of bytes written by AES Encrypt");
    return nullptr;
  }

  // Cleanup
  EVP_CIPHER_CTX_cleanup(&ctx);

  return ciphertext;
}

unique_ptr<string> CryptoOps::GenerateIv(EncType encType) {
  unique_ptr<string> iv = nullptr;

  switch (encType) {
    case NONE:
      iv = nullptr;
      break;

    case AES_256_CBC:
      unsigned char iv_bytes[AES_BLOCK_SIZE];

      if (RAND_bytes(iv_bytes, AES_BLOCK_SIZE) != 1) {
        Util::LogError("OpenSSL could not generate random bytes");
        return nullptr;
      }
      iv = Util::MakeUniquePtrString(iv_bytes, AES_BLOCK_SIZE);
      break;

    default:
      // Should never happen
      Util::LogErrorAndAbort("Invalid encryption type");
      return nullptr;
  }

  return iv;
}

unique_ptr<ByteBuffer> CryptoOps::EcdsaP256Sha256Sign(
    const PrivateKey &private_key, const ByteBuffer &data) {
  if (private_key.algorithm() != KeyAlgorithm::ECDSA_KEY ||
      private_key.data().size() == 0 || data.size() == 0) {
    return nullptr;
  }

  // Make sure we don't overflow EVP_SignUpdate
  if (data.size() > UINT_MAX) {
    Util::LogError("Data too big to sign");
    return nullptr;
  }

  EvpKeyPtr extracted_evpkey = CreateEvpPrivateKey(private_key);
  if (extracted_evpkey == nullptr) {
    return nullptr;
  }

  // Create an empty signature buffer with enough space. OpenSSL will tell us
  // how much it actually wrote.
  int maximum_size = EVP_PKEY_size(extracted_evpkey.get());
  if (maximum_size <= 0) {
    Util::LogErrorAndAbort("unexpected max size when computing evp key size");
    return nullptr;
  }

  ByteBuffer signature_buffer(maximum_size);
  unsigned int signature_length = 0;

  // Create a new message digest context and initialize it.
  unique_ptr<EVP_MD_CTX, void (*)(EVP_MD_CTX *)> mdctx(EVP_MD_CTX_create(),
                                                       EVP_MD_CTX_destroy);
  EVP_MD_CTX_init(mdctx.get());
  int return_code = EVP_SignInit_ex(mdctx.get(), EVP_sha256(), NULL);
  if (return_code != 1) {
    Util::LogErrorAndAbort("could not initialize digest context");
    return nullptr;
  }

  // On public signature types, we add salt.
  return_code = EVP_SignUpdate(mdctx.get(), kSalt, sizeof(kSalt));
  if (return_code != 1) {
    Util::LogErrorAndAbort("could not add salt");
    return nullptr;
  }

  // Set the message to sign.
  return_code = EVP_SignUpdate(mdctx.get(), data.ImmutableUChar(),
                               data.size());
  if (return_code != 1) {
    Util::LogErrorAndAbort("could not set data to sign");
    return nullptr;
  }

  // Compute the signature.
  return_code = EVP_SignFinal(mdctx.get(), signature_buffer.MutableUChar(),
                              &signature_length, extracted_evpkey.get());
  if (return_code != 1) {
    Util::LogErrorAndAbort("could not execute signature");
    return nullptr;
  }

  // Verify we got a signature.
  if (signature_length <= 0) {
    Util::LogErrorAndAbort("signature length is too small");
    return nullptr;
  }

  // Verify the signature fits in the buffer.
  if (signature_length > static_cast<unsigned int>(maximum_size)) {
    Util::LogErrorAndAbort("signature buffer is too small");
    return nullptr;
  }

  return unique_ptr<ByteBuffer>(
      new ByteBuffer(signature_buffer.ImmutableUChar(), signature_length));
}

bool CryptoOps::EcdsaP256Sha256Verify(const PublicKey& public_key,
                                      const ByteBuffer& signature,
                                      const ByteBuffer& data) {
  if (public_key.algorithm() != KeyAlgorithm::ECDSA_KEY ||
      public_key.data().size() == 0 || data.size() == 0) {
    return false;
  }

  // Make sure we don't overflow EVP_VerifyUpdate
  if (data.size() > UINT_MAX) {
    Util::LogError("Data too big to verify");
    return nullptr;
  }

  EvpKeyPtr extracted_public_evpkey = CreateEvpPublicKey(public_key);
  if (extracted_public_evpkey == nullptr) {
    return false;
  }

  // Create a verify digest context and initialize it
  unique_ptr<EVP_MD_CTX, void (*)(EVP_MD_CTX *)> verifyctx(EVP_MD_CTX_create(),
                                                           EVP_MD_CTX_destroy);
  EVP_MD_CTX_init(verifyctx.get());
  int return_code = EVP_VerifyInit_ex(verifyctx.get(), EVP_sha256(), NULL);
  if (return_code != 1) {
    Util::LogErrorAndAbort("could not initialize verify digest context");
    return false;
  }

  // On public signatures, we added salt to the signature.
  return_code = EVP_VerifyUpdate(verifyctx.get(), kSalt, sizeof(kSalt));
  if (return_code != 1) {
    Util::LogErrorAndAbort("could not add salt to verify");
    return false;
  }

  // Set the message to verify
  return_code =
      EVP_VerifyUpdate(verifyctx.get(), data.ImmutableUChar(), data.size());
  if (return_code != 1) {
    Util::LogErrorAndAbort("could not set data to verify");
    return false;
  }

  // Verify the signature
  return_code =
      EVP_VerifyFinal(verifyctx.get(), signature.ImmutableUChar(),
                      static_cast<unsigned int>(signature.size()),
                      extracted_public_evpkey.get());

  if (return_code != 1) {
    Util::LogError("could not verify signature");
    return false;
  }

  return true;
}

unique_ptr<ByteBuffer> CryptoOps::EcdhKeyAgreement(
    const PrivateKey& private_key,
    const PublicKey& peer_key) {
  // Shared return code.
  int return_code;

  // Create the private key from the data.
  EvpKeyPtr evp_private_key = CreateEvpPrivateKey(private_key);
  if (evp_private_key == nullptr) {
    return nullptr;
  }

  // Create the public key from the data.
  EvpKeyPtr evp_peer_key = CreateEvpPublicKey(peer_key);
  if (evp_peer_key == nullptr) {
    return nullptr;
  }

  // Create the context for the shared secret derivation.
  unique_ptr<EVP_PKEY_CTX, void (*)(EVP_PKEY_CTX *)> ctx(
      EVP_PKEY_CTX_new(evp_private_key.get(), NULL), EVP_PKEY_CTX_free);
  if (ctx == nullptr) {
    Util::LogErrorAndAbort("could not create ECDH context");
    return nullptr;
  }

  // Initialize.
  return_code = EVP_PKEY_derive_init(ctx.get());
  if (return_code != 1) {
    Util::LogErrorAndAbort("could not initialize context");
    return nullptr;
  }

  // Provide the peer public key.
  return_code = EVP_PKEY_derive_set_peer(ctx.get(), evp_peer_key.get());
  if (return_code != 1) {
    Util::LogErrorAndAbort("could not set peer");
    return nullptr;
  }

  // Determine buffer length for shared secret.
  size_t secret_len;
  return_code = EVP_PKEY_derive(ctx.get(), NULL, &secret_len);
  if (return_code != 1) {
    Util::LogErrorAndAbort("could not determine secret length");
    return nullptr;
  }

  // Create the buffer.
  auto secret = unique_ptr<ByteBuffer>(new ByteBuffer(secret_len));

  // Derive the shared secret.
  return_code = EVP_PKEY_derive(ctx.get(), secret->MutableUChar(),
                                &secret_len);
  if (return_code != 1 || secret_len != secret->size()) {
    Util::LogErrorAndAbort("could not derive secret");
    return nullptr;
  }

  return secret;
}

unique_ptr<ByteBuffer> CryptoOps::Rsa2048Sha256Sign(
    const PrivateKey &private_key, const ByteBuffer &data) {
  if (private_key.algorithm() != KeyAlgorithm::RSA_KEY ||
      private_key.data().size() == 0 || data.size() == 0) {
    return nullptr;
  }

  // Overflow check to make sure we don't overflow EVP_SignUpdate
  if (data.size() > UINT_MAX) {
    Util::LogError("Data too large to sign");
    return nullptr;
  }

  int return_code;
  const uint8_t *key_data = private_key.data().ImmutableUInt8();

  // Import bytes into an RSA key structure
  unique_ptr<RSA, void (*)(RSA *)> rsa_key(
      d2i_RSAPrivateKey(NULL, &key_data, private_key.data().size()), RSA_free);

  if (rsa_key.get() == NULL) {
    Util::LogError("could not re-create rsa key");
    return nullptr;
  }

  // Create an EVP key structure
  EvpKeyPtr rsa_pkey(EVP_PKEY_new());
  if (rsa_pkey.get() == NULL) {
    Util::LogErrorAndAbort("Could not create new EVP_PKEY structure");
    return nullptr;
  }

  // Place the RSA key into the EVP structure
  return_code = EVP_PKEY_set1_RSA(rsa_pkey.get(), rsa_key.get());
  if (return_code != 1) {
    Util::LogErrorAndAbort("Could not set rsa key into pkey");
    return nullptr;
  }

  // Set up a new signature context
  unique_ptr<EVP_MD_CTX, void (*)(EVP_MD_CTX *)> ctx(EVP_MD_CTX_create(),
                                                     EVP_MD_CTX_destroy);
  if (ctx.get() == NULL) {
    Util::LogErrorAndAbort("Could not create signature context");
    return nullptr;
  }

  // Initialize it
  return_code = EVP_SignInit(ctx.get(), EVP_sha256());
  if (return_code != 1) {
    Util::LogErrorAndAbort("Could not initialize context");
    return nullptr;
  }

  // On public signature types, we add salt.
  return_code = EVP_SignUpdate(ctx.get(), kSalt, sizeof(kSalt));
  if (return_code != 1) {
    Util::LogErrorAndAbort("could not add salt");
    return nullptr;
  }

  // Set the message to sign
  return_code = EVP_SignUpdate(ctx.get(), data.ImmutableUChar(),
                               data.size());
  if (return_code != 1) {
    Util::LogErrorAndAbort("could not set data to sign");
    return nullptr;
  }

  // Make space for the signature
  size_t signature_size = EVP_PKEY_size(rsa_pkey.get());
  if (signature_size == 0) {
    Util::LogErrorAndAbort("Invalid signature size");
    return nullptr;
  }
  ByteBuffer signature(signature_size);

  // Perform the signature
  unsigned int bytes_written = 0;
  return_code = EVP_SignFinal(ctx.get(), signature.MutableUInt8(),
                              &bytes_written, rsa_pkey.get());
  if (return_code != 1) {
    Util::LogErrorAndAbort("Error while signing");
    return nullptr;
  }

  return unique_ptr<ByteBuffer>(
      new ByteBuffer(signature.ImmutableUInt8(), bytes_written));
}

bool CryptoOps::Rsa2048Sha256Verify(const PublicKey& public_key,
                                    const ByteBuffer& signature,
                                    const ByteBuffer& data) {
  if (public_key.algorithm() != KeyAlgorithm::RSA_KEY ||
      public_key.data().size() == 0 || data.size() == 0) {
    return nullptr;
  }

  // Make sure we don't overflow EVP_VerifyUpdate
  if (data.size() > UINT_MAX) {
    Util::LogError("Data too big to verify");
    return nullptr;
  }

  int return_code;
  const uint8_t *key_data = public_key.data().ImmutableUInt8();

  // Import bytes into an RSA key structure
  unique_ptr<RSA, void (*)(RSA *)> rsa_public_key(
      d2i_RSA_PUBKEY(NULL, &key_data, public_key.data().size()), RSA_free);
  if (rsa_public_key.get() == NULL) {
    Util::LogErrorAndAbort(
        "could not import bytes into RSA key object for public key");
    return false;
  }

  // Create an EVP key structure
  EvpKeyPtr rsa_public_pkey(EVP_PKEY_new());
  if (rsa_public_pkey.get() == NULL) {
    Util::LogErrorAndAbort(
        "could not create EVP structure for storing public RSA key");
    return false;
  }

  // Place the RSA key into the EVP structure
  return_code = EVP_PKEY_set1_RSA(rsa_public_pkey.get(), rsa_public_key.get());
  if (return_code != 1) {
    Util::LogErrorAndAbort("could not set RSA public key into EVP structure");
    return false;
  }

  // Create verification context
  unique_ptr<EVP_MD_CTX, void (*)(EVP_MD_CTX *)> verifyctx(EVP_MD_CTX_create(),
                                                           EVP_MD_CTX_destroy);
  EVP_MD_CTX_init(verifyctx.get());

  // Initialize it
  return_code = EVP_VerifyInit_ex(verifyctx.get(), EVP_sha256(), NULL);
  if (return_code != 1) {
    Util::LogErrorAndAbort("could not initialize verify digest context");
    return false;
  }

  // On public signatures, we added salt to the signature.
  return_code = EVP_VerifyUpdate(verifyctx.get(), kSalt, sizeof(kSalt));
  if (return_code != 1) {
    Util::LogErrorAndAbort("could not add salt to verify");
    return false;
  }

  // Set the message to verify
  return_code =
      EVP_VerifyUpdate(verifyctx.get(), data.ImmutableUChar(), data.size());
  if (return_code != 1) {
    Util::LogErrorAndAbort("could not set data to verify");
    return false;
  }

  // Verify the signature
  return_code = EVP_VerifyFinal(verifyctx.get(), signature.ImmutableUChar(),
                                static_cast<unsigned int>(signature.size()),
                                rsa_public_pkey.get());

  if (return_code != 1) {
    Util::LogError("could not verify signature");
    return false;
  }

  return true;
}

unique_ptr<CryptoOps::PublicKey> CryptoOps::ImportEcP256Key(const string& x,
                                                            const string& y) {
  int return_code;  // Used to check all of OpenSSL's return codes

  if (!IsValidEcP256CoordinateEncoding(x) ||
      !IsValidEcP256CoordinateEncoding(y)) {
    Util::LogError("error, invalid key format");
    return nullptr;
  }

  // Generate new ec key structure for the P256 curve
  unique_ptr<EC_KEY, void (*)(EC_KEY *)> eckey(
      EC_KEY_new_by_curve_name(NID_X9_62_prime256v1),
      EC_KEY_free);
  if (eckey.get() == NULL) {
    Util::LogErrorAndAbort("error, couldn't create new key structure");
    return nullptr;
  }

  auto x_data = reinterpret_cast<const unsigned char *>(x.data());
  auto y_data = reinterpret_cast<const unsigned char *>(y.data());

  unique_ptr<BIGNUM, void (*)(BIGNUM *)> x_value(
      BN_bin2bn(x_data, static_cast<unsigned int>(x.length()), NULL),
      BN_free);
  unique_ptr<BIGNUM, void (*)(BIGNUM *)> y_value(
      BN_bin2bn(y_data, static_cast<unsigned int>(y.length()), NULL),
      BN_free);

  return_code = EC_KEY_set_public_key_affine_coordinates(eckey.get(),
                                                         x_value.get(),
                                                         y_value.get());

  if (return_code != 1) {
    Util::LogError("error, couldn't set public key");
    return nullptr;
  }

  unique_ptr<ByteBuffer> public_key_bytes = PublicKeyToBytes(eckey.get());
  if (public_key_bytes == nullptr) {
    Util::LogErrorAndAbort("error, couldn't unwrap public key");
    return nullptr;
  }

  return unique_ptr<PublicKey>(
      new PublicKey(*public_key_bytes, KeyAlgorithm::ECDSA_KEY));
}

bool CryptoOps::ExportEcP256Key(const CryptoOps::PublicKey& key,
                                string *x,
                                string *y) {
  int return_code;  // Used to check all of OpenSSL's return codes

  if (key.algorithm() != ECDSA_KEY) {
    Util::LogError("error, invalid key type");
    return false;
  }

  const unsigned char *pub_key_buffer = key.data().ImmutableUChar();
  unique_ptr<EC_KEY, void (*)(EC_KEY *)> eckey(
      d2i_EC_PUBKEY(NULL, &pub_key_buffer, key.data().size()),
      EC_KEY_free);

  if (eckey.get() == NULL) {
    Util::LogError("error, couldn't import new key structure");
    return false;
  }

  const EC_POINT *ecpoint = EC_KEY_get0_public_key(eckey.get());
  const EC_GROUP *ecgroup = EC_KEY_get0_group(eckey.get());

  if (ecpoint == NULL || ecgroup == NULL) {
    Util::LogErrorAndAbort("error, couldn't get the public key details");
    return false;
  }

  unique_ptr<BIGNUM, void (*)(BIGNUM *)> x_value(
      BN_new(),
      BN_free);
  unique_ptr<BIGNUM, void (*)(BIGNUM *)> y_value(
      BN_new(),
      BN_free);

  return_code = EC_POINT_get_affine_coordinates_GFp(ecgroup,
                                                    ecpoint,
                                                    x_value.get(),
                                                    y_value.get(),
                                                    NULL);

  if (return_code != 1) {
    Util::LogErrorAndAbort("error, could not capture coordinates of key");
    return false;
  }

  ByteBuffer x_bytes(BN_num_bytes(x_value.get()));
  ByteBuffer y_bytes(BN_num_bytes(y_value.get()));
  BN_bn2bin(x_value.get(), x_bytes.MutableUChar());
  BN_bn2bin(y_value.get(), y_bytes.MutableUChar());

  // Make sure the byte format is in two's complement by adding a byte of 0's.
  x_bytes.Prepend(string(1, '\x00'));
  y_bytes.Prepend(string(1, '\x00'));

  if (x != NULL) {
    x->assign(x_bytes.String());
  }
  if (y != NULL) {
    y->assign(y_bytes.String());
  }
  return true;
}

unique_ptr<CryptoOps::PublicKey> CryptoOps::ImportRsa2048Key(const string& n,
                                                             int32_t e) {
  if (!IsValidRsa2048ModulusEncoding(n)) {
    Util::LogError("error, invalid key encoding");
    return nullptr;
  }

  unique_ptr<RSA, void (*)(RSA *)> rsa(RSA_new(), RSA_free);
  if (rsa.get() == NULL) {
    Util::LogErrorAndAbort("error, couldn't create new key structure");
    return nullptr;
  }

  auto n_data = reinterpret_cast<const unsigned char *>(n.data());

  string e_str = Int32BytesToString(e);
  auto e_data = reinterpret_cast<const unsigned char *>(e_str.data());

  unique_ptr<BIGNUM, void (*)(BIGNUM *)> n_value(
      BN_bin2bn(n_data, static_cast<unsigned int>(n.length()), NULL),
      BN_free);
  unique_ptr<BIGNUM, void (*)(BIGNUM *)> e_value(
      BN_bin2bn(e_data, static_cast<unsigned int>(e_str.length()), NULL),
      BN_free);

  rsa->n = n_value.release();
  rsa->e = e_value.release();

  unsigned char *public_key_buffer = NULL;
  int public_key_len = i2d_RSA_PUBKEY(rsa.get(), &public_key_buffer);

  if (public_key_len <= 0) {
    Util::LogErrorAndAbort("invalid public key length");
    return nullptr;
  }

  if (public_key_buffer == NULL) {
    Util::LogErrorAndAbort("couldn't allocate public key buffer");
    return nullptr;
  }

  ByteBuffer public_key_bytes(public_key_buffer, public_key_len);
  free(public_key_buffer);

  return unique_ptr<PublicKey>(
      new PublicKey(public_key_bytes, KeyAlgorithm::RSA_KEY));
}

bool CryptoOps::ExportRsa2048Key(const CryptoOps::PublicKey& key,
                                 string *n,
                                 int32_t *e) {
  if (key.algorithm() != RSA_KEY) {
    Util::LogError("error, invalid key type");
    return false;
  }

  const unsigned char *pub_key_buffer = key.data().ImmutableUChar();
  unique_ptr<RSA, void (*)(RSA *)> rsa(
      d2i_RSA_PUBKEY(NULL, &pub_key_buffer, key.data().size()),
      RSA_free);

  if (rsa.get() == NULL) {
    Util::LogError("error, couldn't import new key structure");
    return false;
  }

  if (rsa->n == NULL || rsa->e == NULL) {
    Util::LogErrorAndAbort("error, couldn't get the public key details");
    return false;
  }

  if (static_cast<size_t>(BN_num_bytes(rsa->e)) > sizeof(*e)) {
    Util::LogErrorAndAbort("error, invalid exponent size");
    return false;
  }

  ByteBuffer n_bytes(BN_num_bytes(rsa->n));
  ByteBuffer e_bytes(BN_num_bytes(rsa->e));

  BN_bn2bin(rsa->n, n_bytes.MutableUChar());
  BN_bn2bin(rsa->e, e_bytes.MutableUChar());

  // Make sure the modulus bytes are in two's complement by ensuring the
  // leading bit is not 1.
  n_bytes.Prepend(string(1, '\x00'));

  int32_t e_int32 = 0;
  if (!StringToInt32Bytes(e_bytes.String(), &e_int32)) {
    Util::LogErrorAndAbort("error, invalid exponent bytes");
    return false;
  }

  if (n != NULL) {
    n->assign(n_bytes.String());
  }

  if (e != NULL) {
    *e = e_int32;
  }
  return true;
}

unique_ptr<CryptoOps::SecretKey> CryptoOps::GenerateAes256SecretKey() {
  size_t key_size_in_bytes = EVP_CIPHER_key_length(EVP_aes_256_cbc());
  ByteBuffer key(key_size_in_bytes);

  if (RAND_bytes(key.MutableUInt8(),
                 static_cast<unsigned int>(key_size_in_bytes)) != 1) {
    Util::LogError(
        "Could not get enough cryptographically secure bytes for key");
    return nullptr;
  }

  return unique_ptr<SecretKey>(
      new SecretKey(key.String(), KeyAlgorithm::AES_256_KEY));
}

unique_ptr<CryptoOps::KeyPair> CryptoOps::GenerateEcP256KeyPair() {
  int return_code;  // Used to check all of OpenSSL's return codes

  // Create a new EVP key structure for the EC key
  EvpKeyPtr ecpkey(EVP_PKEY_new());
  if (ecpkey.get() == NULL) {
    Util::LogErrorAndAbort("Could not create EVP PKEY structure");
    return nullptr;
  }

  // Generate new ec key structure for the P256 curve
  EC_KEY *eckey = EC_KEY_new_by_curve_name(NID_X9_62_prime256v1);
  if (eckey == NULL) {
    Util::LogErrorAndAbort("error, couldn't create new key structure");
    return nullptr;
  }

  // Generate a new key and stick it in the structure
  return_code = EC_KEY_generate_key(eckey);
  if (return_code != 1) {
    Util::LogErrorAndAbort("Couldn't generate new key");
    return nullptr;
  }

  // Assign the EC Key to a EVP PKEY structure
  return_code = EVP_PKEY_assign_EC_KEY(ecpkey.get(), eckey);
  if (return_code != 1) {
    Util::LogErrorAndAbort("Could not assign EC key to EVP structure");
    return nullptr;
  }

  // Convert public key to bytes
  unique_ptr<ByteBuffer> public_key_bytes = PublicKeyToBytes(eckey);
  if (public_key_bytes == nullptr) {
    return nullptr;
  }

  // Convert private key to bytes
  unique_ptr<PKCS8_PRIV_KEY_INFO, void (*)(PKCS8_PRIV_KEY_INFO *)> pkcs8(
      EVP_PKEY2PKCS8(ecpkey.get()), PKCS8_PRIV_KEY_INFO_free);

  if (pkcs8.get() == NULL) {
    Util::LogError("could not convert evp key into pkcs8 key");
    return nullptr;
  }
  int priv_key_len = i2d_PKCS8_PRIV_KEY_INFO(pkcs8.get(), NULL);
  if (priv_key_len <= 0) {
    Util::LogErrorAndAbort("unexpected private key length returned");
    return nullptr;
  }
  unsigned char *priv_key_buffer = NULL;
  return_code = i2d_PKCS8_PRIV_KEY_INFO(pkcs8.get(), &priv_key_buffer);
  if (return_code != priv_key_len) {
    Util::LogErrorAndAbort("wrote an unexpected number of private key bytes");
    return nullptr;
  }
  ByteBuffer private_key_bytes(priv_key_buffer, priv_key_len);
  free(priv_key_buffer);

  return unique_ptr<KeyPair>(
      new KeyPair(unique_ptr<PublicKey>(new PublicKey(
                      *public_key_bytes, KeyAlgorithm::ECDSA_KEY)),
                  unique_ptr<PrivateKey>(new PrivateKey(
                      private_key_bytes, KeyAlgorithm::ECDSA_KEY))));
}

unique_ptr<CryptoOps::KeyPair> CryptoOps::GenerateRsa2048KeyPair() {
  // Create the exponent
  unique_ptr<BIGNUM, void (*)(BIGNUM *)> exp(BN_new(), BN_clear_free);
  if (exp.get() == NULL) {
    Util::LogErrorAndAbort("Could not create new bignum");
    return nullptr;
  }

  int return_code = BN_set_word(exp.get(), RSA_F4);
  if (return_code != 1) {
    Util::LogErrorAndAbort("Error setting exponent");
    return nullptr;
  }

  // Generate a key
  unique_ptr<RSA, void (*)(RSA *)> rsa(RSA_new(), RSA_free);
  if (rsa.get() == NULL) {
    Util::LogErrorAndAbort("Error creating RSA structure");
    return nullptr;
  }

  return_code = RSA_generate_key_ex(rsa.get(), 2048, exp.get(), NULL);
  if (return_code != 1) {
    Util::LogErrorAndAbort("Error generating RSA key");
    return nullptr;
  }

  // Store private key
  unsigned char *private_key_buffer = NULL;
  int private_key_len = i2d_RSAPrivateKey(rsa.get(), &private_key_buffer);
  if (private_key_buffer == NULL) {
    Util::LogErrorAndAbort("couldn't allocate private key buffer");
    return nullptr;
  }

  if (private_key_len <= 0) {
    Util::LogErrorAndAbort(
        "invalid private key length encountered during key generation");
    return nullptr;
  }
  ByteBuffer private_key(private_key_buffer, private_key_len);
  free(private_key_buffer);

  // Store public key
  unsigned char *public_key_buffer = NULL;
  int public_key_len = i2d_RSA_PUBKEY(rsa.get(), &public_key_buffer);
  if (public_key_buffer == NULL) {
    Util::LogErrorAndAbort("couldn't allocate public key buffer");
    return nullptr;
  }

  if (public_key_len <= 0) {
    Util::LogErrorAndAbort("invalid public key length");
    return nullptr;
  }
  ByteBuffer public_key(public_key_buffer, public_key_len);
  free(public_key_buffer);

  return unique_ptr<KeyPair>(new KeyPair(
      unique_ptr<PublicKey>(new PublicKey(public_key, KeyAlgorithm::RSA_KEY)),
      unique_ptr<PrivateKey>(
          new PrivateKey(private_key, KeyAlgorithm::RSA_KEY))));
}

}  // namespace securemessage
