// 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/fdio/debug.h>
#include <openssl/digest.h>
#include <openssl/hmac.h>
#include <zircon/errors.h>
#include <zircon/types.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;
    }
    if ((rc = out->Resize(out_len)) != ZX_OK ||
        (rc = out->Copy(tmp.get(), out_len)) != ZX_OK) {
        return rc;
    }

    return ZX_OK;
}

} // namespace crypto
