/*
 * Copyright 2015 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 "keymaster1_engine.h"

#include <assert.h>

#include <algorithm>
#include <memory>

#define LOG_TAG "Keymaster1Engine"
#include <cutils/log.h>

#include "keymaster/android_keymaster_utils.h"

#include <openssl/bn.h>
#include <openssl/ec_key.h>
#include <openssl/ecdsa.h>

#include "openssl_err.h"
#include "openssl_utils.h"

using std::shared_ptr;
using std::unique_ptr;

namespace keymaster {

Keymaster1Engine* Keymaster1Engine::instance_ = nullptr;

Keymaster1Engine::Keymaster1Engine(const keymaster1_device_t* keymaster1_device)
    : keymaster1_device_(keymaster1_device), engine_(ENGINE_new()),
      rsa_index_(RSA_get_ex_new_index(0 /* argl */, NULL /* argp */, NULL /* new_func */,
                                      Keymaster1Engine::duplicate_key_data,
                                      Keymaster1Engine::free_key_data)),
      ec_key_index_(EC_KEY_get_ex_new_index(0 /* argl */, NULL /* argp */, NULL /* new_func */,
                                            Keymaster1Engine::duplicate_key_data,
                                            Keymaster1Engine::free_key_data)),
      rsa_method_(BuildRsaMethod()), ecdsa_method_(BuildEcdsaMethod()) {
    assert(rsa_index_ != -1);
    assert(ec_key_index_ != -1);
    assert(keymaster1_device);
    assert(!instance_);

    instance_ = this;

    ENGINE_set_RSA_method(engine_.get(), &rsa_method_, sizeof(rsa_method_));
    ENGINE_set_ECDSA_method(engine_.get(), &ecdsa_method_, sizeof(ecdsa_method_));
}

Keymaster1Engine::~Keymaster1Engine() {
    keymaster1_device_->common.close(
        reinterpret_cast<hw_device_t*>(const_cast<keymaster1_device_t*>(keymaster1_device_)));
    instance_ = nullptr;
}

static void ConvertCharacteristics(keymaster_key_characteristics_t* characteristics,
                                   AuthorizationSet* hw_enforced, AuthorizationSet* sw_enforced) {
    unique_ptr<keymaster_key_characteristics_t, Characteristics_Delete> characteristics_deleter(
        characteristics);
    if (hw_enforced)
        hw_enforced->Reinitialize(characteristics->hw_enforced);
    if (sw_enforced)
        sw_enforced->Reinitialize(characteristics->sw_enforced);
}

keymaster_error_t Keymaster1Engine::GenerateKey(const AuthorizationSet& key_description,
                                                KeymasterKeyBlob* key_blob,
                                                AuthorizationSet* hw_enforced,
                                                AuthorizationSet* sw_enforced) const {
    assert(key_blob);

    keymaster_key_characteristics_t* characteristics;
    keymaster_key_blob_t blob;
    keymaster_error_t error = keymaster1_device_->generate_key(keymaster1_device_, &key_description,
                                                               &blob, &characteristics);
    if (error != KM_ERROR_OK)
        return error;
    unique_ptr<uint8_t, Malloc_Delete> blob_deleter(const_cast<uint8_t*>(blob.key_material));
    key_blob->key_material = dup_buffer(blob.key_material, blob.key_material_size);
    key_blob->key_material_size = blob.key_material_size;

    ConvertCharacteristics(characteristics, hw_enforced, sw_enforced);
    return error;
}

