// Copyright 2018 The Chromium OS 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 <cstdint>
#include <cstring>
#include <string>
#include <vector>

#include <base/files/file_path.h>
#include <base/files/file_util.h>
#include <base/logging.h>
#include <base/strings/stringprintf.h>
#include <brillo/secure_blob.h>
#include <crypto/scoped_openssl_types.h>
#include <fuzzer/FuzzedDataProvider.h>
#include <openssl/bio.h>
#include <openssl/err.h>
#include <openssl/pem.h>
#include <openssl/rsa.h>
#include <openssl/x509.h>

#include "cryptohome/cryptolib.h"

using brillo::Blob;
using brillo::BlobFromString;
using brillo::SecureBlob;
using crypto::ScopedRSA;
using cryptohome::CryptoLib;

namespace {

constexpr char kStaticFilesPath[] = "/usr/libexec/fuzzers/";

constexpr int kMaxPlaintextLength = 5;
constexpr int kMaxOaepLabelLength = 5;

struct Environment {
  Environment();

  // The RSA keys loaded from the data files installed next to the fuzzer.
  static constexpr int kRsaKeyCount = 8;
  ScopedRSA rsa_keys[kRsaKeyCount];
};

struct ScopedOpensslErrorClearer {
  ~ScopedOpensslErrorClearer() { ERR_clear_error(); }
};

ScopedRSA LoadRsaPrivateKeyFromPemFile(const base::FilePath& pem_file_path) {
  std::string pem_data;
  CHECK(base::ReadFileToString(pem_file_path, &pem_data));
  crypto::ScopedBIO pem_data_bio(
      BIO_new_mem_buf(pem_data.data(), pem_data.size()));
  CHECK(pem_data_bio);
  crypto::ScopedRSA rsa(PEM_read_bio_RSAPrivateKey(
      pem_data_bio.get(), /*RSA **x=*/nullptr, /*pem_password_cb *cb=*/nullptr,
      /*void *u=*/nullptr));
  CHECK(rsa);
  return rsa;
}

Environment::Environment() {
  logging::SetMinLogLevel(logging::LOG_FATAL);

  int key_index = 0;
  for (int key_size : {512, 1024, 2048, 4096}) {
    for (int current_key_number : {1, 2}) {
      const base::FilePath key_file_path =
          base::FilePath(kStaticFilesPath)
              .AppendASCII(base::StringPrintf("cryptohome_fuzzer_key_rsa_%d_%d",
                                              key_size, current_key_number));
      CHECK_LT(key_index, kRsaKeyCount);
      rsa_keys[key_index] = LoadRsaPrivateKeyFromPemFile(key_file_path);
      ++key_index;
    }
  }
}

// The "commands" that the MutateBlob() function uses for enterpreting the
// fuzzer input and performing the mutations it implements.
enum class BlobMutatorCommand {
  kCopyRemainingData,
  kCopyChunk,
  kDeleteChunk,
  kInsertByte,

