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