/*
 * Copyright (C) 2011 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 <errno.h>
#include <string.h>
#include <stdint.h>

// For debugging
#define LOG_NDEBUG 0

// TEE is the Trusted Execution Environment
#define LOG_TAG "TEEKeyMaster"
#include <cutils/log.h>

#include <hardware/hardware.h>
#include <hardware/keymaster0.h>

#include <openssl/bn.h>
#include <openssl/err.h>
#include <openssl/evp.h>
#include <openssl/rand.h>
#include <openssl/x509.h>

#include <cryptoki.h>
#include <pkcs11.h>

#include <UniquePtr.h>


/** The size of a key ID in bytes */
#define ID_LENGTH 32

/** The current stored key version. */
const static uint32_t KEY_VERSION = 1;


struct EVP_PKEY_Delete {
    void operator()(EVP_PKEY* p) const {
        EVP_PKEY_free(p);
    }
};
typedef UniquePtr<EVP_PKEY, EVP_PKEY_Delete> Unique_EVP_PKEY;

struct RSA_Delete {
    void operator()(RSA* p) const {
        RSA_free(p);
    }
};
typedef UniquePtr<RSA, RSA_Delete> Unique_RSA;

struct PKCS8_PRIV_KEY_INFO_Delete {
    void operator()(PKCS8_PRIV_KEY_INFO* p) const {
        PKCS8_PRIV_KEY_INFO_free(p);
    }
};
typedef UniquePtr<PKCS8_PRIV_KEY_INFO, PKCS8_PRIV_KEY_INFO_Delete> Unique_PKCS8_PRIV_KEY_INFO;

typedef UniquePtr<keymaster0_device_t> Unique_keymaster_device_t;

typedef UniquePtr<CK_BYTE[]> Unique_CK_BYTE;

typedef UniquePtr<CK_ATTRIBUTE[]> Unique_CK_ATTRIBUTE;

class ByteArray {
public:
    ByteArray(CK_BYTE* array, size_t len) :
            mArray(array), mLength(len) {
    }

    ByteArray(size_t len) :
            mLength(len) {
        mArray = new CK_BYTE[len];
    }

    ~ByteArray() {
        if (mArray != NULL) {
            delete[] mArray;
        }
    }

    CK_BYTE* get() const {
        return mArray;
    }

    void setLength(size_t length) {
        mLength = length;
    }

    size_t length() const {
        return mLength;
    }

    CK_BYTE* release() {
        CK_BYTE* array = mArray;
        mArray = NULL;
        return array;
    }

private:
    CK_BYTE* mArray;
    size_t mLength;
};
typedef UniquePtr<ByteArray> Unique_ByteArray;

class CryptoSession {
public:
    CryptoSession(CK_SESSION_HANDLE masterHandle) :
            mHandle(masterHandle), mSubsession(CK_INVALID_HANDLE) {
        CK_SESSION_HANDLE subsessionHandle = mHandle;
        CK_RV openSessionRV = C_OpenSession(CKV_TOKEN_USER,
                CKF_SERIAL_SESSION | CKF_RW_SESSION | CKVF_OPEN_SUB_SESSION,
                NULL,
                NULL,
                &subsessionHandle);

        if (openSessionRV != CKR_OK || subsessionHandle == CK_INVALID_HANDLE) {
            (void) C_Finalize(NULL_PTR);
            ALOGE("Error opening secondary session with TEE: 0x%x", openSessionRV);
        } else {
            ALOGV("Opening subsession 0x%x", subsessionHandle);
            mSubsession = subsessionHandle;
        }
    }

    ~CryptoSession() {
        if (mSubsession != CK_INVALID_HANDLE) {
            CK_RV rv = C_CloseSession(mSubsession);
            ALOGV("Closing subsession 0x%x: 0x%x", mSubsession, rv);
            mSubsession = CK_INVALID_HANDLE;
        }
    }

    CK_SESSION_HANDLE get() const {
        return mSubsession;
    }

    CK_SESSION_HANDLE getPrimary() const {
        return mHandle;
    }

private:
    CK_SESSION_HANDLE mHandle;
    CK_SESSION_HANDLE mSubsession;
};

class ObjectHandle {
public:
    ObjectHandle(const CryptoSession* session, CK_OBJECT_HANDLE handle = CK_INVALID_HANDLE) :
            mSession(session), mHandle(handle) {
    }

