/*
 * 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 "keymaster0_engine.h"

#include <assert.h>

#include <memory>

#define LOG_TAG "Keymaster0Engine"
#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_utils.h"

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

namespace keymaster {

Keymaster0Engine* Keymaster0Engine::instance_ = nullptr;

Keymaster0Engine::Keymaster0Engine(const keymaster0_device_t* keymaster0_device)
    : keymaster0_device_(keymaster0_device), engine_(ENGINE_new()), supports_ec_(false) {
    assert(!instance_);
    instance_ = this;

    rsa_index_ = RSA_get_ex_new_index(0 /* argl */, NULL /* argp */, NULL /* new_func */,
                                      keyblob_dup, keyblob_free);
    ec_key_index_ = EC_KEY_get_ex_new_index(0 /* argl */, NULL /* argp */, NULL /* new_func */,
                                            keyblob_dup, keyblob_free);

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

    ENGINE_set_RSA_method(engine_, &rsa_method_, sizeof(rsa_method_));

    if ((keymaster0_device_->flags & KEYMASTER_SUPPORTS_EC) != 0) {
        supports_ec_ = true;

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

        ENGINE_set_ECDSA_method(engine_, &ecdsa_method_, sizeof(ecdsa_method_));
    }
}

Keymaster0Engine::~Keymaster0Engine() {
    if (keymaster0_device_)
        keymaster0_device_->common.close(
            reinterpret_cast<hw_device_t*>(const_cast<keymaster0_device_t*>(keymaster0_device_)));
    ENGINE_free(engine_);
    instance_ = nullptr;
}

bool Keymaster0Engine::GenerateRsaKey(uint64_t public_exponent, uint32_t public_modulus,
                                      KeymasterKeyBlob* key_material) const {
    assert(key_material);
    keymaster_rsa_keygen_params_t params;
    params.public_exponent = public_exponent;
    params.modulus_size = public_modulus;

    uint8_t* key_blob = 0;
    if (keymaster0_device_->generate_keypair(keymaster0_device_, TYPE_RSA, &params, &key_blob,
                                             &key_material->key_material_size) < 0) {
        ALOGE("Error generating RSA key pair with keymaster0 device");
        return false;
    }
    unique_ptr<uint8_t, Malloc_Delete> key_blob_deleter(key_blob);
    key_material->key_material = dup_buffer(key_blob, key_material->key_material_size);
    return true;
}

bool Keymaster0Engine::GenerateEcKey(uint32_t key_size, KeymasterKeyBlob* key_material) const {
    assert(key_material);
    keymaster_ec_keygen_params_t params;
    params.field_size = key_size;

    uint8_t* key_blob = 0;
    if (keymaster0_device_->generate_keypair(keymaster0_device_, TYPE_EC, &params, &key_blob,
                                             &key_material->key_material_size) < 0) {
        ALOGE("Error generating EC key pair with keymaster0 device");
        return false;
    }
    unique_ptr<uint8_t, Malloc_Delete> key_blob_deleter(key_blob);
    key_material->key_material = dup_buffer(key_blob, key_material->key_material_size);
    return true;
}

bool Keymaster0Engine::ImportKey(keymaster_key_format_t key_format,
                                 const KeymasterKeyBlob& to_import,
                                 KeymasterKeyBlob* imported_key) const {
    assert(imported_key);
    if (key_format != KM_KEY_FORMAT_PKCS8)
        return false;

    uint8_t* key_blob = 0;
    if (keymaster0_device_->import_keypair(keymaster0_device_, to_import.key_material,
                                           to_import.key_material_size, &key_blob,
                                           &imported_key->key_material_size) < 0) {
        ALOGW("Error importing keypair with keymaster0 device");
        return false;
    }
    unique_ptr<uint8_t, Malloc_Delete> key_blob_deleter(key_blob);
    imported_key->key_material = dup_buffer(key_blob, imported_key->key_material_size);
    return true;
}

static keymaster_key_blob_t* duplicate_blob(const uint8_t* key_data, size_t key_data_size) {
    unique_ptr<uint8_t[]> key_material_copy(dup_buffer(key_data, key_data_size));
    if (!key_material_copy)
        return nullptr;

    unique_ptr<keymaster_key_blob_t> blob_copy(new (std::nothrow) keymaster_key_blob_t);
    if (!blob_copy.get())
        return nullptr;
    blob_copy->key_material_size = key_data_size;
    blob_copy->key_material = key_material_copy.release();
    return blob_copy.release();
}

inline keymaster_key_blob_t* duplicate_blob(const keymaster_key_blob_t& blob) {
    return duplicate_blob(blob.key_material, blob.key_material_size);
}

