/*
 *  Copyright 2011 The WebRTC Project Authors. All rights reserved.
 *
 *  Use of this source code is governed by a BSD-style license
 *  that can be found in the LICENSE file in the root of the source
 *  tree. An additional intellectual property rights grant can be found
 *  in the file PATENTS.  All contributing project authors may
 *  be found in the AUTHORS file in the root of the source tree.
 */

#include "rtc_base/message_digest.h"

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

#include "rtc_base/openssl_digest.h"
#include "rtc_base/string_encode.h"

namespace rtc {

// From RFC 4572.
const char DIGEST_MD5[] = "md5";
const char DIGEST_SHA_1[] = "sha-1";
const char DIGEST_SHA_224[] = "sha-224";
const char DIGEST_SHA_256[] = "sha-256";
const char DIGEST_SHA_384[] = "sha-384";
const char DIGEST_SHA_512[] = "sha-512";

static const size_t kBlockSize = 64;  // valid for SHA-256 and down

MessageDigest* MessageDigestFactory::Create(const std::string& alg) {
  MessageDigest* digest = new OpenSSLDigest(alg);
  if (digest->Size() == 0) {  // invalid algorithm
    delete digest;
    digest = nullptr;
  }
  return digest;
}

bool IsFips180DigestAlgorithm(const std::string& alg) {
  // These are the FIPS 180 algorithms.  According to RFC 4572 Section 5,
  // "Self-signed certificates (for which legacy certificates are not a
  // consideration) MUST use one of the FIPS 180 algorithms (SHA-1,
  // SHA-224, SHA-256, SHA-384, or SHA-512) as their signature algorithm,
  // and thus also MUST use it to calculate certificate fingerprints."
  return alg == DIGEST_SHA_1 || alg == DIGEST_SHA_224 ||
         alg == DIGEST_SHA_256 || alg == DIGEST_SHA_384 ||
         alg == DIGEST_SHA_512;
}

size_t ComputeDigest(MessageDigest* digest,
                     const void* input,
                     size_t in_len,
                     void* output,
                     size_t out_len) {
  digest->Update(input, in_len);
  return digest->Finish(output, out_len);
}

size_t ComputeDigest(const std::string& alg,
                     const void* input,
                     size_t in_len,
                     void* output,
                     size_t out_len) {
  std::unique_ptr<MessageDigest> digest(MessageDigestFactory::Create(alg));
  return (digest) ? ComputeDigest(digest.get(), input, in_len, output, out_len)
                  : 0;
}

std::string ComputeDigest(MessageDigest* digest, const std::string& input) {
  std::unique_ptr<char[]> output(new char[digest->Size()]);
  ComputeDigest(digest, input.data(), input.size(), output.get(),
                digest->Size());
  return hex_encode(output.get(), digest->Size());
}

bool ComputeDigest(const std::string& alg,
                   const std::string& input,
                   std::string* output) {
  std::unique_ptr<MessageDigest> digest(MessageDigestFactory::Create(alg));
  if (!digest) {
    return false;
  }
  *output = ComputeDigest(digest.get(), input);
  return true;
}

std::string ComputeDigest(const std::string& alg, const std::string& input) {
  std::string output;
  ComputeDigest(alg, input, &output);
  return output;
}

// Compute a RFC 2104 HMAC: H(K XOR opad, H(K XOR ipad, text))
size_t ComputeHmac(MessageDigest* digest,
                   const void* key,
                   size_t key_len,
                   const void* input,
                   size_t in_len,
                   void* output,
                   size_t out_len) {
  // We only handle algorithms with a 64-byte blocksize.
  // TODO: Add BlockSize() method to MessageDigest.
  size_t block_len = kBlockSize;
  if (digest->Size() > 32) {
    return 0;
  }
  // Copy the key to a block-sized buffer to simplify padding.
  // If the key is longer than a block, hash it and use the result instead.
  std::unique_ptr<uint8_t[]> new_key(new uint8_t[block_len]);
  if (key_len > block_len) {
    ComputeDigest(digest, key, key_len, new_key.get(), block_len);
    memset(new_key.get() + digest->Size(), 0, block_len - digest->Size());
  } else {
    memcpy(new_key.get(), key, key_len);
    memset(new_key.get() + key_len, 0, block_len - key_len);
  }
  // Set up the padding from the key, salting appropriately for each padding.
  std::unique_ptr<uint8_t[]> o_pad(new uint8_t[block_len]);
  std::unique_ptr<uint8_t[]> i_pad(new uint8_t[block_len]);
  for (size_t i = 0; i < block_len; ++i) {
    o_pad[i] = 0x5c ^ new_key[i];
    i_pad[i] = 0x36 ^ new_key[i];
  }
  // Inner hash; hash the inner padding, and then the input buffer.
  std::unique_ptr<uint8_t[]> inner(new uint8_t[digest->Size()]);
  digest->Update(i_pad.get(), block_len);
  digest->Update(input, in_len);
  digest->Finish(inner.get(), digest->Size());
  // Outer hash; hash the outer padding, and then the result of the inner hash.
  digest->Update(o_pad.get(), block_len);
  digest->Update(inner.get(), digest->Size());
  return digest->Finish(output, out_len);
}

size_t ComputeHmac(const std::string& alg,
                   const void* key,
                   size_t key_len,
                   const void* input,
                   size_t in_len,
                   void* output,
                   size_t out_len) {
  std::unique_ptr<MessageDigest> digest(MessageDigestFactory::Create(alg));
  if (!digest) {
    return 0;
  }
  return ComputeHmac(digest.get(), key, key_len, input, in_len, output,
                     out_len);
}

std::string ComputeHmac(MessageDigest* digest,
                        const std::string& key,
                        const std::string& input) {
  std::unique_ptr<char[]> output(new char[digest->Size()]);
  ComputeHmac(digest, key.data(), key.size(), input.data(), input.size(),
              output.get(), digest->Size());
  return hex_encode(output.get(), digest->Size());
}

bool ComputeHmac(const std::string& alg,
                 const std::string& key,
                 const std::string& input,
                 std::string* output) {
  std::unique_ptr<MessageDigest> digest(MessageDigestFactory::Create(alg));
  if (!digest) {
    return false;
  }
  *output = ComputeHmac(digest.get(), key, input);
  return true;
}

std::string ComputeHmac(const std::string& alg,
                        const std::string& key,
                        const std::string& input) {
  std::string output;
  ComputeHmac(alg, key, input, &output);
  return output;
}

}  // namespace rtc