    ~ObjectHandle() {
        if (mHandle != CK_INVALID_HANDLE) {
            CK_RV rv = C_CloseObjectHandle(mSession->getPrimary(), mHandle);
            if (rv != CKR_OK) {
                ALOGW("Couldn't close object handle 0x%x: 0x%x", mHandle, rv);
            } else {
                ALOGV("Closing object handle 0x%x", mHandle);
                mHandle = CK_INVALID_HANDLE;
            }
        }
    }

    CK_OBJECT_HANDLE get() const {
        return mHandle;
    }

    void reset(CK_OBJECT_HANDLE handle) {
        mHandle = handle;
    }

private:
    const CryptoSession* mSession;
    CK_OBJECT_HANDLE mHandle;
};


/**
 * Many OpenSSL APIs take ownership of an argument on success but don't free the argument
 * on failure. This means we need to tell our scoped pointers when we've transferred ownership,
 * without triggering a warning by not using the result of release().
 */
#define OWNERSHIP_TRANSFERRED(obj) \
    typeof (obj.release()) _dummy __attribute__((unused)) = obj.release()


/*
 * Checks this thread's OpenSSL error queue and logs if
 * necessary.
 */
static void logOpenSSLError(const char* location) {
    int error = ERR_get_error();

    if (error != 0) {
        char message[256];
        ERR_error_string_n(error, message, sizeof(message));
        ALOGE("OpenSSL error in %s %d: %s", location, error, message);
    }

    ERR_clear_error();
    ERR_remove_state(0);
}


/**
 * Convert from OpenSSL's BIGNUM format to TEE's Big Integer format.
 */
static ByteArray* bignum_to_array(const BIGNUM* bn) {
    const int bignumSize = BN_num_bytes(bn);

    Unique_CK_BYTE bytes(new CK_BYTE[bignumSize]);

    unsigned char* tmp = reinterpret_cast<unsigned char*>(bytes.get());
    if (BN_bn2bin(bn, tmp) != bignumSize) {
        ALOGE("public exponent size wasn't what was expected");
        return NULL;
    }

    return new ByteArray(bytes.release(), bignumSize);
}

static void set_attribute(CK_ATTRIBUTE* attrib, CK_ATTRIBUTE_TYPE type, void* pValue,
        CK_ULONG ulValueLen) {
    attrib->type = type;
    attrib->pValue = pValue;
    attrib->ulValueLen = ulValueLen;
}

static ByteArray* generate_random_id() {
    Unique_ByteArray id(new ByteArray(ID_LENGTH));
    if (RAND_pseudo_bytes(reinterpret_cast<unsigned char*>(id->get()), id->length()) < 0) {
        return NULL;
    }

    return id.release();
}

static int keyblob_save(ByteArray* objId, uint8_t** key_blob, size_t* key_blob_length) {
    Unique_ByteArray handleBlob(new ByteArray(sizeof(uint32_t) + objId->length()));
    if (handleBlob.get() == NULL) {
        ALOGE("Could not allocate key blob");
        return -1;
    }
    uint8_t* tmp = handleBlob->get();
    for (size_t i = 0; i < sizeof(uint32_t); i++) {
        *tmp++ = KEY_VERSION >> ((sizeof(uint32_t) - i - 1) * 8);
    }
    memcpy(tmp, objId->get(), objId->length());

    *key_blob_length = handleBlob->length();
    *key_blob = handleBlob->get();
    ByteArray* unused __attribute__((unused)) = handleBlob.release();

    return 0;
}

static int find_single_object(const uint8_t* obj_id, const size_t obj_id_length,
        CK_OBJECT_CLASS obj_class, const CryptoSession* session, ObjectHandle* object) {

    // Note that the CKA_ID attribute is never written, so we can cast away const here.
    void* obj_id_ptr = reinterpret_cast<void*>(const_cast<uint8_t*>(obj_id));
    CK_ATTRIBUTE attributes[] = {
            { CKA_ID,    obj_id_ptr, obj_id_length },
            { CKA_CLASS, &obj_class, sizeof(obj_class) },
    };

    CK_RV rv = C_FindObjectsInit(session->get(), attributes,
            sizeof(attributes) / sizeof(CK_ATTRIBUTE));
    if (rv != CKR_OK) {
        ALOGE("Error in C_FindObjectsInit: 0x%x", rv);
        return -1;
    }

    CK_OBJECT_HANDLE tmpHandle;
    CK_ULONG tmpCount;

    rv = C_FindObjects(session->get(), &tmpHandle, 1, &tmpCount);
    ALOGV("Found %d object 0x%x : class 0x%x", tmpCount, tmpHandle, obj_class);
    if (rv != CKR_OK || tmpCount != 1) {
        C_FindObjectsFinal(session->get());
        ALOGE("Couldn't find key!");
        return -1;
    }
    C_FindObjectsFinal(session->get());

    object->reset(tmpHandle);
    return 0;
}

