/*
**
** Copyright 2017, 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 "keymaster_passthrough_operation.h"
#include <keymaster/legacy_support/keymaster_passthrough_engine.h>
#include <keymaster/legacy_support/keymaster_passthrough_key.h>

#include <hardware/keymaster1.h>
#include <hardware/keymaster2.h>

#include <assert.h>

#include <algorithm>
#include <memory>
#include <type_traits>

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

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

namespace keymaster {

template <typename KeymasterDeviceType>
class TKeymasterPassthroughEngine : public KeymasterPassthroughEngine {
    using opfactory_t = KeymasterPassthroughOperationFactory<KeymasterDeviceType>;

  public:
    /**
     * The engine takes ownership of the device, and will close it during destruction.
     */
    explicit TKeymasterPassthroughEngine(const KeymasterDeviceType* km_device)
        : km_device_(km_device) {
        rsa_encrypt_op_factory_.reset(
            new opfactory_t(KM_ALGORITHM_RSA, KM_PURPOSE_ENCRYPT, km_device_));
        rsa_decrypt_op_factory_.reset(
            new opfactory_t(KM_ALGORITHM_RSA, KM_PURPOSE_DECRYPT, km_device_));
        rsa_sign_op_factory_.reset(new opfactory_t(KM_ALGORITHM_RSA, KM_PURPOSE_SIGN, km_device_));
        rsa_verify_op_factory_.reset(
            new opfactory_t(KM_ALGORITHM_RSA, KM_PURPOSE_VERIFY, km_device_));
        ec_encrypt_op_factory_.reset(
            new opfactory_t(KM_ALGORITHM_EC, KM_PURPOSE_ENCRYPT, km_device_));
        ec_decrypt_op_factory_.reset(
            new opfactory_t(KM_ALGORITHM_EC, KM_PURPOSE_DECRYPT, km_device_));
        ec_sign_op_factory_.reset(new opfactory_t(KM_ALGORITHM_EC, KM_PURPOSE_SIGN, km_device_));
        ec_verify_op_factory_.reset(
            new opfactory_t(KM_ALGORITHM_EC, KM_PURPOSE_VERIFY, km_device_));
        ec_derive_op_factory_.reset(
            new opfactory_t(KM_ALGORITHM_EC, KM_PURPOSE_DERIVE_KEY, km_device_));
        aes_encrypt_op_factory_.reset(
            new opfactory_t(KM_ALGORITHM_AES, KM_PURPOSE_ENCRYPT, km_device_));
        aes_decrypt_op_factory_.reset(
            new opfactory_t(KM_ALGORITHM_AES, KM_PURPOSE_DECRYPT, km_device_));
        triple_des_encrypt_op_factory_.reset(
            new opfactory_t(KM_ALGORITHM_TRIPLE_DES, KM_PURPOSE_ENCRYPT, km_device_));
        triple_des_decrypt_op_factory_.reset(
            new opfactory_t(KM_ALGORITHM_TRIPLE_DES, KM_PURPOSE_DECRYPT, km_device_));
        hmac_sign_op_factory_.reset(
            new opfactory_t(KM_ALGORITHM_HMAC, KM_PURPOSE_SIGN, km_device_));
        hmac_verify_op_factory_.reset(
            new opfactory_t(KM_ALGORITHM_HMAC, KM_PURPOSE_VERIFY, km_device_));
    }
    virtual ~TKeymasterPassthroughEngine() {
        // QUIRK: we only take ownership if this is a KM2 device.
        //        For KM1 the Keymaster1Engine takes ownership
        if (std::is_same<KeymasterDeviceType, keymaster2_device_t>::value)
            km_device_->common.close(
                    reinterpret_cast<hw_device_t*>(const_cast<KeymasterDeviceType*>(km_device_)));
    }

    keymaster_error_t GenerateKey(const AuthorizationSet& key_description,
                                  KeymasterKeyBlob* key_material, AuthorizationSet* hw_enforced,
                                  AuthorizationSet* sw_enforced) const override;

    keymaster_error_t 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 override;
    keymaster_error_t ExportKey(keymaster_key_format_t format,
                                const KeymasterKeyBlob& blob,
                                const KeymasterBlob& client_id,
                                const KeymasterBlob& app_data,
                                KeymasterBlob* export_data) const override {
        keymaster_blob_t my_export_data = {};
        keymaster_error_t error = km_device_->export_key(km_device_, format, &blob, &client_id,
                                                         &app_data, &my_export_data);
        if (error != KM_ERROR_OK)
            return error;
        *export_data = KeymasterBlob(my_export_data.data, my_export_data.data_length);
        free(const_cast<uint8_t*>(my_export_data.data));
        if (export_data->data == nullptr) {
            return KM_ERROR_MEMORY_ALLOCATION_FAILED;
        }
        return error;
    }
    keymaster_error_t DeleteKey(const KeymasterKeyBlob& blob) const override {
        return km_device_->delete_key(km_device_, &blob);
    }
    keymaster_error_t DeleteAllKeys() const override {
        return km_device_->delete_all_keys(km_device_);
    }
    OperationFactory* GetOperationFactory(keymaster_purpose_t purpose,
                                          keymaster_algorithm_t algorithm) const override {
        switch(algorithm) {
        case KM_ALGORITHM_RSA:
            switch(purpose) {
            case KM_PURPOSE_ENCRYPT:
                return rsa_encrypt_op_factory_.get();
            case KM_PURPOSE_DECRYPT:
                return rsa_decrypt_op_factory_.get();
            case KM_PURPOSE_SIGN:
                return rsa_sign_op_factory_.get();
            case KM_PURPOSE_VERIFY:
                return rsa_verify_op_factory_.get();
            default:
                return nullptr;
            }
        case KM_ALGORITHM_EC:
            switch(purpose) {
            case KM_PURPOSE_ENCRYPT:
                return ec_encrypt_op_factory_.get();
            case KM_PURPOSE_DECRYPT:
                return ec_decrypt_op_factory_.get();
            case KM_PURPOSE_SIGN:
                return ec_sign_op_factory_.get();
            case KM_PURPOSE_VERIFY:
                return ec_verify_op_factory_.get();
            case KM_PURPOSE_DERIVE_KEY:
                return ec_derive_op_factory_.get();
            default:
                return nullptr;
            }
        case KM_ALGORITHM_AES:
            switch(purpose) {
            case KM_PURPOSE_ENCRYPT:
                return aes_encrypt_op_factory_.get();
            case KM_PURPOSE_DECRYPT:
                return aes_decrypt_op_factory_.get();
            default:
                return nullptr;
            }
        case KM_ALGORITHM_TRIPLE_DES:
            switch (purpose) {
            case KM_PURPOSE_ENCRYPT:
                return triple_des_encrypt_op_factory_.get();
            case KM_PURPOSE_DECRYPT:
                return triple_des_decrypt_op_factory_.get();
            default:
                return nullptr;
            }
        case KM_ALGORITHM_HMAC:
            switch (purpose) {
            case KM_PURPOSE_SIGN:
                return hmac_sign_op_factory_.get();
            case KM_PURPOSE_VERIFY:
                return hmac_verify_op_factory_.get();
            default:
                return nullptr;
            }
        }
    }

    const KeymasterDeviceType* device() const { return km_device_; }

  private:
    TKeymasterPassthroughEngine(const KeymasterPassthroughEngine&) = delete;  // Uncopyable
    void operator=(const KeymasterPassthroughEngine&) = delete;    // Unassignable

    const KeymasterDeviceType* const km_device_;
    std::unique_ptr<opfactory_t> rsa_encrypt_op_factory_;
    std::unique_ptr<opfactory_t> rsa_decrypt_op_factory_;
    std::unique_ptr<opfactory_t> rsa_sign_op_factory_;
    std::unique_ptr<opfactory_t> rsa_verify_op_factory_;
    std::unique_ptr<opfactory_t> ec_encrypt_op_factory_;
    std::unique_ptr<opfactory_t> ec_decrypt_op_factory_;
    std::unique_ptr<opfactory_t> ec_sign_op_factory_;
    std::unique_ptr<opfactory_t> ec_verify_op_factory_;
    std::unique_ptr<opfactory_t> ec_derive_op_factory_;
    std::unique_ptr<opfactory_t> aes_encrypt_op_factory_;
    std::unique_ptr<opfactory_t> aes_decrypt_op_factory_;
    std::unique_ptr<opfactory_t> triple_des_encrypt_op_factory_;
    std::unique_ptr<opfactory_t> triple_des_decrypt_op_factory_;
    std::unique_ptr<opfactory_t> hmac_sign_op_factory_;
    std::unique_ptr<opfactory_t> hmac_verify_op_factory_;
};

