xref: /optee_os/core/tee/tee_fs_key_manager.c (revision b72716ce78a1d1e9054683e2bec1377c1c1ae344)
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 <initcall.h>
41 #include <stdlib.h>
42 #include <string.h>
43 #include <kernel/panic.h>
44 #include <kernel/tee_common_otp.h>
45 #include <kernel/tee_ta_manager.h>
46 #include <tee/tee_cryp_utl.h>
47 #include <tee/tee_cryp_provider.h>
48 #include <tee/tee_fs_key_manager.h>
49 #include <compiler.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(uint8_t *out_key, uint32_t out_key_size,
63 			  const uint8_t *in_key, uint32_t in_key_size,
64 			  const uint8_t *message, uint32_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_ops.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_ops.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_ops.mac.update(ctx, TEE_FS_KM_HMAC_ALG,
86 			message, message_size);
87 	if (res != TEE_SUCCESS)
88 		goto exit;
89 
90 	res = crypto_ops.mac.final(ctx, TEE_FS_KM_HMAC_ALG, out_key,
91 				   out_key_size);
92 	if (res != TEE_SUCCESS)
93 		goto exit;
94 
95 	res = TEE_SUCCESS;
96 
97 exit:
98 	free(ctx);
99 	return res;
100 }
101 
102 TEE_Result tee_fs_fek_crypt(TEE_OperationMode mode, const uint8_t *in_key,
103 			    size_t size, 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 	struct tee_ta_session *sess;
111 
112 	if (!in_key || !out_key)
113 		return TEE_ERROR_BAD_PARAMETERS;
114 
115 	if (size != TEE_FS_KM_FEK_SIZE)
116 		return TEE_ERROR_BAD_PARAMETERS;
117 
118 	if (tee_fs_ssk.is_init == 0)
119 		return TEE_ERROR_GENERIC;
120 
121 	res = tee_ta_get_current_session(&sess);
122 	if (res != TEE_SUCCESS)
123 		return res;
124 
125 	res = do_hmac(tsk, sizeof(tsk), tee_fs_ssk.key, TEE_FS_KM_SSK_SIZE,
126 		      (uint8_t *)&sess->ctx->uuid, sizeof(TEE_UUID));
127 	if (res != TEE_SUCCESS)
128 		return res;
129 
130 	res = crypto_ops.cipher.get_ctx_size(TEE_FS_KM_ENC_FEK_ALG, &ctx_size);
131 	if (res != TEE_SUCCESS)
132 		return res;
133 
134 	ctx = malloc(ctx_size);
135 	if (!ctx)
136 		return TEE_ERROR_OUT_OF_MEMORY;
137 
138 	res = crypto_ops.cipher.init(ctx, TEE_FS_KM_ENC_FEK_ALG, mode, tsk,
139 				     sizeof(tsk), NULL, 0, NULL, 0);
140 	if (res != TEE_SUCCESS)
141 		goto exit;
142 
143 	res = crypto_ops.cipher.update(ctx, TEE_FS_KM_ENC_FEK_ALG,
144 			mode, true, in_key, size, dst_key);
145 	if (res != TEE_SUCCESS)
146 		goto exit;
147 
148 	crypto_ops.cipher.final(ctx, TEE_FS_KM_ENC_FEK_ALG);
149 
150 	memcpy(out_key, dst_key, sizeof(dst_key));
151 
152 exit:
153 	free(ctx);
154 
155 	return res;
156 }
157 
158 static TEE_Result generate_fek(uint8_t *key, uint8_t len)
159 {
160 	return crypto_ops.prng.read(key, len);
161 }
162 
163 static TEE_Result tee_fs_init_key_manager(void)
164 {
165 	int res = TEE_SUCCESS;
166 	struct tee_hw_unique_key huk;
167 	uint8_t chip_id[TEE_FS_KM_CHIP_ID_LENGTH];
168 	uint8_t message[sizeof(chip_id) + sizeof(string_for_ssk_gen)];
169 
170 	/* Secure Storage Key Generation:
171 	 *
172 	 *     SSK = HMAC(HUK, message)
173 	 *     message := concatenate(chip_id, static string)
174 	 * */
175 	tee_otp_get_hw_unique_key(&huk);
176 	tee_otp_get_die_id(chip_id, sizeof(chip_id));
177 
178 	memcpy(message, chip_id, sizeof(chip_id));
179 	memcpy(message + sizeof(chip_id), string_for_ssk_gen,
180 			sizeof(string_for_ssk_gen));
181 
182 	res = do_hmac(tee_fs_ssk.key, sizeof(tee_fs_ssk.key),
183 			huk.data, sizeof(huk.data),
184 			message, sizeof(message));
185 
186 	if (res == TEE_SUCCESS)
187 		tee_fs_ssk.is_init = 1;
188 
189 	return res;
190 }
191 
192 TEE_Result tee_fs_generate_fek(uint8_t *buf, int buf_size)
193 {
194 	TEE_Result res;
195 
196 	if (buf_size != TEE_FS_KM_FEK_SIZE)
197 		return TEE_ERROR_BAD_PARAMETERS;
198 
199 	res = generate_fek(buf, TEE_FS_KM_FEK_SIZE);
200 	if (res != TEE_SUCCESS)
201 		return res;
202 
203 	return tee_fs_fek_crypt(TEE_MODE_ENCRYPT, buf, TEE_FS_KM_FEK_SIZE, buf);
204 }
205 
206 static TEE_Result sha256(uint8_t *out, size_t out_size, const uint8_t *in,
207 			 size_t in_size)
208 {
209 	TEE_Result res;
210 	uint8_t *ctx = NULL;
211 	size_t ctx_size;
212 	uint32_t algo = TEE_ALG_SHA256;
213 
214 	res = crypto_ops.hash.get_ctx_size(algo, &ctx_size);
215 	if (res != TEE_SUCCESS)
216 		return res;
217 
218 	ctx = malloc(ctx_size);
219 	if (!ctx)
220 		return TEE_ERROR_OUT_OF_MEMORY;
221 
222 	res = crypto_ops.hash.init(ctx, algo);
223 	if (res != TEE_SUCCESS)
224 		goto out;
225 
226 	res = crypto_ops.hash.update(ctx, algo, in, in_size);
227 	if (res != TEE_SUCCESS)
228 		goto out;
229 
230 	res = crypto_ops.hash.final(ctx, algo, out, out_size);
231 
232 out:
233 	free(ctx);
234 	return res;
235 }
236 
237 static TEE_Result aes_ecb(uint8_t out[TEE_AES_BLOCK_SIZE],
238 			  const uint8_t in[TEE_AES_BLOCK_SIZE],
239 			  const uint8_t *key, size_t key_size)
240 {
241 	TEE_Result res;
242 	uint8_t *ctx = NULL;
243 	size_t ctx_size;
244 	uint32_t algo = TEE_ALG_AES_ECB_NOPAD;
245 
246 	res = crypto_ops.cipher.get_ctx_size(algo, &ctx_size);
247 	if (res != TEE_SUCCESS)
248 		return res;
249 
250 	ctx = malloc(ctx_size);
251 	if (!ctx)
252 		return TEE_ERROR_OUT_OF_MEMORY;
253 
254 	res = crypto_ops.cipher.init(ctx, algo, TEE_MODE_ENCRYPT, key,
255 				     key_size, NULL, 0, NULL, 0);
256 	if (res != TEE_SUCCESS)
257 		goto out;
258 
259 	res = crypto_ops.cipher.update(ctx, algo, TEE_MODE_ENCRYPT, true, in,
260 				       TEE_AES_BLOCK_SIZE, out);
261 	if (res != TEE_SUCCESS)
262 		goto out;
263 
264 	crypto_ops.cipher.final(ctx, algo);
265 	res = TEE_SUCCESS;
266 
267 out:
268 	free(ctx);
269 	return res;
270 }
271 
272 static TEE_Result essiv(uint8_t iv[TEE_AES_BLOCK_SIZE],
273 			const uint8_t fek[TEE_FS_KM_FEK_SIZE],
274 			uint16_t blk_idx)
275 {
276 	TEE_Result res;
277 	uint8_t sha[TEE_SHA256_HASH_SIZE];
278 	uint8_t pad_blkid[TEE_AES_BLOCK_SIZE] = { 0, };
279 
280 	res = sha256(sha, sizeof(sha), fek, TEE_FS_KM_FEK_SIZE);
281 	if (res != TEE_SUCCESS)
282 		return res;
283 
284 	pad_blkid[0] = (blk_idx & 0xFF);
285 	pad_blkid[1] = (blk_idx & 0xFF00) >> 8;
286 
287 	return aes_ecb(iv, pad_blkid, sha, 16);
288 }
289 
290 /*
291  * Encryption/decryption of RPMB FS file data. This is AES CBC with ESSIV.
292  */
293 TEE_Result tee_fs_crypt_block(uint8_t *out, const uint8_t *in, size_t size,
294 			      uint16_t blk_idx, const uint8_t *encrypted_fek,
295 			      TEE_OperationMode mode)
296 {
297 	TEE_Result res;
298 	uint8_t fek[TEE_FS_KM_FEK_SIZE];
299 	uint8_t iv[TEE_AES_BLOCK_SIZE];
300 	uint8_t *ctx;
301 	size_t ctx_size;
302 	uint32_t algo = TEE_ALG_AES_CBC_NOPAD;
303 
304 	DMSG("%scrypt block #%u", (mode == TEE_MODE_ENCRYPT) ? "En" : "De",
305 	     blk_idx);
306 
307 	/* Decrypt FEK */
308 	res = tee_fs_fek_crypt(TEE_MODE_DECRYPT, encrypted_fek,
309 			       TEE_FS_KM_FEK_SIZE, fek);
310 	if (res != TEE_SUCCESS)
311 		return res;
312 
313 	/* Compute initialization vector for this block */
314 	res = essiv(iv, fek, blk_idx);
315 
316 	/* Run AES CBC */
317 	res = crypto_ops.cipher.get_ctx_size(algo, &ctx_size);
318 	if (res != TEE_SUCCESS)
319 		return res;
320 	ctx = malloc(ctx_size);
321 	if (!ctx)
322 		return TEE_ERROR_OUT_OF_MEMORY;
323 
324 	res = crypto_ops.cipher.init(ctx, algo, mode, fek, sizeof(fek), NULL,
325 				     0, iv, TEE_AES_BLOCK_SIZE);
326 	if (res != TEE_SUCCESS)
327 		goto exit;
328 	res = crypto_ops.cipher.update(ctx, algo, mode, true, in, size, out);
329 	if (res != TEE_SUCCESS)
330 		goto exit;
331 
332 	crypto_ops.cipher.final(ctx, algo);
333 
334 exit:
335 	free(ctx);
336 	return res;
337 }
338 
339 service_init_late(tee_fs_init_key_manager);
340