xref: /optee_os/core/tee/tee_fs_key_manager.c (revision b1d7375c01ec8bcbf3561d27425d320afed23bce)
1 // SPDX-License-Identifier: BSD-2-Clause
2 /*
3  * Copyright (c) 2015, Linaro Limited
4  */
5 
6 
7 /*
8  * Acronyms:
9  *
10  * FEK - File Encryption Key
11  * SSK - Secure Storage Key
12  * TSK - Trusted app Storage Key
13  * IV  - Initial vector
14  * HUK - Hardware Unique Key
15  * RNG - Random Number Generator
16  */
17 
18 #include <compiler.h>
19 #include <crypto/crypto.h>
20 #include <initcall.h>
21 #include <kernel/panic.h>
22 #include <kernel/tee_common_otp.h>
23 #include <kernel/tee_ta_manager.h>
24 #include <stdlib.h>
25 #include <string.h>
26 #include <tee/tee_cryp_utl.h>
27 #include <tee/tee_fs_key_manager.h>
28 #include <trace.h>
29 #include <util.h>
30 
31 struct tee_fs_ssk {
32 	bool is_init;
33 	uint8_t key[TEE_FS_KM_SSK_SIZE];
34 };
35 
36 static struct tee_fs_ssk tee_fs_ssk;
37 static uint8_t string_for_ssk_gen[] = "ONLY_FOR_tee_fs_ssk";
38 
39 
40 static TEE_Result do_hmac(void *out_key, size_t out_key_size,
41 			  const void *in_key, size_t in_key_size,
42 			  const void *message, size_t message_size)
43 {
44 	TEE_Result res = TEE_ERROR_GENERIC;
45 	uint8_t *ctx = NULL;
46 	size_t hash_ctx_size = 0;
47 
48 	if (!out_key || !in_key || !message)
49 		return TEE_ERROR_BAD_PARAMETERS;
50 
51 	res = crypto_mac_get_ctx_size(TEE_FS_KM_HMAC_ALG, &hash_ctx_size);
52 	if (res != TEE_SUCCESS)
53 		return res;
54 
55 	ctx = malloc(hash_ctx_size);
56 	if (!ctx)
57 		return TEE_ERROR_OUT_OF_MEMORY;
58 
59 	res = crypto_mac_init(ctx, TEE_FS_KM_HMAC_ALG, in_key, in_key_size);
60 	if (res != TEE_SUCCESS)
61 		goto exit;
62 
63 	res = crypto_mac_update(ctx, TEE_FS_KM_HMAC_ALG, message, message_size);
64 	if (res != TEE_SUCCESS)
65 		goto exit;
66 
67 	res = crypto_mac_final(ctx, TEE_FS_KM_HMAC_ALG, out_key, out_key_size);
68 	if (res != TEE_SUCCESS)
69 		goto exit;
70 
71 	res = TEE_SUCCESS;
72 
73 exit:
74 	free(ctx);
75 	return res;
76 }
77 
78 TEE_Result tee_fs_fek_crypt(const TEE_UUID *uuid, TEE_OperationMode mode,
79 			    const uint8_t *in_key, size_t size,
80 			    uint8_t *out_key)
81 {
82 	TEE_Result res;
83 	uint8_t *ctx = NULL;
84 	size_t ctx_size;
85 	uint8_t tsk[TEE_FS_KM_TSK_SIZE];
86 	uint8_t dst_key[size];
87 
88 	if (!in_key || !out_key)
89 		return TEE_ERROR_BAD_PARAMETERS;
90 
91 	if (size != TEE_FS_KM_FEK_SIZE)
92 		return TEE_ERROR_BAD_PARAMETERS;
93 
94 	if (tee_fs_ssk.is_init == 0)
95 		return TEE_ERROR_GENERIC;
96 
97 	if (uuid) {
98 		res = do_hmac(tsk, sizeof(tsk), tee_fs_ssk.key,
99 			      TEE_FS_KM_SSK_SIZE, uuid, sizeof(*uuid));
100 		if (res != TEE_SUCCESS)
101 			return res;
102 	} else {
103 		/*
104 		 * Pick something of a different size than TEE_UUID to
105 		 * guarantee that there's never a conflict.
106 		 */
107 		uint8_t dummy[1] = { 0 };
108 
109 		res = do_hmac(tsk, sizeof(tsk), tee_fs_ssk.key,
110 			      TEE_FS_KM_SSK_SIZE, dummy, sizeof(dummy));
111 		if (res != TEE_SUCCESS)
112 			return res;
113 	}
114 
115 	res = crypto_cipher_get_ctx_size(TEE_FS_KM_ENC_FEK_ALG, &ctx_size);
116 	if (res != TEE_SUCCESS)
117 		return res;
118 
119 	ctx = malloc(ctx_size);
120 	if (!ctx)
121 		return TEE_ERROR_OUT_OF_MEMORY;
122 
123 	res = crypto_cipher_init(ctx, TEE_FS_KM_ENC_FEK_ALG, mode, tsk,
124 				 sizeof(tsk), NULL, 0, NULL, 0);
125 	if (res != TEE_SUCCESS)
126 		goto exit;
127 
128 	res = crypto_cipher_update(ctx, TEE_FS_KM_ENC_FEK_ALG,
129 				   mode, true, in_key, size, dst_key);
130 	if (res != TEE_SUCCESS)
131 		goto exit;
132 
133 	crypto_cipher_final(ctx, TEE_FS_KM_ENC_FEK_ALG);
134 
135 	memcpy(out_key, dst_key, sizeof(dst_key));
136 
137 exit:
138 	free(ctx);
139 
140 	return res;
141 }
142 
143 static TEE_Result generate_fek(uint8_t *key, uint8_t len)
144 {
145 	return crypto_rng_read(key, len);
146 }
147 
148 static TEE_Result tee_fs_init_key_manager(void)
149 {
150 	int res = TEE_SUCCESS;
151 	struct tee_hw_unique_key huk;
152 	uint8_t chip_id[TEE_FS_KM_CHIP_ID_LENGTH];
153 	uint8_t message[sizeof(chip_id) + sizeof(string_for_ssk_gen)];
154 
155 	/* Secure Storage Key Generation:
156 	 *
157 	 *     SSK = HMAC(HUK, message)
158 	 *     message := concatenate(chip_id, static string)
159 	 * */
160 	tee_otp_get_hw_unique_key(&huk);
161 	tee_otp_get_die_id(chip_id, sizeof(chip_id));
162 
163 	memcpy(message, chip_id, sizeof(chip_id));
164 	memcpy(message + sizeof(chip_id), string_for_ssk_gen,
165 			sizeof(string_for_ssk_gen));
166 
167 	res = do_hmac(tee_fs_ssk.key, sizeof(tee_fs_ssk.key),
168 			huk.data, sizeof(huk.data),
169 			message, sizeof(message));
170 
171 	if (res == TEE_SUCCESS)
172 		tee_fs_ssk.is_init = 1;
173 
174 	return res;
175 }
176 
177 TEE_Result tee_fs_generate_fek(const TEE_UUID *uuid, void *buf, size_t buf_size)
178 {
179 	TEE_Result res;
180 
181 	if (buf_size != TEE_FS_KM_FEK_SIZE)
182 		return TEE_ERROR_BAD_PARAMETERS;
183 
184 	res = generate_fek(buf, TEE_FS_KM_FEK_SIZE);
185 	if (res != TEE_SUCCESS)
186 		return res;
187 
188 	return tee_fs_fek_crypt(uuid, TEE_MODE_ENCRYPT, buf,
189 				TEE_FS_KM_FEK_SIZE, buf);
190 }
191 
192 static TEE_Result sha256(uint8_t *out, size_t out_size, const uint8_t *in,
193 			 size_t in_size)
194 {
195 	TEE_Result res;
196 	uint8_t *ctx = NULL;
197 	size_t ctx_size;
198 	uint32_t algo = TEE_ALG_SHA256;
199 
200 	res = crypto_hash_get_ctx_size(algo, &ctx_size);
201 	if (res != TEE_SUCCESS)
202 		return res;
203 
204 	ctx = malloc(ctx_size);
205 	if (!ctx)
206 		return TEE_ERROR_OUT_OF_MEMORY;
207 
208 	res = crypto_hash_init(ctx, algo);
209 	if (res != TEE_SUCCESS)
210 		goto out;
211 
212 	res = crypto_hash_update(ctx, algo, in, in_size);
213 	if (res != TEE_SUCCESS)
214 		goto out;
215 
216 	res = crypto_hash_final(ctx, algo, out, out_size);
217 
218 out:
219 	free(ctx);
220 	return res;
221 }
222 
223 static TEE_Result aes_ecb(uint8_t out[TEE_AES_BLOCK_SIZE],
224 			  const uint8_t in[TEE_AES_BLOCK_SIZE],
225 			  const uint8_t *key, size_t key_size)
226 {
227 	TEE_Result res;
228 	uint8_t *ctx = NULL;
229 	size_t ctx_size;
230 	uint32_t algo = TEE_ALG_AES_ECB_NOPAD;
231 
232 	res = crypto_cipher_get_ctx_size(algo, &ctx_size);
233 	if (res != TEE_SUCCESS)
234 		return res;
235 
236 	ctx = malloc(ctx_size);
237 	if (!ctx)
238 		return TEE_ERROR_OUT_OF_MEMORY;
239 
240 	res = crypto_cipher_init(ctx, algo, TEE_MODE_ENCRYPT, key,
241 				 key_size, NULL, 0, NULL, 0);
242 	if (res != TEE_SUCCESS)
243 		goto out;
244 
245 	res = crypto_cipher_update(ctx, algo, TEE_MODE_ENCRYPT, true, in,
246 				   TEE_AES_BLOCK_SIZE, out);
247 	if (res != TEE_SUCCESS)
248 		goto out;
249 
250 	crypto_cipher_final(ctx, algo);
251 	res = TEE_SUCCESS;
252 
253 out:
254 	free(ctx);
255 	return res;
256 }
257 
258 static TEE_Result essiv(uint8_t iv[TEE_AES_BLOCK_SIZE],
259 			const uint8_t fek[TEE_FS_KM_FEK_SIZE],
260 			uint16_t blk_idx)
261 {
262 	TEE_Result res;
263 	uint8_t sha[TEE_SHA256_HASH_SIZE];
264 	uint8_t pad_blkid[TEE_AES_BLOCK_SIZE] = { 0, };
265 
266 	res = sha256(sha, sizeof(sha), fek, TEE_FS_KM_FEK_SIZE);
267 	if (res != TEE_SUCCESS)
268 		return res;
269 
270 	pad_blkid[0] = (blk_idx & 0xFF);
271 	pad_blkid[1] = (blk_idx & 0xFF00) >> 8;
272 
273 	return aes_ecb(iv, pad_blkid, sha, 16);
274 }
275 
276 /*
277  * Encryption/decryption of RPMB FS file data. This is AES CBC with ESSIV.
278  */
279 TEE_Result tee_fs_crypt_block(const TEE_UUID *uuid, uint8_t *out,
280 			      const uint8_t *in, size_t size,
281 			      uint16_t blk_idx, const uint8_t *encrypted_fek,
282 			      TEE_OperationMode mode)
283 {
284 	TEE_Result res;
285 	uint8_t fek[TEE_FS_KM_FEK_SIZE];
286 	uint8_t iv[TEE_AES_BLOCK_SIZE];
287 	uint8_t *ctx;
288 	size_t ctx_size;
289 	uint32_t algo = TEE_ALG_AES_CBC_NOPAD;
290 
291 	DMSG("%scrypt block #%u", (mode == TEE_MODE_ENCRYPT) ? "En" : "De",
292 	     blk_idx);
293 
294 	/* Decrypt FEK */
295 	res = tee_fs_fek_crypt(uuid, TEE_MODE_DECRYPT, encrypted_fek,
296 			       TEE_FS_KM_FEK_SIZE, fek);
297 	if (res != TEE_SUCCESS)
298 		return res;
299 
300 	/* Compute initialization vector for this block */
301 	res = essiv(iv, fek, blk_idx);
302 
303 	/* Run AES CBC */
304 	res = crypto_cipher_get_ctx_size(algo, &ctx_size);
305 	if (res != TEE_SUCCESS)
306 		return res;
307 	ctx = malloc(ctx_size);
308 	if (!ctx)
309 		return TEE_ERROR_OUT_OF_MEMORY;
310 
311 	res = crypto_cipher_init(ctx, algo, mode, fek, sizeof(fek), NULL,
312 				 0, iv, TEE_AES_BLOCK_SIZE);
313 	if (res != TEE_SUCCESS)
314 		goto exit;
315 	res = crypto_cipher_update(ctx, algo, mode, true, in, size, out);
316 	if (res != TEE_SUCCESS)
317 		goto exit;
318 
319 	crypto_cipher_final(ctx, algo);
320 
321 exit:
322 	free(ctx);
323 	return res;
324 }
325 
326 service_init_late(tee_fs_init_key_manager);
327