static int keyblob_restore(const CryptoSession* session, const uint8_t* keyBlob,
        const size_t keyBlobLength, ObjectHandle* public_key, ObjectHandle* private_key) {
    if (keyBlob == NULL) {
        ALOGE("key blob was null");
        return -1;
    }

    if (keyBlobLength < (sizeof(KEY_VERSION) + ID_LENGTH)) {
        ALOGE("key blob is not correct size");
        return -1;
    }

    uint32_t keyVersion = 0;

    const uint8_t* p = keyBlob;
    for (size_t i = 0; i < sizeof(keyVersion); i++) {
        keyVersion = (keyVersion << 8) | *p++;
    }

    if (keyVersion != 1) {
        ALOGE("Invalid key version %d", keyVersion);
        return -1;
    }

    return find_single_object(p, ID_LENGTH, CKO_PUBLIC_KEY, session, public_key)
            || find_single_object(p, ID_LENGTH, CKO_PRIVATE_KEY, session, private_key);
}

static int tee_generate_keypair(const keymaster0_device_t* dev,
        const keymaster_keypair_t type, const void* key_params,
        uint8_t** key_blob, size_t* key_blob_length) {
    CK_BBOOL bTRUE = CK_TRUE;

    if (type != TYPE_RSA) {
        ALOGW("Unknown key type %d", type);
        return -1;
    }

    if (key_params == NULL) {
        ALOGW("generate_keypair params were NULL");
        return -1;
    }

    keymaster_rsa_keygen_params_t* rsa_params = (keymaster_rsa_keygen_params_t*) key_params;

    CK_MECHANISM mechanism = {
            CKM_RSA_PKCS_KEY_PAIR_GEN, NULL, 0,
    };
    CK_ULONG modulusBits = (CK_ULONG) rsa_params->modulus_size;

    /**
     * Convert our unsigned 64-bit integer to the TEE Big Integer class. It's
     * an unsigned array of bytes with MSB first.
     */
    CK_BYTE publicExponent[sizeof(uint64_t)];
    const uint64_t exp = rsa_params->public_exponent;
    size_t offset = sizeof(publicExponent) - 1;
    for (size_t i = 0; i < sizeof(publicExponent); i++) {
        publicExponent[offset--] = (exp >> (i * CHAR_BIT)) & 0xFF;
    }

    Unique_ByteArray objId(generate_random_id());
    if (objId.get() == NULL) {
        ALOGE("Couldn't generate random key ID");
        return -1;
    }

    CK_ATTRIBUTE publicKeyTemplate[] = {
            {CKA_ID,              objId->get(),   objId->length()},
            {CKA_TOKEN,           &bTRUE,         sizeof(bTRUE)},
            {CKA_ENCRYPT,         &bTRUE,         sizeof(bTRUE)},
            {CKA_VERIFY,          &bTRUE,         sizeof(bTRUE)},
            {CKA_MODULUS_BITS,    &modulusBits,   sizeof(modulusBits)},
            {CKA_PUBLIC_EXPONENT, publicExponent, sizeof(publicExponent)},
    };

    CK_ATTRIBUTE privateKeyTemplate[] = {
            {CKA_ID,              objId->get(),   objId->length()},
            {CKA_TOKEN,           &bTRUE,         sizeof(bTRUE)},
            {CKA_DECRYPT,         &bTRUE,         sizeof(bTRUE)},
            {CKA_SIGN,            &bTRUE,         sizeof(bTRUE)},
    };

    CryptoSession session(reinterpret_cast<CK_SESSION_HANDLE>(dev->context));

    CK_OBJECT_HANDLE hPublicKey, hPrivateKey;
    CK_RV rv = C_GenerateKeyPair(session.get(),
            &mechanism,
            publicKeyTemplate,
            sizeof(publicKeyTemplate)/sizeof(CK_ATTRIBUTE),
            privateKeyTemplate,
            sizeof(privateKeyTemplate)/sizeof(CK_ATTRIBUTE),
            &hPublicKey,
            &hPrivateKey);

    if (rv != CKR_OK) {
        ALOGE("Generate keypair failed: 0x%x", rv);
        return -1;
    }

    ObjectHandle publicKey(&session, hPublicKey);
    ObjectHandle privateKey(&session, hPrivateKey);
    ALOGV("public handle = 0x%x, private handle = 0x%x", publicKey.get(), privateKey.get());

    return keyblob_save(objId.get(), key_blob, key_blob_length);
}

