/*
 * Copyright (C) 2017 The Android Open Source Project
 * Copyright 2017 NXP
 *
 * 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 <assert.h>
#include <stddef.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <uapi/err.h>

#include <interface/hwkey/hwkey.h>
#include <openssl/aes.h>
#include <openssl/cipher.h>
#include <openssl/digest.h>
#include <openssl/err.h>
#include <openssl/hkdf.h>

#include "caam.h"
#include "common.h"
#include "hwkey_keyslots.h"
#include "hwkey_srv_priv.h"
#include "uuids.h"

#define TLOG_LVL TLOG_LVL_DEFAULT
#define TLOG_TAG "hwkey_caam"
#include "tlog.h"

static const uint8_t skeymod[16] __attribute__((aligned(16))) = {
        0x0f, 0x0e, 0x0d, 0x0c, 0x0b, 0x0a, 0x09, 0x08,
        0x07, 0x06, 0x05, 0x04, 0x03, 0x02, 0x01, 0x00};

static uint8_t kdfv1_key[32] __attribute__((aligned(32)));

/*
 * Derive key V1 - HKDF based key derive.
 */
uint32_t derive_key_v1(const uuid_t* uuid,
                       const uint8_t* ikm_data,
                       size_t ikm_len,
                       uint8_t* key_buf,
                       size_t* key_len) {
    uint32_t res;

    *key_len = 0;

    if (!ikm_len)
        return HWKEY_ERR_BAD_LEN;

    if (!HKDF(key_buf, ikm_len, EVP_sha256(), (const uint8_t*)kdfv1_key,
              sizeof(kdfv1_key), (const uint8_t*)uuid, sizeof(uuid_t), ikm_data,
              ikm_len)) {
        TLOGE("HDKF failed 0x%x\n", ERR_get_error());
        memset(key_buf, 0, ikm_len);
        res = HWKEY_ERR_GENERIC;
        goto done;
    }
    *key_len = ikm_len;
    res = HWKEY_NO_ERROR;
done:
    return res;
}

/*
 *  RPMB Key support
 */
#define RPMB_SS_AUTH_KEY_SIZE 32
#define RPMB_SS_AUTH_KEY_ID "com.android.trusty.storage_auth.rpmb"

/* Secure storage service app uuid */
static const uuid_t ss_uuid = SECURE_STORAGE_SERVER_APP_UUID;
static size_t rpmb_keyblob_len;
static uint8_t rpmb_keyblob[RPMBKEY_LEN];

/*
 * Fetch RPMB Secure Storage Authentication key
 */
static uint32_t get_rpmb_ss_auth_key(const struct hwkey_keyslot* slot,
                                     uint8_t* kbuf,
                                     size_t kbuf_len,
                                     size_t* klen) {
    uint32_t res;
    assert(kbuf_len >= RPMB_SS_AUTH_KEY_SIZE);

    if (rpmb_keyblob_len != sizeof(rpmb_keyblob))
        return HWKEY_ERR_NOT_FOUND; /* no RPMB key */

    res = caam_decap_blob(skeymod, sizeof(skeymod), kbuf, rpmb_keyblob,
                          RPMB_SS_AUTH_KEY_SIZE);
    if (res == CAAM_SUCCESS) {
        *klen = RPMB_SS_AUTH_KEY_SIZE;
        return HWKEY_NO_ERROR;
    } else {
        /* wipe target buffer */
        TLOGE("%s: failed to unpack rpmb key\n", __func__);
        memset(kbuf, 0, RPMB_SS_AUTH_KEY_SIZE);
        return HWKEY_ERR_GENERIC;
    }
}

/*
 *  List of keys slots that hwkey service supports
 */
static const struct hwkey_keyslot _keys[] = {
        {
                .uuid = &ss_uuid,
                .key_id = RPMB_SS_AUTH_KEY_ID,
                .handler = get_rpmb_ss_auth_key,
        },
};

static void unpack_kbox(void) {
    uint32_t res;
    struct keyslot_package* kbox = caam_get_keybox();

    if (strncmp(kbox->magic, KEYPACK_MAGIC, 4)) {
        TLOGE("Invalid magic\n");
        abort();
    }

    /* Copy RPMB blob */
    assert(!rpmb_keyblob_len); /* key should be unset */
    if (kbox->rpmb_keyblob_len != sizeof(rpmb_keyblob)) {
        TLOGE("Unexpected RPMB key len: %u\n", kbox->rpmb_keyblob_len);
    } else {
        memcpy(rpmb_keyblob, kbox->rpmb_keyblob, kbox->rpmb_keyblob_len);
        rpmb_keyblob_len = kbox->rpmb_keyblob_len;
    }

    /* generate kdfv1 root it should never fail */
    res = caam_gen_kdfv1_root_key(kdfv1_key, sizeof(kdfv1_key));
    assert(res == CAAM_SUCCESS);

    /* copy pubkey blob */

    /* wipe kbox in sram */
    memset(kbox, 0, sizeof(*kbox));
}

/*
 *  Initialize Fake HWKEY service provider
 */
void hwkey_init_srv_provider(void) {
    int rc;

    TLOGI("Init HWKEY service provider\n");

    unpack_kbox();

    /* install key handlers */
    hwkey_install_keys(_keys, countof(_keys));

    /* start service */
    rc = hwkey_start_service();
    if (rc != NO_ERROR) {
        TLOGE("failed (%d) to start HWKEY service\n", rc);
    }
}
