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