static int tee_import_keypair(const keymaster0_device_t* dev,
        const uint8_t* key, const size_t key_length,
        uint8_t** key_blob, size_t* key_blob_length) {
    CK_RV rv;
    CK_BBOOL bTRUE = CK_TRUE;

    if (key == NULL) {
        ALOGW("provided key is null");
        return -1;
    }

    Unique_PKCS8_PRIV_KEY_INFO pkcs8(d2i_PKCS8_PRIV_KEY_INFO(NULL, &key, key_length));
    if (pkcs8.get() == NULL) {
        logOpenSSLError("tee_import_keypair");
        return -1;
    }

    /* assign to EVP */
    Unique_EVP_PKEY pkey(EVP_PKCS82PKEY(pkcs8.get()));
    if (pkey.get() == NULL) {
        logOpenSSLError("tee_import_keypair");
        return -1;
    }

    if (EVP_PKEY_type(pkey->type) != EVP_PKEY_RSA) {
        ALOGE("Unsupported key type: %d", EVP_PKEY_type(pkey->type));
        return -1;
    }

    Unique_RSA rsa(EVP_PKEY_get1_RSA(pkey.get()));
    if (rsa.get() == NULL) {
        logOpenSSLError("tee_import_keypair");
        return -1;
    }

    Unique_ByteArray modulus(bignum_to_array(rsa->n));
    if (modulus.get() == NULL) {
        ALOGW("Could not convert modulus to array");
        return -1;
    }

    Unique_ByteArray publicExponent(bignum_to_array(rsa->e));
    if (publicExponent.get() == NULL) {
        ALOGW("Could not convert publicExponent to array");
        return -1;
    }

    CK_KEY_TYPE rsaType = CKK_RSA;

    CK_OBJECT_CLASS pubClass = CKO_PUBLIC_KEY;

    Unique_ByteArray objId(generate_random_id());
    if (objId.get() == NULL) {
        ALOGE("Couldn't generate random key ID");
        return -1;
    }

    CK_ATTRIBUTE publicKeyTemplate[] = {
            {CKA_ID,              objId->get(),          objId->length()},
            {CKA_TOKEN,           &bTRUE,                sizeof(bTRUE)},
            {CKA_CLASS,           &pubClass,             sizeof(pubClass)},
            {CKA_KEY_TYPE,        &rsaType,              sizeof(rsaType)},
            {CKA_ENCRYPT,         &bTRUE,                sizeof(bTRUE)},
            {CKA_VERIFY,          &bTRUE,                sizeof(bTRUE)},
            {CKA_MODULUS,         modulus->get(),        modulus->length()},
            {CKA_PUBLIC_EXPONENT, publicExponent->get(), publicExponent->length()},
    };

    CryptoSession session(reinterpret_cast<CK_SESSION_HANDLE>(dev->context));

    CK_OBJECT_HANDLE hPublicKey;
    rv = C_CreateObject(session.get(),
            publicKeyTemplate,
            sizeof(publicKeyTemplate)/sizeof(CK_ATTRIBUTE),
            &hPublicKey);
    if (rv != CKR_OK) {
        ALOGE("Creation of public key failed: 0x%x", rv);
        return -1;
    }
    ObjectHandle publicKey(&session, hPublicKey);

    Unique_ByteArray privateExponent(bignum_to_array(rsa->d));
    if (privateExponent.get() == NULL) {
        ALOGW("Could not convert private exponent");
        return -1;
    }


    /*
     * Normally we need:
     *   CKA_ID
     *   CKA_TOKEN
     *   CKA_CLASS
     *   CKA_KEY_TYPE
     *
     *   CKA_DECRYPT
     *   CKA_SIGN
     *
     *   CKA_MODULUS
     *   CKA_PUBLIC_EXPONENT
     *   CKA_PRIVATE_EXPONENT
     */
#define PRIV_ATTRIB_NORMAL_NUM (4 + 2 + 3)

    /*
     * For additional private key values:
     *   CKA_PRIME_1
     *   CKA_PRIME_2
     *
     *   CKA_EXPONENT_1
     *   CKA_EXPONENT_2
     *
     *   CKA_COEFFICIENT
     */
#define PRIV_ATTRIB_EXTENDED_NUM (PRIV_ATTRIB_NORMAL_NUM + 5)

    /*
     * If we have the prime, prime exponents, and coefficient, we can
     * copy them in.
     */
    bool has_extra_data = (rsa->p != NULL) && (rsa->q != NULL) && (rsa->dmp1 != NULL) &&
            (rsa->dmq1 != NULL) && (rsa->iqmp != NULL);

    Unique_CK_ATTRIBUTE privateKeyTemplate(new CK_ATTRIBUTE[
            has_extra_data ? PRIV_ATTRIB_EXTENDED_NUM : PRIV_ATTRIB_NORMAL_NUM]);

    CK_OBJECT_CLASS privClass = CKO_PRIVATE_KEY;

    size_t templateOffset = 0;

    set_attribute(&privateKeyTemplate[templateOffset++], CKA_ID, objId->get(), objId->length());
    set_attribute(&privateKeyTemplate[templateOffset++], CKA_TOKEN, &bTRUE, sizeof(bTRUE));
    set_attribute(&privateKeyTemplate[templateOffset++], CKA_CLASS, &privClass, sizeof(privClass));
    set_attribute(&privateKeyTemplate[templateOffset++], CKA_KEY_TYPE, &rsaType, sizeof(rsaType));

    set_attribute(&privateKeyTemplate[templateOffset++], CKA_DECRYPT, &bTRUE, sizeof(bTRUE));
    set_attribute(&privateKeyTemplate[templateOffset++], CKA_SIGN, &bTRUE, sizeof(bTRUE));

    set_attribute(&privateKeyTemplate[templateOffset++], CKA_MODULUS, modulus->get(),
            modulus->length());
    set_attribute(&privateKeyTemplate[templateOffset++], CKA_PUBLIC_EXPONENT,
            publicExponent->get(), publicExponent->length());
    set_attribute(&privateKeyTemplate[templateOffset++], CKA_PRIVATE_EXPONENT,
            privateExponent->get(), privateExponent->length());

    Unique_ByteArray prime1, prime2, exp1, exp2, coeff;
    if (has_extra_data) {
        prime1.reset(bignum_to_array(rsa->p));
        if (prime1->get() == NULL) {
            ALOGW("Could not convert prime1");
            return -1;
        }
        set_attribute(&privateKeyTemplate[templateOffset++], CKA_PRIME_1, prime1->get(),
                prime1->length());

        prime2.reset(bignum_to_array(rsa->q));
        if (prime2->get() == NULL) {
            ALOGW("Could not convert prime2");
            return -1;
        }
        set_attribute(&privateKeyTemplate[templateOffset++], CKA_PRIME_2, prime2->get(),
                prime2->length());

        exp1.reset(bignum_to_array(rsa->dmp1));
        if (exp1->get() == NULL) {
            ALOGW("Could not convert exponent 1");
            return -1;
        }
        set_attribute(&privateKeyTemplate[templateOffset++], CKA_EXPONENT_1, exp1->get(),
                exp1->length());

        exp2.reset(bignum_to_array(rsa->dmq1));
        if (exp2->get() == NULL) {
            ALOGW("Could not convert exponent 2");
            return -1;
        }
        set_attribute(&privateKeyTemplate[templateOffset++], CKA_EXPONENT_2, exp2->get(),
                exp2->length());

        coeff.reset(bignum_to_array(rsa->iqmp));
        if (coeff->get() == NULL) {
            ALOGW("Could not convert coefficient");
            return -1;
        }
        set_attribute(&privateKeyTemplate[templateOffset++], CKA_COEFFICIENT, coeff->get(),
                coeff->length());
    }

    CK_OBJECT_HANDLE hPrivateKey;
    rv = C_CreateObject(session.get(),
            privateKeyTemplate.get(),
            templateOffset,
            &hPrivateKey);
    if (rv != CKR_OK) {
        ALOGE("Creation of private key failed: 0x%x", rv);
        return -1;
    }
    ObjectHandle privateKey(&session, hPrivateKey);

    ALOGV("public handle = 0x%x, private handle = 0x%x", publicKey.get(), privateKey.get());

    return keyblob_save(objId.get(), key_blob, key_blob_length);
}