static void ConvertCharacteristics(const keymaster_key_characteristics_t& characteristics,
                                   AuthorizationSet* hw_enforced, AuthorizationSet* sw_enforced) {
    if (hw_enforced)
        hw_enforced->Reinitialize(characteristics.hw_enforced);
    if (sw_enforced)
        sw_enforced->Reinitialize(characteristics.sw_enforced);
}

template<>
keymaster_error_t
TKeymasterPassthroughEngine<keymaster1_device_t>::GenerateKey(const AuthorizationSet& key_description,
                                                KeymasterKeyBlob* key_blob,
                                                AuthorizationSet* hw_enforced,
                                                AuthorizationSet* sw_enforced) const {
    assert(key_blob);

    keymaster_key_characteristics_t* characteristics = nullptr;
    keymaster_key_blob_t blob = {};
    keymaster_error_t error = km_device_->generate_key(km_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);
    keymaster_free_characteristics(characteristics);
    free (characteristics);
    return error;
}
template<>
keymaster_error_t
TKeymasterPassthroughEngine<keymaster2_device_t>::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 = km_device_->generate_key(km_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);
    keymaster_free_characteristics(&characteristics);
    return error;
}

template<>
keymaster_error_t
TKeymasterPassthroughEngine<keymaster1_device_t>::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 = km_device_->import_key(km_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 = KeymasterKeyBlob(blob);

    ConvertCharacteristics(*characteristics, hw_enforced, sw_enforced);
    keymaster_free_characteristics(characteristics);
    free(characteristics);
    return error;
}

template<>
keymaster_error_t
TKeymasterPassthroughEngine<keymaster2_device_t>::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 = km_device_->import_key(km_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));
    // TODO why duplicate the blob if we have ownership here anyway?
    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);
    keymaster_free_characteristics(&characteristics);
    return error;
}

typedef UniquePtr<KeymasterPassthroughEngine> engine_ptr_t;

engine_ptr_t
KeymasterPassthroughEngine::createInstance(const keymaster1_device_t* dev) {
    return engine_ptr_t(new TKeymasterPassthroughEngine<keymaster1_device_t>(dev));
}
engine_ptr_t
KeymasterPassthroughEngine::createInstance(const keymaster2_device_t* dev) {
    return engine_ptr_t(new TKeymasterPassthroughEngine<keymaster2_device_t>(dev));
}

}  // namespace keymaster
