xref: /optee_os/core/drivers/imx/dcp/dcp_huk.c (revision c0e8ad830e2c3c0f6b1d451ada925b9b8c89ff8a)
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