static int tee_get_keypair_public(const keymaster0_device* dev,
        const uint8_t* key_blob, const size_t key_blob_length,
        uint8_t** x509_data, size_t* x509_data_length) {

    CryptoSession session(reinterpret_cast<CK_SESSION_HANDLE>(dev->context));

    ObjectHandle publicKey(&session);
    ObjectHandle privateKey(&session);

    if (keyblob_restore(&session, key_blob, key_blob_length, &publicKey, &privateKey)) {
        return -1;
    }

    if (x509_data == NULL || x509_data_length == NULL) {
        ALOGW("Provided destination variables were null");
        return -1;
    }

    CK_ATTRIBUTE attributes[] = {
            {CKA_MODULUS,         NULL, 0},
            {CKA_PUBLIC_EXPONENT, NULL, 0},
    };

    // Call first to get the sizes of the values.
    CK_RV rv = C_GetAttributeValue(session.get(), publicKey.get(), attributes,
            sizeof(attributes)/sizeof(CK_ATTRIBUTE));
    if (rv != CKR_OK) {
        ALOGW("Could not query attribute value sizes: 0x%02x", rv);
        return -1;
    }

    ByteArray modulus(new CK_BYTE[attributes[0].ulValueLen], attributes[0].ulValueLen);
    ByteArray exponent(new CK_BYTE[attributes[1].ulValueLen], attributes[1].ulValueLen);

    attributes[0].pValue = modulus.get();
    attributes[1].pValue = exponent.get();

    rv = C_GetAttributeValue(session.get(), publicKey.get(), attributes,
            sizeof(attributes) / sizeof(CK_ATTRIBUTE));
    if (rv != CKR_OK) {
        ALOGW("Could not query attribute values: 0x%02x", rv);
        return -1;
    }

    ALOGV("modulus is %d (ret=%d), exponent is %d (ret=%d)",
            modulus.length(), attributes[0].ulValueLen,
            exponent.length(), attributes[1].ulValueLen);

    /*
     * Work around a bug in the implementation. The first call to measure how large the array
     * should be sometimes returns values that are too large. The call to get the actual value
     * returns the correct length of the array, so use that instead.
     */
    modulus.setLength(attributes[0].ulValueLen);
    exponent.setLength(attributes[1].ulValueLen);

    Unique_RSA rsa(RSA_new());
    if (rsa.get() == NULL) {
        ALOGE("Could not allocate RSA structure");
        return -1;
    }

    rsa->n = BN_bin2bn(reinterpret_cast<const unsigned char*>(modulus.get()), modulus.length(),
            NULL);
    if (rsa->n == NULL) {
        logOpenSSLError("tee_get_keypair_public");
        return -1;
    }

    rsa->e = BN_bin2bn(reinterpret_cast<const unsigned char*>(exponent.get()), exponent.length(),
            NULL);
    if (rsa->e == NULL) {
        logOpenSSLError("tee_get_keypair_public");
        return -1;
    }

    Unique_EVP_PKEY pkey(EVP_PKEY_new());
    if (pkey.get() == NULL) {
        ALOGE("Could not allocate EVP_PKEY structure");
        return -1;
    }
    if (EVP_PKEY_assign_RSA(pkey.get(), rsa.get()) != 1) {
        logOpenSSLError("tee_get_keypair_public");
        return -1;
    }
    OWNERSHIP_TRANSFERRED(rsa);

    int len = i2d_PUBKEY(pkey.get(), NULL);
    if (len <= 0) {
        logOpenSSLError("tee_get_keypair_public");
        return -1;
    }

    UniquePtr<uint8_t> key(static_cast<uint8_t*>(malloc(len)));
    if (key.get() == NULL) {
        ALOGE("Could not allocate memory for public key data");
        return -1;
    }

    unsigned char* tmp = reinterpret_cast<unsigned char*>(key.get());
    if (i2d_PUBKEY(pkey.get(), &tmp) != len) {
        logOpenSSLError("tee_get_keypair_public");
        return -1;
    }

    ALOGV("Length of x509 data is %d", len);
    *x509_data_length = len;
    *x509_data = key.release();

    return 0;
}

