1 // SPDX-License-Identifier: BSD-2-Clause
2 /*
3  * Copyright 2020 NXP
4  */
5 
6 #include <drivers/imx/dcp.h>
7 #include <kernel/tee_common_otp.h>
8 #include <local.h>
9 #include <trace.h>
10 
11 #define HUK_MESSAGE_NULL_BYTE 0
12 #define NB_ITERATION_HUK      1
13 #define HUK_SIZE_BITS	      128
14 
15 /* State of the generated HUK */
16 enum dcp_huk_state {
17 	DCP_HUK_EMPTY = 0,
18 	DCP_HUK_GENERATED,
19 	DCP_HUK_ERROR,
20 };
21 
22 /* Information about HUK */
23 static struct {
24 	enum dcp_huk_state state;
25 	uint8_t data[HW_UNIQUE_KEY_LENGTH];
26 } dcp_huk = { .state = DCP_HUK_EMPTY };
27 
28 /*
29  * Generate Hardware Unique Key using the Data Co-Processor (DCP) AES128-CMAC
30  * cryptographic operation
31  * Follow dcp_aes_cmac() message format
32  *
33  * @hwkey   [out] Hardware Unique Key private data
34  */
dcp_generate_huk(struct tee_hw_unique_key * hwkey)35 static TEE_Result dcp_generate_huk(struct tee_hw_unique_key *hwkey)
36 {
37 	TEE_Result res = TEE_ERROR_GENERIC;
38 	struct dcp_cipher_init init = {
39 		.key_mode = DCP_OTP,
40 		.mode = DCP_ECB,
41 		.op = DCP_ENCRYPT,
42 	};
43 	uint8_t content[DCP_AES128_BLOCK_SIZE] = { NB_ITERATION_HUK,
44 						   'h',
45 						   'u',
46 						   'k',
47 						   HUK_MESSAGE_NULL_BYTE,
48 						   'o',
49 						   'p',
50 						   't',
51 						   'e',
52 						   'e',
53 						   'o',
54 						   's',
55 						   'd',
56 						   'c',
57 						   'p',
58 						   HUK_SIZE_BITS };
59 
60 	res = dcp_cmac(&init, content, DCP_AES128_BLOCK_SIZE, hwkey->data);
61 
62 	dcp_disable_unique_key();
63 
64 	return res;
65 }
66 
tee_otp_get_hw_unique_key(struct tee_hw_unique_key * hwkey)67 TEE_Result tee_otp_get_hw_unique_key(struct tee_hw_unique_key *hwkey)
68 {
69 	TEE_Result ret = TEE_ERROR_GENERIC;
70 
71 	if (!hwkey) {
72 		EMSG("HUK generation failed, hwkey structure is NULL");
73 		return TEE_ERROR_BAD_PARAMETERS;
74 	}
75 
76 	ret = dcp_init();
77 	if (ret != TEE_SUCCESS) {
78 		dcp_huk.state = DCP_HUK_ERROR;
79 		return ret;
80 	}
81 
82 	if (dcp_huk.state == DCP_HUK_EMPTY) {
83 		ret = dcp_generate_huk(hwkey);
84 		if (ret != TEE_SUCCESS) {
85 			dcp_huk.state = DCP_HUK_ERROR;
86 		} else {
87 			memcpy(dcp_huk.data, hwkey->data, HW_UNIQUE_KEY_LENGTH);
88 			dcp_huk.state = DCP_HUK_GENERATED;
89 		}
90 	} else if (dcp_huk.state == DCP_HUK_GENERATED) {
91 		memcpy(hwkey->data, dcp_huk.data, HW_UNIQUE_KEY_LENGTH);
92 		ret = TEE_SUCCESS;
93 	} else {
94 		ret = TEE_ERROR_GENERIC;
95 	}
96 
97 	return ret;
98 }
99