// 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 <stddef.h>
#include <stdint.h>

#include <crypto/digest.h>
#include <crypto/hmac.h>
#include <explicit-memory/bytes.h>
#include <fbl/alloc_checker.h>
#include <lib/zircon-internal/debug.h>
#include <zircon/errors.h>
#include <zircon/types.h>

// See note in //zircon/third_party/ulib/boringssl/BUILD.gn
#define BORINGSSL_NO_CXX
#include <openssl/digest.h>
#include <openssl/hmac.h>

#include "error.h"

#define ZXDEBUG 0

namespace crypto {
namespace {

const uint16_t kAllFlags = HMAC::ALLOW_TRUNCATION | HMAC::ALLOW_WEAK_KEY;
}
// The previously opaque crypto implementation context.  Guaranteed to clean up on destruction.
struct HMAC::Context {
  Context() { HMAC_CTX_init(&impl); }

  ~Context() { HMAC_CTX_cleanup(&impl); }

  HMAC_CTX impl;
};

HMAC::HMAC() {}
HMAC::~HMAC() {}

zx_status_t HMAC::Create(digest::Algorithm digest, const Secret& key, const void* in, size_t in_len,
                         Bytes* out, uint16_t flags) {
  zx_status_t rc;

  HMAC hmac;
  if ((rc = hmac.Init(digest, key, flags)) != ZX_OK || (rc = hmac.Update(in, in_len)) != ZX_OK ||
      (rc = hmac.Final(out)) != ZX_OK) {
    return rc;
  }

  return ZX_OK;
}

zx_status_t HMAC::Verify(digest::Algorithm digest, const Secret& key, const void* in, size_t in_len,
                         const Bytes& hmac, uint16_t flags) {
  zx_status_t rc;

  Bytes tmp;
  if ((rc = HMAC::Create(digest, key, in, in_len, &tmp, flags)) != ZX_OK) {
    return rc;
  }

  size_t hmac_len = hmac.len();
  size_t tmp_len = tmp.len();
  if (hmac_len != tmp_len) {
    // According to RFC 2104, section 5, the digest can be truncated to half its original size.
    // We enforce a more stringent minimum than the RFC of 128 bits
    if ((flags & ALLOW_TRUNCATION) == 0 || hmac_len < tmp_len / 2 || hmac_len < 16) {
      xprintf("digest to verify is too short: %zu\n", hmac_len);
      return ZX_ERR_INVALID_ARGS;
    }
    if ((rc = tmp.Resize(hmac.len())) != ZX_OK) {
      return rc;
    }
  }

  if (tmp != hmac) {
    xprintf("HMAC verification failed\n");
    return ZX_ERR_IO_DATA_INTEGRITY;
  }

  return ZX_OK;
}

zx_status_t HMAC::Init(digest::Algorithm digest, const Secret& key, uint16_t flags) {
  zx_status_t rc;

  if ((flags & (~kAllFlags)) != 0) {
    xprintf("invalid flags: %04x\n", flags);
    return ZX_ERR_INVALID_ARGS;
  }

  fbl::AllocChecker ac;
  ctx_.reset(new (&ac) Context());
  if (!ac.check()) {
    xprintf("allocation failed: %zu bytes\n", sizeof(Context));
    return ZX_ERR_NO_MEMORY;
  }

  // Get the digest algorithm
  uintptr_t ptr;
  if ((rc = digest::GetDigest(digest, &ptr)) != ZX_OK) {
    return rc;
  }
  const EVP_MD* md = reinterpret_cast<const EVP_MD*>(ptr);

  // Check key length.  Keys less than digest length are invalid (RFC 2104, section 2).
  size_t key_len = key.len();
  if ((flags & ALLOW_WEAK_KEY) == 0 && key_len < EVP_MD_size(md)) {
    xprintf("weak key: %zu bytes\n", key_len);
    return ZX_ERR_INVALID_ARGS;
  }

  // Initialize the HMAC context
  if (HMAC_Init_ex(&ctx_->impl, key.get(), key_len, md, nullptr) != 1) {
    xprintf_crypto_errors(&rc);
    return rc;
  }

  return ZX_OK;
}

zx_status_t HMAC::Update(const void* in, size_t in_len) {
  zx_status_t rc;

  if (!ctx_) {
    xprintf("not initialized\n");
    return ZX_ERR_BAD_STATE;
  }

  if (in_len == 0) {
    return ZX_OK;
  }
  if (!in) {
    xprintf("input is null\n");
    return ZX_ERR_INVALID_ARGS;
  }

  if (HMAC_Update(&ctx_->impl, static_cast<const uint8_t*>(in), in_len) != 1) {
    xprintf_crypto_errors(&rc);
    return rc;
  }

  return ZX_OK;
}

zx_status_t HMAC::Final(Bytes* out) {
  zx_status_t rc;

  if (!out) {
    xprintf("null parameter: out\n");
    return ZX_ERR_INVALID_ARGS;
  }

  if (!ctx_) {
    xprintf("not initialized\n");
    return ZX_ERR_BAD_STATE;
  }

  Bytes tmp;
  if ((rc = tmp.Resize(EVP_MAX_MD_SIZE)) != ZX_OK) {
    return rc;
  }

  unsigned int out_len;
  if (HMAC_Final(&ctx_->impl, tmp.get(), &out_len) != 1) {
    xprintf_crypto_errors(&rc);
    return rc;
  }
  ctx_.reset();

  if ((rc = out->Resize(out_len)) != ZX_OK || (rc = out->Copy(tmp.get(), out_len)) != ZX_OK) {
    return rc;
  }

  return ZX_OK;
}

}  // namespace crypto