static int tee_delete_keypair(const keymaster0_device_t* dev,
            const uint8_t* key_blob, const size_t key_blob_length) {

    CryptoSession session(reinterpret_cast<CK_SESSION_HANDLE>(dev->context));

    ObjectHandle publicKey(&session);
    ObjectHandle privateKey(&session);

    if (keyblob_restore(&session, key_blob, key_blob_length, &publicKey, &privateKey)) {
        return -1;
    }

    // Delete the private key.
    CK_RV rv = C_DestroyObject(session.get(), privateKey.get());
    if (rv != CKR_OK) {
        ALOGW("Could destroy private key object: 0x%02x", rv);
        return -1;
    }

    // Delete the public key.
    rv = C_DestroyObject(session.get(), publicKey.get());
    if (rv != CKR_OK) {
        ALOGW("Could destroy public key object: 0x%02x", rv);
        return -1;
    }

    return 0;
}

static int tee_sign_data(const keymaster0_device_t* dev,
        const void* params,
        const uint8_t* key_blob, const size_t key_blob_length,
        const uint8_t* data, const size_t dataLength,
        uint8_t** signedData, size_t* signedDataLength) {
    ALOGV("tee_sign_data(%p, %p, %llu, %p, %llu, %p, %p)", dev, key_blob,
            (unsigned long long) key_blob_length, data, (unsigned long long) dataLength, signedData,
            signedDataLength);

    if (params == NULL) {
        ALOGW("Signing params were null");
        return -1;
    }

    CryptoSession session(reinterpret_cast<CK_SESSION_HANDLE>(dev->context));

    ObjectHandle publicKey(&session);
    ObjectHandle privateKey(&session);

    if (keyblob_restore(&session, key_blob, key_blob_length, &publicKey, &privateKey)) {
        return -1;
    }
    ALOGV("public handle = 0x%x, private handle = 0x%x", publicKey.get(), privateKey.get());

    keymaster_rsa_sign_params_t* sign_params = (keymaster_rsa_sign_params_t*) params;
    if (sign_params->digest_type != DIGEST_NONE) {
        ALOGW("Cannot handle digest type %d", sign_params->digest_type);
        return -1;
    } else if (sign_params->padding_type != PADDING_NONE) {
        ALOGW("Cannot handle padding type %d", sign_params->padding_type);
        return -1;
    }

    CK_MECHANISM rawRsaMechanism = {
            CKM_RSA_X_509, NULL, 0
    };

    CK_RV rv = C_SignInit(session.get(), &rawRsaMechanism, privateKey.get());
    if (rv != CKR_OK) {
        ALOGV("C_SignInit failed: 0x%x", rv);
        return -1;
    }

    CK_BYTE signature[1024];
    CK_ULONG signatureLength = 1024;

    rv = C_Sign(session.get(), data, dataLength, signature, &signatureLength);
    if (rv != CKR_OK) {
        ALOGV("C_SignFinal failed: 0x%x", rv);
        return -1;
    }

    UniquePtr<uint8_t[]> finalSignature(new uint8_t[signatureLength]);
    if (finalSignature.get() == NULL) {
        ALOGE("Couldn't allocate memory to copy signature");
        return -1;
    }

    memcpy(finalSignature.get(), signature, signatureLength);

    *signedData = finalSignature.release();
    *signedDataLength = static_cast<size_t>(signatureLength);

    ALOGV("tee_sign_data(%p, %p, %llu, %p, %llu, %p, %p) => %p size %llu", dev, key_blob,
            (unsigned long long) key_blob_length, data, (unsigned long long) dataLength, signedData,
            signedDataLength, *signedData, (unsigned long long) *signedDataLength);

    return 0;
}