keymaster_error_t Keymaster1Engine::ImportKey(const AuthorizationSet& key_description,
                                              keymaster_key_format_t input_key_material_format,
                                              const KeymasterKeyBlob& input_key_material,
                                              KeymasterKeyBlob* output_key_blob,
                                              AuthorizationSet* hw_enforced,
                                              AuthorizationSet* sw_enforced) const {
    assert(output_key_blob);

    keymaster_key_characteristics_t* characteristics;
    const keymaster_blob_t input_key = {input_key_material.key_material,
                                        input_key_material.key_material_size};
    keymaster_key_blob_t blob;
    keymaster_error_t error = keymaster1_device_->import_key(keymaster1_device_, &key_description,
                                                             input_key_material_format, &input_key,
                                                             &blob, &characteristics);
    if (error != KM_ERROR_OK)
        return error;
    unique_ptr<uint8_t, Malloc_Delete> blob_deleter(const_cast<uint8_t*>(blob.key_material));
    output_key_blob->key_material = dup_buffer(blob.key_material, blob.key_material_size);
    output_key_blob->key_material_size = blob.key_material_size;

    ConvertCharacteristics(characteristics, hw_enforced, sw_enforced);
    return error;
}

RSA* Keymaster1Engine::BuildRsaKey(const KeymasterKeyBlob& blob,
                                   const AuthorizationSet& additional_params,
                                   keymaster_error_t* error) const {
    // Create new RSA key (with engine methods) and add metadata
    unique_ptr<RSA, RSA_Delete> rsa(RSA_new_method(engine_.get()));
    if (!rsa) {
        *error = TranslateLastOpenSslError();
        return nullptr;
    }

    KeyData* key_data = new KeyData(blob, additional_params);
    if (!RSA_set_ex_data(rsa.get(), rsa_index_, key_data)) {
        *error = TranslateLastOpenSslError();
        delete key_data;
        return nullptr;
    }

    // Copy public key into new RSA key
    unique_ptr<EVP_PKEY, EVP_PKEY_Delete> pkey(
        GetKeymaster1PublicKey(key_data->key_material, key_data->begin_params, error));
    if (!pkey) {
        *error = TranslateLastOpenSslError();
        return nullptr;
    }

    unique_ptr<RSA, RSA_Delete> public_rsa(EVP_PKEY_get1_RSA(pkey.get()));
    if (!public_rsa) {
        *error = TranslateLastOpenSslError();
        return nullptr;
    }

    rsa->n = BN_dup(public_rsa->n);
    rsa->e = BN_dup(public_rsa->e);
    if (!rsa->n || !rsa->e) {
        *error = TranslateLastOpenSslError();
        return nullptr;
    }

    *error = KM_ERROR_OK;
    return rsa.release();
}

EC_KEY* Keymaster1Engine::BuildEcKey(const KeymasterKeyBlob& blob,
                                     const AuthorizationSet& additional_params,
                                     keymaster_error_t* error) const {
    // Create new EC key (with engine methods) and insert blob
    unique_ptr<EC_KEY, EC_Delete> ec_key(EC_KEY_new_method(engine_.get()));
    if (!ec_key) {
        *error = TranslateLastOpenSslError();
        return nullptr;
    }

    KeyData* key_data = new KeyData(blob, additional_params);
    if (!EC_KEY_set_ex_data(ec_key.get(), ec_key_index_, key_data)) {
        *error = TranslateLastOpenSslError();
        delete key_data;
        return nullptr;
    }

    // Copy public key into new EC key
    unique_ptr<EVP_PKEY, EVP_PKEY_Delete> pkey(
        GetKeymaster1PublicKey(blob, additional_params, error));
    if (!pkey) {
        *error = TranslateLastOpenSslError();
        return nullptr;
    }

    unique_ptr<EC_KEY, EC_Delete> public_ec_key(EVP_PKEY_get1_EC_KEY(pkey.get()));
    if (!public_ec_key) {
        *error = TranslateLastOpenSslError();
        return nullptr;
    }

    if (!EC_KEY_set_group(ec_key.get(), EC_KEY_get0_group(public_ec_key.get())) ||
        !EC_KEY_set_public_key(ec_key.get(), EC_KEY_get0_public_key(public_ec_key.get()))) {
        *error = TranslateLastOpenSslError();
        return nullptr;
    }

    *error = KM_ERROR_OK;
    return ec_key.release();
}

