193e678edSClement Faure // SPDX-License-Identifier: BSD-2-Clause
293e678edSClement Faure /*
393e678edSClement Faure * Copyright 2020 NXP
493e678edSClement Faure */
593e678edSClement Faure
693e678edSClement Faure #include <drivers/imx/dcp.h>
793e678edSClement Faure #include <kernel/tee_common_otp.h>
893e678edSClement Faure #include <local.h>
993e678edSClement Faure #include <trace.h>
1093e678edSClement Faure
1193e678edSClement Faure #define HUK_MESSAGE_NULL_BYTE 0
1293e678edSClement Faure #define NB_ITERATION_HUK 1
1393e678edSClement Faure #define HUK_SIZE_BITS 128
1493e678edSClement Faure
1593e678edSClement Faure /* State of the generated HUK */
1693e678edSClement Faure enum dcp_huk_state {
1793e678edSClement Faure DCP_HUK_EMPTY = 0,
1893e678edSClement Faure DCP_HUK_GENERATED,
1993e678edSClement Faure DCP_HUK_ERROR,
2093e678edSClement Faure };
2193e678edSClement Faure
2293e678edSClement Faure /* Information about HUK */
2393e678edSClement Faure static struct {
2493e678edSClement Faure enum dcp_huk_state state;
2593e678edSClement Faure uint8_t data[HW_UNIQUE_KEY_LENGTH];
2693e678edSClement Faure } dcp_huk = { .state = DCP_HUK_EMPTY };
2793e678edSClement Faure
2893e678edSClement Faure /*
2993e678edSClement Faure * Generate Hardware Unique Key using the Data Co-Processor (DCP) AES128-CMAC
3093e678edSClement Faure * cryptographic operation
3193e678edSClement Faure * Follow dcp_aes_cmac() message format
3293e678edSClement Faure *
3393e678edSClement Faure * @hwkey [out] Hardware Unique Key private data
3493e678edSClement Faure */
dcp_generate_huk(struct tee_hw_unique_key * hwkey)3593e678edSClement Faure static TEE_Result dcp_generate_huk(struct tee_hw_unique_key *hwkey)
3693e678edSClement Faure {
373fc5c287SClement Faure TEE_Result res = TEE_ERROR_GENERIC;
3893e678edSClement Faure struct dcp_cipher_init init = {
3993e678edSClement Faure .key_mode = DCP_OTP,
4093e678edSClement Faure .mode = DCP_ECB,
4193e678edSClement Faure .op = DCP_ENCRYPT,
4293e678edSClement Faure };
4393e678edSClement Faure uint8_t content[DCP_AES128_BLOCK_SIZE] = { NB_ITERATION_HUK,
4493e678edSClement Faure 'h',
4593e678edSClement Faure 'u',
4693e678edSClement Faure 'k',
4793e678edSClement Faure HUK_MESSAGE_NULL_BYTE,
4893e678edSClement Faure 'o',
4993e678edSClement Faure 'p',
5093e678edSClement Faure 't',
5193e678edSClement Faure 'e',
5293e678edSClement Faure 'e',
5393e678edSClement Faure 'o',
5493e678edSClement Faure 's',
5593e678edSClement Faure 'd',
5693e678edSClement Faure 'c',
5793e678edSClement Faure 'p',
5893e678edSClement Faure HUK_SIZE_BITS };
5993e678edSClement Faure
603fc5c287SClement Faure res = dcp_cmac(&init, content, DCP_AES128_BLOCK_SIZE, hwkey->data);
613fc5c287SClement Faure
623fc5c287SClement Faure dcp_disable_unique_key();
633fc5c287SClement Faure
643fc5c287SClement Faure return res;
6593e678edSClement Faure }
6693e678edSClement Faure
tee_otp_get_hw_unique_key(struct tee_hw_unique_key * hwkey)6793e678edSClement Faure TEE_Result tee_otp_get_hw_unique_key(struct tee_hw_unique_key *hwkey)
6893e678edSClement Faure {
6993e678edSClement Faure TEE_Result ret = TEE_ERROR_GENERIC;
7093e678edSClement Faure
71*c0e8ad83SJose Quaresma if (!hwkey) {
7293e678edSClement Faure EMSG("HUK generation failed, hwkey structure is NULL");
7393e678edSClement Faure return TEE_ERROR_BAD_PARAMETERS;
7493e678edSClement Faure }
7593e678edSClement Faure
7693e678edSClement Faure ret = dcp_init();
7793e678edSClement Faure if (ret != TEE_SUCCESS) {
7893e678edSClement Faure dcp_huk.state = DCP_HUK_ERROR;
7993e678edSClement Faure return ret;
8093e678edSClement Faure }
8193e678edSClement Faure
8293e678edSClement Faure if (dcp_huk.state == DCP_HUK_EMPTY) {
8393e678edSClement Faure ret = dcp_generate_huk(hwkey);
8493e678edSClement Faure if (ret != TEE_SUCCESS) {
8593e678edSClement Faure dcp_huk.state = DCP_HUK_ERROR;
8693e678edSClement Faure } else {
8793e678edSClement Faure memcpy(dcp_huk.data, hwkey->data, HW_UNIQUE_KEY_LENGTH);
8893e678edSClement Faure dcp_huk.state = DCP_HUK_GENERATED;
8993e678edSClement Faure }
9093e678edSClement Faure } else if (dcp_huk.state == DCP_HUK_GENERATED) {
9193e678edSClement Faure memcpy(hwkey->data, dcp_huk.data, HW_UNIQUE_KEY_LENGTH);
9293e678edSClement Faure ret = TEE_SUCCESS;
9393e678edSClement Faure } else {
9493e678edSClement Faure ret = TEE_ERROR_GENERIC;
9593e678edSClement Faure }
9693e678edSClement Faure
9793e678edSClement Faure return ret;
9893e678edSClement Faure }
99