static int tee_verify_data(const keymaster0_device_t* dev,
        const void* params,
        const uint8_t* keyBlob, const size_t keyBlobLength,
        const uint8_t* signedData, const size_t signedDataLength,
        const uint8_t* signature, const size_t signatureLength) {
    ALOGV("tee_verify_data(%p, %p, %llu, %p, %llu, %p, %llu)", dev, keyBlob,
            (unsigned long long) keyBlobLength, signedData, (unsigned long long) signedDataLength,
            signature, (unsigned long long) signatureLength);

    if (params == NULL) {
        ALOGW("Verification params were null");
        return -1;
    }

    CryptoSession session(reinterpret_cast<CK_SESSION_HANDLE>(dev->context));

    ObjectHandle publicKey(&session);
    ObjectHandle privateKey(&session);

    if (keyblob_restore(&session, keyBlob, keyBlobLength, &publicKey, &privateKey)) {
        return -1;
    }
    ALOGV("public handle = 0x%x, private handle = 0x%x", publicKey.get(), privateKey.get());

    keymaster_rsa_sign_params_t* sign_params = (keymaster_rsa_sign_params_t*) params;
    if (sign_params->digest_type != DIGEST_NONE) {
        ALOGW("Cannot handle digest type %d", sign_params->digest_type);
        return -1;
    } else if (sign_params->padding_type != PADDING_NONE) {
        ALOGW("Cannot handle padding type %d", sign_params->padding_type);
        return -1;
    }

    CK_MECHANISM rawRsaMechanism = {
            CKM_RSA_X_509, NULL, 0
    };

    CK_RV rv = C_VerifyInit(session.get(), &rawRsaMechanism, publicKey.get());
    if (rv != CKR_OK) {
        ALOGV("C_VerifyInit failed: 0x%x", rv);
        return -1;
    }

    // This is a bad prototype for this function. C_Verify should have only const args.
    rv = C_Verify(session.get(), signedData, signedDataLength,
            const_cast<unsigned char*>(signature), signatureLength);
    if (rv != CKR_OK) {
        ALOGV("C_Verify failed: 0x%x", rv);
        return -1;
    }

    return 0;
}