  kMaxValue = kInsertByte
};

// Returns the mutated version of the provided |input_blob|.
// The following mutations are applied:
// * Removing chunk(s) from the input blob;
// * Inserting "random" bytes into the input blob.
// The size of the resulting blob is guaranteed to be within [0; max_length].
Blob MutateBlob(const Blob& input_blob,
                int max_length,
                FuzzedDataProvider* fuzzed_data_provider) {
  // Begin with an empty result blob. The code below will fill it with data,
  // according to the parsed "commands".
  Blob fuzzed_blob;
  fuzzed_blob.reserve(max_length);
  int input_index = 0;
  while (fuzzed_blob.size() < max_length) {
    switch (fuzzed_data_provider->ConsumeEnum<BlobMutatorCommand>()) {
      case BlobMutatorCommand::kCopyRemainingData: {
        // Take all remaining data from the input blob and stop.
        const int bytes_to_copy = std::min(input_blob.size() - input_index,
                                           max_length - fuzzed_blob.size());
        fuzzed_blob.insert(fuzzed_blob.end(), input_blob.begin() + input_index,
                           input_blob.begin() + input_index + bytes_to_copy);
        DCHECK_LE(fuzzed_blob.size(), max_length);
        return fuzzed_blob;
      }
      case BlobMutatorCommand::kCopyChunk: {
        // Take the specified number of bytes from the current position in the
        // input blob.
        const int max_bytes_to_copy = std::min(input_blob.size() - input_index,
                                               max_length - fuzzed_blob.size());
        const int bytes_to_copy =
            fuzzed_data_provider->ConsumeIntegralInRange(0, max_bytes_to_copy);
        fuzzed_blob.insert(fuzzed_blob.end(), input_blob.begin() + input_index,
                           input_blob.begin() + input_index + bytes_to_copy);
        break;
      }
      case BlobMutatorCommand::kDeleteChunk: {
        // Skip (delete) the specified number of bytes from the current position
        // in the input blob.
        const int max_bytes_to_delete = input_blob.size() - input_index;
        const int bytes_to_delete =
            fuzzed_data_provider->ConsumeIntegralInRange(0,
                                                         max_bytes_to_delete);
        input_index += bytes_to_delete;
        break;
      }
      case BlobMutatorCommand::kInsertByte: {
        // Append the specified byte.
        fuzzed_blob.push_back(fuzzed_data_provider->ConsumeIntegral<uint8_t>());
        break;
      }
    }
  }
  DCHECK_LE(fuzzed_blob.size(), max_length);
  return fuzzed_blob;
}

// Returns a mutated RSA-OAEP encrypted blob of the given plaintext.
Blob FuzzedRsaOaepEncrypt(const Blob& plaintext,
                          const Blob& oaep_label,
                          RSA* rsa,
                          FuzzedDataProvider* fuzzed_data_provider) {
  // Explicitly do the padding step first, in order to be able to mutate its
  // result before the actual RSA operation.
  Blob padded_blob(RSA_size(rsa));
  RSA_padding_add_PKCS1_OAEP_mgf1(
      padded_blob.data(), padded_blob.size(), plaintext.data(),
      plaintext.size(), oaep_label.data(), oaep_label.size(), nullptr, nullptr);

  Blob fuzzed_padded_blob =
      MutateBlob(padded_blob, RSA_size(rsa), fuzzed_data_provider);
  fuzzed_padded_blob.resize(RSA_size(rsa));

  Blob ciphertext(RSA_size(rsa));
  RSA_public_encrypt(fuzzed_padded_blob.size(), fuzzed_padded_blob.data(),
                     ciphertext.data(), rsa, RSA_NO_PADDING);
  return MutateBlob(ciphertext, RSA_size(rsa), fuzzed_data_provider);
}

}  // namespace

extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
  static Environment environment;
  // Prevent OpenSSL errors from accumulating in the error queue and leaking the
  // memory across fuzzer executions.
  ScopedOpensslErrorClearer scoped_openssl_error_clearer;

  FuzzedDataProvider fuzzed_data_provider(data, size);

  RSA* const encryption_rsa =
      environment
          .rsa_keys[fuzzed_data_provider.ConsumeIntegralInRange(
              0, Environment::kRsaKeyCount - 1)]
          .get();
  RSA* const decryption_rsa =
      environment
          .rsa_keys[fuzzed_data_provider.ConsumeIntegralInRange(
              0, Environment::kRsaKeyCount - 1)]
          .get();

  // Prepare fuzzed parameters for the tested function, based off real
  // RSA-encoded blobs.
  const Blob plaintext = BlobFromString(
      fuzzed_data_provider.ConsumeRandomLengthString(kMaxPlaintextLength));
  const Blob oaep_label = BlobFromString(
      fuzzed_data_provider.ConsumeRandomLengthString(kMaxOaepLabelLength));
  const Blob fuzzed_ciphertext = FuzzedRsaOaepEncrypt(
      plaintext, oaep_label, encryption_rsa, &fuzzed_data_provider);

  const Blob fuzzed_oaep_label =
      MutateBlob(oaep_label, kMaxOaepLabelLength, &fuzzed_data_provider);

  // Run the fuzzed function.
  SecureBlob decrypted_data;
  if (CryptoLib::RsaOaepDecrypt(SecureBlob(fuzzed_ciphertext),
                                SecureBlob(fuzzed_oaep_label), decryption_rsa,
                                &decrypted_data)) {
    // Assert that the decryption result must be equal to the plaintext that was
    // encrypted above - it's unrealistic for the fuzzer to find a blob that is
    // a valid ciphertext of some different blob.
    CHECK(SecureBlob(plaintext) == decrypted_data);
  }
  return 0;
}
