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