/* Close an opened OpenSSL instance */
static int tee_close(hw_device_t *dev) {
    keymaster0_device_t *keymaster_dev = (keymaster0_device_t *) dev;
    if (keymaster_dev != NULL) {
        CK_SESSION_HANDLE handle = reinterpret_cast<CK_SESSION_HANDLE>(keymaster_dev->context);
        if (handle != CK_INVALID_HANDLE) {
            C_CloseSession(handle);
        }
    }

    CK_RV finalizeRV = C_Finalize(NULL_PTR);
    if (finalizeRV != CKR_OK) {
        ALOGE("Error closing the TEE");
    }
    free(dev);

    return 0;
}

/*
 * Generic device handling
 */
static int tee_open(const hw_module_t* module, const char* name,
        hw_device_t** device) {
    if (strcmp(name, KEYSTORE_KEYMASTER) != 0)
        return -EINVAL;

    Unique_keymaster_device_t dev(new keymaster0_device_t);
    if (dev.get() == NULL)
        return -ENOMEM;

    dev->common.tag = HARDWARE_DEVICE_TAG;
    dev->common.version = 1;
    dev->common.module = (struct hw_module_t*) module;
    dev->common.close = tee_close;
    dev->flags = 0;

    dev->generate_keypair = tee_generate_keypair;
    dev->import_keypair = tee_import_keypair;
    dev->get_keypair_public = tee_get_keypair_public;
    dev->delete_keypair = tee_delete_keypair;
    dev->sign_data = tee_sign_data;
    dev->verify_data = tee_verify_data;
    dev->delete_all = NULL;

    CK_RV initializeRV = C_Initialize(NULL);
    if (initializeRV != CKR_OK) {
        ALOGE("Error initializing TEE: 0x%x", initializeRV);
        return -ENODEV;
    }

    CK_INFO info;
    CK_RV infoRV = C_GetInfo(&info);
    if (infoRV != CKR_OK) {
        (void) C_Finalize(NULL_PTR);
        ALOGE("Error getting information about TEE during initialization: 0x%x", infoRV);
        return -ENODEV;
    }

    ALOGI("C_GetInfo cryptokiVer=%d.%d manufID=%s flags=%d libDesc=%s libVer=%d.%d\n",
           info.cryptokiVersion.major, info.cryptokiVersion.minor,
           info.manufacturerID, info.flags, info.libraryDescription,
           info.libraryVersion.major, info.libraryVersion.minor);

    CK_SESSION_HANDLE sessionHandle = CK_INVALID_HANDLE;

    CK_RV openSessionRV = C_OpenSession(CKV_TOKEN_USER,
            CKF_SERIAL_SESSION | CKF_RW_SESSION,
            NULL,
            NULL,
            &sessionHandle);

    if (openSessionRV != CKR_OK || sessionHandle == CK_INVALID_HANDLE) {
        (void) C_Finalize(NULL_PTR);
        ALOGE("Error opening primary session with TEE: 0x%x", openSessionRV);
        return -1;
    }

    ERR_load_crypto_strings();
    ERR_load_BIO_strings();

    dev->context = reinterpret_cast<void*>(sessionHandle);
    *device = reinterpret_cast<hw_device_t*>(dev.release());

    return 0;
}

static struct hw_module_methods_t keystore_module_methods = {
    open: tee_open,
};

struct keystore_module HAL_MODULE_INFO_SYM
__attribute__ ((visibility ("default"))) = {
    common: {
        tag: HARDWARE_MODULE_TAG,
        module_api_version: KEYMASTER_MODULE_API_VERSION_0_3,
        hal_api_version: HARDWARE_HAL_API_VERSION,
        id: KEYSTORE_HARDWARE_MODULE_ID,
        name: "Keymaster TEE HAL",
        author: "The Android Open Source Project",
        methods: &keystore_module_methods,
        dso: 0,
        reserved: {},
    },
};