RSA* Keymaster0Engine::BlobToRsaKey(const KeymasterKeyBlob& blob) const {
    // Create new RSA key (with engine methods) and insert blob
    unique_ptr<RSA, RSA_Delete> rsa(RSA_new_method(engine_));
    if (!rsa)
        return nullptr;

    keymaster_key_blob_t* blob_copy = duplicate_blob(blob);
    if (!blob_copy->key_material || !RSA_set_ex_data(rsa.get(), rsa_index_, blob_copy))
        return nullptr;

    // Copy public key into new RSA key
    unique_ptr<EVP_PKEY, EVP_PKEY_Delete> pkey(GetKeymaster0PublicKey(blob));
    if (!pkey)
        return nullptr;
    unique_ptr<RSA, RSA_Delete> public_rsa(EVP_PKEY_get1_RSA(pkey.get()));
    if (!public_rsa)
        return nullptr;
    rsa->n = BN_dup(public_rsa->n);
    rsa->e = BN_dup(public_rsa->e);
    if (!rsa->n || !rsa->e)
        return nullptr;

    return rsa.release();
}

EC_KEY* Keymaster0Engine::BlobToEcKey(const KeymasterKeyBlob& blob) const {
    // Create new EC key (with engine methods) and insert blob
    unique_ptr<EC_KEY, EC_Delete> ec_key(EC_KEY_new_method(engine_));
    if (!ec_key)
        return nullptr;

    keymaster_key_blob_t* blob_copy = duplicate_blob(blob);
    if (!blob_copy->key_material || !EC_KEY_set_ex_data(ec_key.get(), ec_key_index_, blob_copy))
        return nullptr;

    // Copy public key into new EC key
    unique_ptr<EVP_PKEY, EVP_PKEY_Delete> pkey(GetKeymaster0PublicKey(blob));
    if (!pkey)
        return nullptr;

    unique_ptr<EC_KEY, EC_Delete> public_ec_key(EVP_PKEY_get1_EC_KEY(pkey.get()));
    if (!public_ec_key)
        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())))
        return nullptr;

    return ec_key.release();
}

const keymaster_key_blob_t* Keymaster0Engine::RsaKeyToBlob(const RSA* rsa) const {
    return reinterpret_cast<keymaster_key_blob_t*>(RSA_get_ex_data(rsa, rsa_index_));
}

const keymaster_key_blob_t* Keymaster0Engine::EcKeyToBlob(const EC_KEY* ec_key) const {
    return reinterpret_cast<keymaster_key_blob_t*>(EC_KEY_get_ex_data(ec_key, ec_key_index_));
}

/* static */
int Keymaster0Engine::keyblob_dup(CRYPTO_EX_DATA* /* to */, const CRYPTO_EX_DATA* /* from */,
                                  void** from_d, int /* index */, long /* argl */,
                                  void* /* argp */) {
    keymaster_key_blob_t* blob = reinterpret_cast<keymaster_key_blob_t*>(*from_d);
    if (!blob)
        return 1;
    *from_d = duplicate_blob(*blob);
    if (*from_d)
        return 1;
    return 0;
}

/* static */
void Keymaster0Engine::keyblob_free(void* /* parent */, void* ptr, CRYPTO_EX_DATA* /* data */,
                                    int /* index*/, long /* argl */, void* /* argp */) {
    keymaster_key_blob_t* blob = reinterpret_cast<keymaster_key_blob_t*>(ptr);
    if (blob) {
        delete[] blob->key_material;
        delete blob;
    }
}

/* static */
int Keymaster0Engine::rsa_private_transform(RSA* rsa, uint8_t* out, const uint8_t* in, size_t len) {
    ALOGV("rsa_private_transform(%p, %p, %p, %u)", rsa, out, in, (unsigned)len);

    assert(instance_);
    return instance_->RsaPrivateTransform(rsa, out, in, len);
}

/* static */
int Keymaster0Engine::ecdsa_sign(const uint8_t* digest, size_t digest_len, uint8_t* sig,
                                 unsigned int* sig_len, EC_KEY* ec_key) {
    ALOGV("ecdsa_sign(%p, %u, %p)", digest, (unsigned)digest_len, ec_key);
    assert(instance_);
    return instance_->EcdsaSign(digest, digest_len, sig, sig_len, ec_key);
}

bool Keymaster0Engine::Keymaster0Sign(const void* signing_params, const keymaster_key_blob_t& blob,
                                      const uint8_t* data, const size_t data_length,
                                      unique_ptr<uint8_t[], Malloc_Delete>* signature,
                                      size_t* signature_length) const {
    uint8_t* signed_data;
    int err = keymaster0_device_->sign_data(keymaster0_device_, signing_params, blob.key_material,
                                            blob.key_material_size, data, data_length, &signed_data,
                                            signature_length);
    if (err < 0) {
        ALOGE("Keymaster0 signing failed with error %d", err);
        return false;
    }

    signature->reset(signed_data);
    return true;
}

