/*
 *  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 "webrtc/rtc_base/messagedigest.h"

#include <memory>

#include <string.h>

#include "webrtc/rtc_base/basictypes.h"
#include "webrtc/rtc_base/openssldigest.h"
#include "webrtc/rtc_base/stringencode.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
