// Copyright 2017 The Fuchsia 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 <ctype.h>
#include <limits.h>
#include <stdio.h>
#include <string.h>
#include <zircon/assert.h>
#include <zircon/errors.h>

#include <memory>

#include <digest/digest.h>
#include <fbl/alloc_checker.h>
#include <fbl/string.h>

// See note in //zircon/third_party/ulib/uboringssl/rules.mk
#define BORINGSSL_NO_CXX
#include <utility>

#include <openssl/sha.h>

namespace digest {

// The previously opaque crypto implementation context.
struct Digest::Context {
  Context() {}
  ~Context() {}
  SHA256_CTX impl;
};

Digest::Digest() : bytes_{0} {}

Digest::Digest(const uint8_t* other) : bytes_{0} { *this = other; }

Digest::Digest(Digest&& o) {
  ctx_ = std::move(o.ctx_);
  memcpy(bytes_, o.bytes_, sizeof(bytes_));
  memset(o.bytes_, 0, sizeof(o.bytes_));
}

Digest::~Digest() {}

Digest& Digest::operator=(Digest&& o) {
  memcpy(bytes_, o.bytes_, sizeof(bytes_));
  return *this;
}

Digest& Digest::operator=(const uint8_t* rhs) {
  memcpy(bytes_, rhs, sizeof(bytes_));
  return *this;
}

zx_status_t Digest::Init() {
  fbl::AllocChecker ac;
  ctx_.reset(new (&ac) Context());
  if (!ac.check()) {
    return ZX_ERR_NO_MEMORY;
  }
  SHA256_Init(&ctx_->impl);
  return ZX_OK;
}

void Digest::Update(const void* buf, size_t len) {
  ZX_DEBUG_ASSERT(len <= INT_MAX);
  ZX_DEBUG_ASSERT(ctx_ != nullptr);
  SHA256_Update(&ctx_->impl, buf, len);
}

const uint8_t* Digest::Final() {
  ZX_DEBUG_ASSERT(ctx_ != nullptr);
  SHA256_Final(bytes_, &ctx_->impl);
  return bytes_;
}

const uint8_t* Digest::Hash(const void* buf, size_t len) {
  Init();
  Update(buf, len);
  return Final();
}

zx_status_t Digest::Parse(const char* hex, size_t len) {
  if (len != sizeof(bytes_) * 2) {
    return ZX_ERR_INVALID_ARGS;
  }
  size_t i = 0;
  for (size_t j = 0; j < sizeof(bytes_) * 2; ++j) {
    int c = toupper(hex[j]);
    if (!isxdigit(c)) {
      return ZX_ERR_INVALID_ARGS;
    }
    c = c < 'A' ? c - '0' : c - '7';  // '7' = 'A' - 10
    if (j % 2 == 0) {
      bytes_[i] = static_cast<uint8_t>(c << 4);
    } else {
      bytes_[i++] |= static_cast<uint8_t>(c);
    }
  }
  return ZX_OK;
}

fbl::String Digest::ToString() const {
  char hex[kSha256HexLength];
  char* p = hex;
  for (size_t i = 0; i < sizeof(bytes_); ++i) {
    sprintf(p, "%02x", bytes_[i]);
    p += 2;
  }
  return fbl::String(hex);
}

zx_status_t Digest::CopyTo(uint8_t* out, size_t len) const {
  if (len < sizeof(bytes_)) {
    return ZX_ERR_BUFFER_TOO_SMALL;
  }
  memset(out, 0, len);
  memcpy(out, bytes_, sizeof(bytes_));
  return ZX_OK;
}

bool Digest::operator==(const Digest& rhs) const {
  return memcmp(bytes_, rhs.bytes_, sizeof(bytes_)) == 0;
}

bool Digest::operator!=(const Digest& rhs) const { return !(*this == rhs); }

bool Digest::operator==(const uint8_t* rhs) const {
  return rhs ? memcmp(bytes_, rhs, sizeof(bytes_)) == 0 : false;
}

bool Digest::operator!=(const uint8_t* rhs) const { return !(*this == rhs); }

}  // namespace digest
