/*
 * Copyright 2014 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#include "hmac_operation.h"

#include <new>

#include <openssl/evp.h>
#include <openssl/hmac.h>

#include "openssl_err.h"
#include "symmetric_key.h"

#if defined(OPENSSL_IS_BORINGSSL)
#include <openssl/mem.h>
typedef size_t openssl_size_t;
#else
typedef int openssl_size_t;
#endif

namespace keymaster {

Operation* HmacOperationFactory::CreateOperation(const Key& key,
                                                 const AuthorizationSet& begin_params,
                                                 keymaster_error_t* error) {
    uint32_t tag_length = 0;
    begin_params.GetTagValue(TAG_MAC_LENGTH, &tag_length);
    if (tag_length % 8 != 0) {
        LOG_E("MAC length %d nod a multiple of 8 bits", tag_length);
        *error = KM_ERROR_UNSUPPORTED_MAC_LENGTH;
        return nullptr;
    }

    keymaster_digest_t digest;
    if (!begin_params.GetTagValue(TAG_DIGEST, &digest)) {
        LOG_E("%d digests specified in begin params", begin_params.GetTagCount(TAG_DIGEST));
        *error = KM_ERROR_UNSUPPORTED_DIGEST;
        return nullptr;
    } else if (!key.authorizations().Contains(TAG_DIGEST, digest)) {
        LOG_E("Digest %d was specified, but not authorized by key", digest);
        *error = KM_ERROR_INCOMPATIBLE_DIGEST;
        return nullptr;
    }

    const SymmetricKey* symmetric_key = static_cast<const SymmetricKey*>(&key);
    UniquePtr<HmacOperation> op(
        new (std::nothrow) HmacOperation(purpose(), symmetric_key->key_data(),
                                         symmetric_key->key_data_size(), digest, tag_length / 8));
    if (!op.get())
        *error = KM_ERROR_MEMORY_ALLOCATION_FAILED;
    else
        *error = op->error();

    if (*error != KM_ERROR_OK)
        return nullptr;

    return op.release();
}

static keymaster_digest_t supported_digests[] = {KM_DIGEST_SHA1, KM_DIGEST_SHA_2_224,
                                                 KM_DIGEST_SHA_2_256, KM_DIGEST_SHA_2_384,
                                                 KM_DIGEST_SHA_2_512};
const keymaster_digest_t* HmacOperationFactory::SupportedDigests(size_t* digest_count) const {
    *digest_count = array_length(supported_digests);
    return supported_digests;
}

HmacOperation::HmacOperation(keymaster_purpose_t purpose, const uint8_t* key_data,
                             size_t key_data_size, keymaster_digest_t digest, size_t tag_length)
    : Operation(purpose), error_(KM_ERROR_OK), tag_length_(tag_length) {
    // Initialize CTX first, so dtor won't crash even if we error out later.
    HMAC_CTX_init(&ctx_);

    const EVP_MD* md = nullptr;
    switch (digest) {
    case KM_DIGEST_NONE:
    case KM_DIGEST_MD5:
        error_ = KM_ERROR_UNSUPPORTED_DIGEST;
        break;
    case KM_DIGEST_SHA1:
        md = EVP_sha1();
        break;
    case KM_DIGEST_SHA_2_224:
        md = EVP_sha224();
        break;
    case KM_DIGEST_SHA_2_256:
        md = EVP_sha256();
        break;
    case KM_DIGEST_SHA_2_384:
        md = EVP_sha384();
        break;
    case KM_DIGEST_SHA_2_512:
        md = EVP_sha512();
        break;
    }

    if (md == nullptr) {
        error_ = KM_ERROR_UNSUPPORTED_DIGEST;
        return;
    }

    HMAC_Init_ex(&ctx_, key_data, key_data_size, md, NULL /* engine */);
}

HmacOperation::~HmacOperation() {
    HMAC_CTX_cleanup(&ctx_);
}

keymaster_error_t HmacOperation::Begin(const AuthorizationSet& /* input_params */,
                                       AuthorizationSet* /* output_params */) {
    return error_;
}

keymaster_error_t HmacOperation::Update(const AuthorizationSet& /* additional_params */,
                                        const Buffer& input, AuthorizationSet* /* output_params */,
                                        Buffer* /* output */, size_t* input_consumed) {
    if (!HMAC_Update(&ctx_, input.peek_read(), input.available_read()))
        return TranslateLastOpenSslError();
    *input_consumed = input.available_read();
    return KM_ERROR_OK;
}

keymaster_error_t HmacOperation::Abort() {
    return KM_ERROR_OK;
}

keymaster_error_t HmacOperation::Finish(const AuthorizationSet& /* additional_params */,
                                        const Buffer& signature,
                                        AuthorizationSet* /* output_params */, Buffer* output) {
    uint8_t digest[EVP_MAX_MD_SIZE];
    unsigned int digest_len;
    if (!HMAC_Final(&ctx_, digest, &digest_len))
        return TranslateLastOpenSslError();

    switch (purpose()) {
    case KM_PURPOSE_SIGN:
        if (tag_length_ > digest_len)
            return KM_ERROR_UNSUPPORTED_MAC_LENGTH;
        if (!output->reserve(tag_length_) || !output->write(digest, tag_length_))
            return KM_ERROR_MEMORY_ALLOCATION_FAILED;
        return KM_ERROR_OK;
    case KM_PURPOSE_VERIFY:
        if (signature.available_read() > digest_len)
            return KM_ERROR_INVALID_INPUT_LENGTH;
        if (CRYPTO_memcmp(signature.peek_read(), digest, signature.available_read()) != 0)
            return KM_ERROR_VERIFICATION_FAILED;
        return KM_ERROR_OK;
    default:
        return KM_ERROR_UNSUPPORTED_PURPOSE;
    }
}

}  // namespace keymaster