Keymaster1Engine::KeyData* Keymaster1Engine::GetData(EVP_PKEY* key) const {
    switch (EVP_PKEY_type(key->type)) {
    case EVP_PKEY_RSA: {
        unique_ptr<RSA, RSA_Delete> rsa(EVP_PKEY_get1_RSA(key));
        return GetData(rsa.get());
    }

    case EVP_PKEY_EC: {
        unique_ptr<EC_KEY, EC_Delete> ec_key(EVP_PKEY_get1_EC_KEY(key));
        return GetData(ec_key.get());
    }

    default:
        return nullptr;
    };
}

Keymaster1Engine::KeyData* Keymaster1Engine::GetData(const RSA* rsa) const {
    if (!rsa)
        return nullptr;
    return reinterpret_cast<KeyData*>(RSA_get_ex_data(rsa, rsa_index_));
}

Keymaster1Engine::KeyData* Keymaster1Engine::GetData(const EC_KEY* ec_key) const {
    if (!ec_key)
        return nullptr;
    return reinterpret_cast<KeyData*>(EC_KEY_get_ex_data(ec_key, ec_key_index_));
}

/* static */
int Keymaster1Engine::duplicate_key_data(CRYPTO_EX_DATA* /* to */, const CRYPTO_EX_DATA* /* from */,
                                         void** from_d, int /* index */, long /* argl */,
                                         void* /* argp */) {
    KeyData* data = reinterpret_cast<KeyData*>(*from_d);
    if (!data)
        return 1;

    // Default copy ctor is good.
    *from_d = new KeyData(*data);
    if (*from_d)
        return 1;
    return 0;
}

/* static */
void Keymaster1Engine::free_key_data(void* /* parent */, void* ptr, CRYPTO_EX_DATA* /* data */,
                                     int /* index*/, long /* argl */, void* /* argp */) {
    delete reinterpret_cast<KeyData*>(ptr);
}

keymaster_error_t Keymaster1Engine::Keymaster1Finish(const KeyData* key_data,
                                                     const keymaster_blob_t& input,
                                                     keymaster_blob_t* output) {
    if (key_data->op_handle == 0)
        return KM_ERROR_UNKNOWN_ERROR;

    size_t input_consumed;
    // Note: devices are required to consume all input in a single update call for undigested
    // signing operations and encryption operations.  No need to loop here.
    keymaster_error_t error =
        device()->update(device(), key_data->op_handle, &key_data->finish_params, &input,
                         &input_consumed, nullptr /* out_params */, nullptr /* output */);
    if (error != KM_ERROR_OK)
        return error;

    return device()->finish(device(), key_data->op_handle, &key_data->finish_params,
                            nullptr /* signature */, nullptr /* out_params */, output);
}

/* static */
int Keymaster1Engine::rsa_sign_raw(RSA* rsa, size_t* out_len, uint8_t* out, size_t max_out,
                                   const uint8_t* in, size_t in_len, int padding) {
    KeyData* key_data = instance_->GetData(rsa);
    if (!key_data)
        return 0;

    if (padding != key_data->expected_openssl_padding) {
        LOG_E("Expected sign_raw with padding %d but got padding %d",
              key_data->expected_openssl_padding, padding);
        return KM_ERROR_UNKNOWN_ERROR;
    }

    keymaster_blob_t input = {in, in_len};
    keymaster_blob_t output;
    key_data->error = instance_->Keymaster1Finish(key_data, input, &output);
    if (key_data->error != KM_ERROR_OK)
        return 0;
    unique_ptr<uint8_t, Malloc_Delete> output_deleter(const_cast<uint8_t*>(output.data));

    *out_len = std::min(output.data_length, max_out);
    memcpy(out, output.data, *out_len);
    return 1;
}

/* static */
int Keymaster1Engine::rsa_decrypt(RSA* rsa, size_t* out_len, uint8_t* out, size_t max_out,
                                  const uint8_t* in, size_t in_len, int padding) {
    KeyData* key_data = instance_->GetData(rsa);
    if (!key_data)
        return 0;

    if (padding != key_data->expected_openssl_padding) {
        LOG_E("Expected sign_raw with padding %d but got padding %d",
              key_data->expected_openssl_padding, padding);
        return KM_ERROR_UNKNOWN_ERROR;
    }

    keymaster_blob_t input = {in, in_len};
    keymaster_blob_t output;
    key_data->error = instance_->Keymaster1Finish(key_data, input, &output);
    if (key_data->error != KM_ERROR_OK)
        return 0;
    unique_ptr<uint8_t, Malloc_Delete> output_deleter(const_cast<uint8_t*>(output.data));

    *out_len = std::min(output.data_length, max_out);
    memcpy(out, output.data, *out_len);
    return 1;
}

