xref: /optee_os/core/drivers/stm32mp15_huk.c (revision 9f0072258fe062fa3932d4eb4d625170b04c25c1)
1 // SPDX-License-Identifier: BSD-2-Clause
2 /*
3  * Copyright (c) 2022, Linaro Limited
4  * Copyright (c) 2022, Foundries.io Limited
5  */
6 
7 #include <assert.h>
8 #include <config.h>
9 #include <crypto/crypto.h>
10 #include <drivers/stm32_bsec.h>
11 #include <kernel/tee_common_otp.h>
12 #include <mempool.h>
13 #include <platform_config.h>
14 #include <stm32_util.h>
15 #include <string.h>
16 #include <string_ext.h>
17 
18 #define HUK_NB_OTP (HW_UNIQUE_KEY_LENGTH / sizeof(uint32_t))
19 
20 static bool stm32mp15_huk_init;
21 
stm32mp15_read_uid(uint32_t * uid)22 static TEE_Result stm32mp15_read_uid(uint32_t *uid)
23 {
24 	TEE_Result ret = TEE_ERROR_GENERIC;
25 	uint32_t *q = uid;
26 	uint32_t otp_idx = 0;
27 	size_t __maybe_unused sz = 0;
28 	uint8_t __maybe_unused offset = 0;
29 
30 	ret = stm32_bsec_find_otp_in_nvmem_layout("uid_otp", &otp_idx, &offset,
31 						  &sz);
32 	if (ret)
33 		return ret;
34 	assert(sz == 3 * 32);
35 	assert(offset == 0);
36 
37 	/*
38 	 * Shadow memory for UID words might not be locked: to guarante that
39 	 * the final values are read we must lock them.
40 	 */
41 	if (stm32_bsec_set_sw_lock(otp_idx) ||
42 	    stm32_bsec_shadow_read_otp(q++, otp_idx))
43 		return TEE_ERROR_GENERIC;
44 
45 	if (stm32_bsec_set_sw_lock(otp_idx + 1) ||
46 	    stm32_bsec_shadow_read_otp(q++, otp_idx + 1))
47 		return TEE_ERROR_GENERIC;
48 
49 	if (stm32_bsec_set_sw_lock(otp_idx + 2) ||
50 	    stm32_bsec_shadow_read_otp(q++, otp_idx + 2))
51 		return TEE_ERROR_GENERIC;
52 
53 	return TEE_SUCCESS;
54 }
55 
stm32mp15_read_otp(uint32_t otp,uint32_t * key,bool * locked)56 static TEE_Result stm32mp15_read_otp(uint32_t otp, uint32_t *key, bool *locked)
57 {
58 	bool tmp = true;
59 	uint32_t state = 0;
60 
61 	if (stm32_bsec_get_state(&state))
62 		panic();
63 
64 	if (state != BSEC_STATE_SEC_CLOSED) {
65 		/*
66 		 * When the device is not closed, the shadow memory for these
67 		 * words might not be locked: check and report them
68 		 */
69 		if (stm32_bsec_read_permanent_lock(otp, &tmp))
70 			return TEE_ERROR_GENERIC;
71 
72 		if (tmp && stm32_bsec_read_sw_lock(otp, &tmp))
73 			return TEE_ERROR_GENERIC;
74 	}
75 
76 	if (stm32_bsec_shadow_read_otp(key, otp))
77 		return TEE_ERROR_GENERIC;
78 
79 	*locked = *locked && tmp;
80 
81 	return TEE_SUCCESS;
82 }
83 
84 /*
85  *  AES-GCM: nonce must be unique per message and key.
86  *
87  *  This function always uses the same key - once its locked - with the same
88  *  unique message hence the nonce can be any constant.
89  */
aes_gcm_encrypt_uid(uint8_t * key,size_t key_len,uint8_t * out,size_t * out_len)90 static TEE_Result aes_gcm_encrypt_uid(uint8_t *key, size_t key_len,
91 				      uint8_t *out, size_t *out_len)
92 {
93 	TEE_Result ret = TEE_ERROR_GENERIC;
94 	const uint8_t nonce[12] = { 0x55 };
95 	uint32_t uid[4] = { 0 };
96 	uint8_t tag[16] = { 0 };
97 	size_t nonce_len = sizeof(nonce);
98 	size_t tag_len = sizeof(tag);
99 	size_t uid_len = sizeof(uid);
100 	void *ctx = NULL;
101 
102 	ret = stm32mp15_read_uid(uid);
103 	if (ret)
104 		goto out;
105 
106 	ret = crypto_authenc_alloc_ctx(&ctx, TEE_ALG_AES_GCM);
107 	if (ret)
108 		goto out;
109 
110 	ret = crypto_authenc_init(ctx, TEE_MODE_ENCRYPT, key, key_len, nonce,
111 				  nonce_len, TEE_AES_BLOCK_SIZE, 0, uid_len);
112 	if (ret)
113 		goto out_free_ctx;
114 
115 	ret = crypto_authenc_enc_final(ctx, (uint8_t *)uid, sizeof(uid),
116 				       out, out_len, tag, &tag_len);
117 	if (ret)
118 		goto out_free_ctx;
119 
120 	crypto_authenc_final(ctx);
121 out_free_ctx:
122 	crypto_authenc_free_ctx(ctx);
123 out:
124 	if (ret)
125 		memzero_explicit(out, *out_len);
126 
127 	return ret;
128 }
129 
pos_from_dt(uint32_t otp_id[HUK_NB_OTP])130 static __maybe_unused TEE_Result pos_from_dt(uint32_t otp_id[HUK_NB_OTP])
131 {
132 	TEE_Result ret = TEE_SUCCESS;
133 	uint32_t otp_start = 0;
134 	size_t sz = 0;
135 	uint8_t offset = 0;
136 	size_t i = 0;
137 
138 	ret = stm32_bsec_find_otp_in_nvmem_layout("huk-otp", &otp_start,
139 						  &offset, &sz);
140 	if (ret)
141 		return ret;
142 
143 	if (sz != (HW_UNIQUE_KEY_LENGTH * CHAR_BIT) || offset != 0)
144 		return TEE_ERROR_SECURITY;
145 
146 	for (i = 0; i < HUK_NB_OTP; i++)
147 		otp_id[i] = otp_start + i;
148 
149 	return TEE_SUCCESS;
150 }
151 
get_otp_pos(uint32_t otp_id[HUK_NB_OTP])152 static TEE_Result get_otp_pos(uint32_t otp_id[HUK_NB_OTP])
153 {
154 #ifdef CFG_STM32_HUK_FROM_DT
155 	return pos_from_dt(otp_id);
156 #else /* CFG_STM32_HUK_FROM_DT */
157 
158 	static_assert(CFG_STM32MP15_HUK_BSEC_KEY_0 < STM32MP1_OTP_MAX_ID);
159 	static_assert(CFG_STM32MP15_HUK_BSEC_KEY_1 < STM32MP1_OTP_MAX_ID);
160 	static_assert(CFG_STM32MP15_HUK_BSEC_KEY_2 < STM32MP1_OTP_MAX_ID);
161 	static_assert(CFG_STM32MP15_HUK_BSEC_KEY_3 < STM32MP1_OTP_MAX_ID);
162 
163 	otp_id[0] = CFG_STM32MP15_HUK_BSEC_KEY_0;
164 	otp_id[1] = CFG_STM32MP15_HUK_BSEC_KEY_1;
165 	otp_id[2] = CFG_STM32MP15_HUK_BSEC_KEY_2;
166 	otp_id[3] = CFG_STM32MP15_HUK_BSEC_KEY_3;
167 
168 	return TEE_SUCCESS;
169 #endif /* CFG_STM32_HUK_FROM_DT */
170 }
171 
tee_otp_get_hw_unique_key(struct tee_hw_unique_key * hwkey)172 TEE_Result tee_otp_get_hw_unique_key(struct tee_hw_unique_key *hwkey)
173 {
174 	uint32_t otp_key[HUK_NB_OTP] = { };
175 	uint32_t otp_id[HUK_NB_OTP] = { };
176 	size_t len = HW_UNIQUE_KEY_LENGTH;
177 	TEE_Result ret = TEE_SUCCESS;
178 	uint32_t *key = otp_key;
179 	bool lock = true;
180 	size_t i = 0;
181 
182 	ret = get_otp_pos(otp_id);
183 	if (ret)
184 		return ret;
185 
186 	for (i = 0; i < HUK_NB_OTP; i++) {
187 		ret = stm32mp15_read_otp(otp_id[i], key++, &lock);
188 		if (ret)
189 			goto out;
190 	}
191 
192 	if (IS_ENABLED(CFG_STM32MP15_HUK_BSEC_KEY)) {
193 		static_assert(sizeof(otp_key) == HW_UNIQUE_KEY_LENGTH);
194 		memcpy(hwkey->data, otp_key, HW_UNIQUE_KEY_LENGTH);
195 		ret = TEE_SUCCESS;
196 		goto out;
197 	}
198 
199 	if (IS_ENABLED(CFG_STM32MP15_HUK_BSEC_DERIVE_UID)) {
200 		ret = aes_gcm_encrypt_uid((uint8_t *)otp_key, len, hwkey->data,
201 					  &len);
202 		if (len != HW_UNIQUE_KEY_LENGTH)
203 			ret = TEE_ERROR_GENERIC;
204 		goto out;
205 	}
206 
207 	panic();
208 
209 out:
210 	memzero_explicit(otp_key, HW_UNIQUE_KEY_LENGTH);
211 
212 	if (!ret && !stm32mp15_huk_init) {
213 		stm32mp15_huk_init = true;
214 		IMSG("HUK %slocked", lock ? "" : "un");
215 		DHEXDUMP(hwkey->data, HW_UNIQUE_KEY_LENGTH);
216 	}
217 
218 	return ret;
219 }
220 
221