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 	struct dcp_cipher_init init = {
38 		.key_mode = DCP_OTP,
39 		.mode = DCP_ECB,
40 		.op = DCP_ENCRYPT,
41 	};
42 	uint8_t content[DCP_AES128_BLOCK_SIZE] = { NB_ITERATION_HUK,
43 						   'h',
44 						   'u',
45 						   'k',
46 						   HUK_MESSAGE_NULL_BYTE,
47 						   'o',
48 						   'p',
49 						   't',
50 						   'e',
51 						   'e',
52 						   'o',
53 						   's',
54 						   'd',
55 						   'c',
56 						   'p',
57 						   HUK_SIZE_BITS };
58 
59 	return dcp_cmac(&init, content, DCP_AES128_BLOCK_SIZE, hwkey->data);
60 }
61 
tee_otp_get_hw_unique_key(struct tee_hw_unique_key * hwkey)62 TEE_Result tee_otp_get_hw_unique_key(struct tee_hw_unique_key *hwkey)
63 {
64 	TEE_Result ret = TEE_ERROR_GENERIC;
65 
66 	if (!hwkey || !hwkey->data) {
67 		EMSG("HUK generation failed, hwkey structure is NULL");
68 		return TEE_ERROR_BAD_PARAMETERS;
69 	}
70 
71 	ret = dcp_init();
72 	if (ret != TEE_SUCCESS) {
73 		dcp_huk.state = DCP_HUK_ERROR;
74 		return ret;
75 	}
76 
77 	if (dcp_huk.state == DCP_HUK_EMPTY) {
78 		ret = dcp_generate_huk(hwkey);
79 		if (ret != TEE_SUCCESS) {
80 			dcp_huk.state = DCP_HUK_ERROR;
81 		} else {
82 			memcpy(dcp_huk.data, hwkey->data, HW_UNIQUE_KEY_LENGTH);
83 			dcp_huk.state = DCP_HUK_GENERATED;
84 		}
85 	} else if (dcp_huk.state == DCP_HUK_GENERATED) {
86 		memcpy(hwkey->data, dcp_huk.data, HW_UNIQUE_KEY_LENGTH);
87 		ret = TEE_SUCCESS;
88 	} else {
89 		ret = TEE_ERROR_GENERIC;
90 	}
91 
92 	return ret;
93 }
94