/* static */
int Keymaster1Engine::ecdsa_sign(const uint8_t* digest, size_t digest_len, uint8_t* sig,
                                 unsigned int* sig_len, EC_KEY* ec_key) {
    KeyData* key_data = instance_->GetData(ec_key);
    if (!key_data)
        return 0;

    // Truncate digest if it's too long
    size_t max_input_len = (ec_group_size_bits(ec_key) + 7) / 8;
    if (digest_len > max_input_len)
        digest_len = max_input_len;

    keymaster_blob_t input = {digest, digest_len};
    keymaster_blob_t output;
    key_data->error = instance_->Keymaster1Finish(key_data, input, &output);
    if (key_data->error != KM_ERROR_OK)
        return 0;
    unique_ptr<uint8_t, Malloc_Delete> output_deleter(const_cast<uint8_t*>(output.data));

    *sig_len = std::min(output.data_length, ECDSA_size(ec_key));
    memcpy(sig, output.data, *sig_len);
    return 1;
}

EVP_PKEY* Keymaster1Engine::GetKeymaster1PublicKey(const KeymasterKeyBlob& blob,
                                                   const AuthorizationSet& additional_params,
                                                   keymaster_error_t* error) const {
    keymaster_blob_t client_id = {nullptr, 0};
    keymaster_blob_t app_data = {nullptr, 0};
    keymaster_blob_t* client_id_ptr = nullptr;
    keymaster_blob_t* app_data_ptr = nullptr;
    if (additional_params.GetTagValue(TAG_APPLICATION_ID, &client_id))
        client_id_ptr = &client_id;
    if (additional_params.GetTagValue(TAG_APPLICATION_DATA, &app_data))
        app_data_ptr = &app_data;

    keymaster_blob_t export_data = {nullptr, 0};
    *error = keymaster1_device_->export_key(keymaster1_device_, KM_KEY_FORMAT_X509, &blob,
                                            client_id_ptr, app_data_ptr, &export_data);
    if (*error != KM_ERROR_OK)
        return nullptr;

    unique_ptr<uint8_t, Malloc_Delete> pub_key(const_cast<uint8_t*>(export_data.data));

    const uint8_t* p = export_data.data;
    return d2i_PUBKEY(nullptr /* allocate new struct */, &p, export_data.data_length);
}

RSA_METHOD Keymaster1Engine::BuildRsaMethod() {
    RSA_METHOD method;

    method.common.references = 0;
    method.common.is_static = 1;
    method.app_data = nullptr;
    method.init = nullptr;
    method.finish = nullptr;
    method.size = nullptr;
    method.sign = nullptr;
    method.verify = nullptr;
    method.encrypt = nullptr;
    method.sign_raw = Keymaster1Engine::rsa_sign_raw;
    method.decrypt = Keymaster1Engine::rsa_decrypt;
    method.verify_raw = nullptr;
    method.private_transform = nullptr;
    method.mod_exp = nullptr;
    method.bn_mod_exp = BN_mod_exp_mont;
    method.flags = RSA_FLAG_OPAQUE;
    method.keygen = nullptr;
    method.supports_digest = nullptr;

    return method;
}

ECDSA_METHOD Keymaster1Engine::BuildEcdsaMethod() {
    ECDSA_METHOD method;

    method.common.references = 0;
    method.common.is_static = 1;
    method.app_data = nullptr;
    method.init = nullptr;
    method.finish = nullptr;
    method.group_order_size = nullptr;
    method.sign = Keymaster1Engine::ecdsa_sign;
    method.verify = nullptr;
    method.flags = ECDSA_FLAG_OPAQUE;

    return method;
}

}  // namespace keymaster