EVP_PKEY* Keymaster0Engine::GetKeymaster0PublicKey(const KeymasterKeyBlob& blob) const {
    uint8_t* pub_key_data;
    size_t pub_key_data_length;
    int err = keymaster0_device_->get_keypair_public(keymaster0_device_, blob.key_material,
                                                     blob.key_material_size, &pub_key_data,
                                                     &pub_key_data_length);
    if (err < 0) {
        ALOGE("Error %d extracting public key", err);
        return nullptr;
    }
    unique_ptr<uint8_t, Malloc_Delete> pub_key(pub_key_data);

    const uint8_t* p = pub_key_data;
    return d2i_PUBKEY(nullptr /* allocate new struct */, &p, pub_key_data_length);
}

static bool data_too_large_for_public_modulus(const uint8_t* data, size_t len, const RSA* rsa) {
    unique_ptr<BIGNUM, BIGNUM_Delete> input_as_bn(
        BN_bin2bn(data, len, nullptr /* allocate result */));
    return input_as_bn && BN_ucmp(input_as_bn.get(), rsa->n) >= 0;
}

#define USER_F_private_transform 100
#define USER_F_ecdsa_sign 101

int Keymaster0Engine::RsaPrivateTransform(RSA* rsa, uint8_t* out, const uint8_t* in,
                                          size_t len) const {
    const keymaster_key_blob_t* key_blob = RsaKeyToBlob(rsa);
    if (key_blob == NULL) {
        ALOGE("key had no key_blob!");
        return 0;
    }

    keymaster_rsa_sign_params_t sign_params = {DIGEST_NONE, PADDING_NONE};
    unique_ptr<uint8_t[], Malloc_Delete> signature;
    size_t signature_length;
    if (!Keymaster0Sign(&sign_params, *key_blob, in, len, &signature, &signature_length)) {
        if (data_too_large_for_public_modulus(in, len, rsa)) {
            ALOGE("Keymaster0 signing failed because data is too large.");
            OPENSSL_PUT_ERROR(RSA, private_transform, RSA_R_DATA_TOO_LARGE_FOR_MODULUS);
        } else {
            // We don't know what error code is correct; force an "unknown error" return
            OPENSSL_PUT_ERROR(USER, private_transform, KM_ERROR_UNKNOWN_ERROR);
        }
        return 0;
    }
    Eraser eraser(signature.get(), signature_length);

    if (signature_length > len) {
        /* The result of the RSA operation can never be larger than the size of
         * the modulus so we assume that the result has extra zeros on the
         * left. This provides attackers with an oracle, but there's nothing
         * that we can do about it here. */
        memcpy(out, signature.get() + signature_length - len, len);
    } else if (signature_length < len) {
        /* If the keymaster0 implementation returns a short value we assume that
         * it's because it removed leading zeros from the left side. This is
         * bad because it provides attackers with an oracle but we cannot do
         * anything about a broken keymaster0 implementation here. */
        memset(out, 0, len);
        memcpy(out + len - signature_length, signature.get(), signature_length);
    } else {
        memcpy(out, signature.get(), len);
    }

    ALOGV("rsa=%p keystore_rsa_priv_dec successful", rsa);
    return 1;
}

int Keymaster0Engine::EcdsaSign(const uint8_t* digest, size_t digest_len, uint8_t* sig,
                                unsigned int* sig_len, EC_KEY* ec_key) const {
    const keymaster_key_blob_t* key_blob = EcKeyToBlob(ec_key);
    if (key_blob == NULL) {
        ALOGE("key had no key_blob!");
        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_ec_sign_params_t sign_params = {DIGEST_NONE};
    unique_ptr<uint8_t[], Malloc_Delete> signature;
    size_t signature_length;
    if (!Keymaster0Sign(&sign_params, *key_blob, digest, digest_len, &signature,
                        &signature_length)) {
        // We don't know what error code is correct; force an "unknown error" return
        OPENSSL_PUT_ERROR(USER, ecdsa_sign, KM_ERROR_UNKNOWN_ERROR);
        return 0;
    }
    Eraser eraser(signature.get(), signature_length);

    if (signature_length == 0) {
        ALOGW("No valid signature returned");
        return 0;
    } else if (signature_length > ECDSA_size(ec_key)) {
        ALOGW("Signature is too large");
        return 0;
    } else {
        memcpy(sig, signature.get(), signature_length);
        *sig_len = signature_length;
    }

    ALOGV("ecdsa_sign(%p, %u, %p) => success", digest, (unsigned)digest_len, ec_key);
    return 1;
}

}  // namespace keymaster
