xref: /optee_os/core/tee/tee_fs_key_manager.c (revision 5ca2c36555d169a2be60964e2cbe39340c5245a4)
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 <assert.h>
19 #include <compiler.h>
20 #include <crypto/crypto.h>
21 #include <initcall.h>
22 #include <kernel/huk_subkey.h>
23 #include <kernel/tee_common_otp.h>
24 #include <kernel/tee_ta_manager.h>
25 #include <stdlib.h>
26 #include <string.h>
27 #include <string_ext.h>
28 #include <tee/tee_cryp_utl.h>
29 #include <tee/tee_fs_key_manager.h>
30 #include <trace.h>
31 #include <util.h>
32 
33 struct tee_fs_ssk {
34 	bool is_init;
35 	uint8_t key[TEE_FS_KM_SSK_SIZE];
36 };
37 
38 static struct tee_fs_ssk tee_fs_ssk;
39 
do_hmac(void * out_key,size_t out_key_size,const void * in_key,size_t in_key_size,const void * message,size_t message_size)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;
45 	void *ctx = NULL;
46 
47 	if (!out_key || !in_key || !message)
48 		return TEE_ERROR_BAD_PARAMETERS;
49 
50 	res = crypto_mac_alloc_ctx(&ctx, TEE_FS_KM_HMAC_ALG);
51 	if (res != TEE_SUCCESS)
52 		return res;
53 
54 	res = crypto_mac_init(ctx, in_key, in_key_size);
55 	if (res != TEE_SUCCESS)
56 		goto exit;
57 
58 	res = crypto_mac_update(ctx, message, message_size);
59 	if (res != TEE_SUCCESS)
60 		goto exit;
61 
62 	res = crypto_mac_final(ctx, out_key, out_key_size);
63 	if (res != TEE_SUCCESS)
64 		goto exit;
65 
66 	res = TEE_SUCCESS;
67 
68 exit:
69 	crypto_mac_free_ctx(ctx);
70 	return res;
71 }
72 
tee_fs_fek_crypt(const TEE_UUID * uuid,TEE_OperationMode mode,const uint8_t * in_key,size_t size,uint8_t * out_key)73 TEE_Result tee_fs_fek_crypt(const TEE_UUID *uuid, TEE_OperationMode mode,
74 			    const uint8_t *in_key, size_t size,
75 			    uint8_t *out_key)
76 {
77 	TEE_Result res;
78 	void *ctx = NULL;
79 	uint8_t tsk[TEE_FS_KM_TSK_SIZE];
80 	uint8_t dst_key[size];
81 
82 	if (!in_key || !out_key)
83 		return TEE_ERROR_BAD_PARAMETERS;
84 
85 	if (size != TEE_FS_KM_FEK_SIZE)
86 		return TEE_ERROR_BAD_PARAMETERS;
87 
88 	if (tee_fs_ssk.is_init == 0)
89 		return TEE_ERROR_GENERIC;
90 
91 	if (uuid) {
92 		res = do_hmac(tsk, sizeof(tsk), tee_fs_ssk.key,
93 			      TEE_FS_KM_SSK_SIZE, uuid, sizeof(*uuid));
94 		if (res != TEE_SUCCESS)
95 			return res;
96 	} else {
97 		/*
98 		 * Pick something of a different size than TEE_UUID to
99 		 * guarantee that there's never a conflict.
100 		 */
101 		uint8_t dummy[1] = { 0 };
102 
103 		res = do_hmac(tsk, sizeof(tsk), tee_fs_ssk.key,
104 			      TEE_FS_KM_SSK_SIZE, dummy, sizeof(dummy));
105 		if (res != TEE_SUCCESS)
106 			return res;
107 	}
108 
109 	res = crypto_cipher_alloc_ctx(&ctx, TEE_FS_KM_ENC_FEK_ALG);
110 	if (res != TEE_SUCCESS)
111 		return res;
112 
113 	res = crypto_cipher_init(ctx, mode, tsk, sizeof(tsk), NULL, 0, NULL, 0);
114 	if (res != TEE_SUCCESS)
115 		goto exit;
116 
117 	res = crypto_cipher_update(ctx, mode, true, in_key, size, dst_key);
118 	if (res != TEE_SUCCESS)
119 		goto exit;
120 
121 	crypto_cipher_final(ctx);
122 
123 	memcpy(out_key, dst_key, sizeof(dst_key));
124 
125 exit:
126 	crypto_cipher_free_ctx(ctx);
127 	memzero_explicit(tsk, sizeof(tsk));
128 	memzero_explicit(dst_key, sizeof(dst_key));
129 
130 	return res;
131 }
132 
generate_fek(uint8_t * key,uint8_t len)133 static TEE_Result generate_fek(uint8_t *key, uint8_t len)
134 {
135 	return crypto_rng_read(key, len);
136 }
137 
tee_fs_init_key_manager(void)138 static TEE_Result tee_fs_init_key_manager(void)
139 {
140 	TEE_Result res = TEE_SUCCESS;
141 
142 	COMPILE_TIME_ASSERT(TEE_FS_KM_SSK_SIZE <= HUK_SUBKEY_MAX_LEN);
143 
144 	res = huk_subkey_derive(HUK_SUBKEY_SSK, NULL, 0,
145 				tee_fs_ssk.key, sizeof(tee_fs_ssk.key));
146 	if (res == TEE_SUCCESS)
147 		tee_fs_ssk.is_init = 1;
148 	else
149 		memzero_explicit(&tee_fs_ssk, sizeof(tee_fs_ssk));
150 
151 	return res;
152 }
153 
tee_fs_generate_fek(const TEE_UUID * uuid,void * buf,size_t buf_size)154 TEE_Result tee_fs_generate_fek(const TEE_UUID *uuid, void *buf, size_t buf_size)
155 {
156 	TEE_Result res;
157 
158 	if (buf_size != TEE_FS_KM_FEK_SIZE)
159 		return TEE_ERROR_BAD_PARAMETERS;
160 
161 	res = generate_fek(buf, TEE_FS_KM_FEK_SIZE);
162 	if (res != TEE_SUCCESS)
163 		return res;
164 
165 	return tee_fs_fek_crypt(uuid, TEE_MODE_ENCRYPT, buf,
166 				TEE_FS_KM_FEK_SIZE, buf);
167 }
168 
sha256(uint8_t * out,size_t out_size,const uint8_t * in,size_t in_size)169 static TEE_Result sha256(uint8_t *out, size_t out_size, const uint8_t *in,
170 			 size_t in_size)
171 {
172 	return tee_hash_createdigest(TEE_ALG_SHA256, in, in_size,
173 				     out, out_size);
174 }
175 
aes_ecb(uint8_t out[TEE_AES_BLOCK_SIZE],const uint8_t in[TEE_AES_BLOCK_SIZE],const uint8_t * key,size_t key_size)176 static TEE_Result aes_ecb(uint8_t out[TEE_AES_BLOCK_SIZE],
177 			  const uint8_t in[TEE_AES_BLOCK_SIZE],
178 			  const uint8_t *key, size_t key_size)
179 {
180 	TEE_Result res;
181 	void *ctx = NULL;
182 
183 	res = crypto_cipher_alloc_ctx(&ctx, TEE_ALG_AES_ECB_NOPAD);
184 	if (res != TEE_SUCCESS)
185 		return res;
186 
187 	res = crypto_cipher_init(ctx, TEE_MODE_ENCRYPT, key,
188 				 key_size, NULL, 0, NULL, 0);
189 	if (res != TEE_SUCCESS)
190 		goto out;
191 
192 	res = crypto_cipher_update(ctx, TEE_MODE_ENCRYPT, true, in,
193 				   TEE_AES_BLOCK_SIZE, out);
194 	if (res != TEE_SUCCESS)
195 		goto out;
196 
197 	crypto_cipher_final(ctx);
198 	res = TEE_SUCCESS;
199 
200 out:
201 	crypto_cipher_free_ctx(ctx);
202 	return res;
203 }
204 
essiv(uint8_t iv[TEE_AES_BLOCK_SIZE],const uint8_t fek[TEE_FS_KM_FEK_SIZE],uint16_t blk_idx)205 static TEE_Result essiv(uint8_t iv[TEE_AES_BLOCK_SIZE],
206 			const uint8_t fek[TEE_FS_KM_FEK_SIZE],
207 			uint16_t blk_idx)
208 {
209 	TEE_Result res;
210 	uint8_t sha[TEE_SHA256_HASH_SIZE];
211 	uint8_t pad_blkid[TEE_AES_BLOCK_SIZE] = { 0, };
212 
213 	res = sha256(sha, sizeof(sha), fek, TEE_FS_KM_FEK_SIZE);
214 	if (res != TEE_SUCCESS)
215 		return res;
216 
217 	pad_blkid[0] = (blk_idx & 0xFF);
218 	pad_blkid[1] = (blk_idx & 0xFF00) >> 8;
219 
220 	res = aes_ecb(iv, pad_blkid, sha, 16);
221 
222 	memzero_explicit(sha, sizeof(sha));
223 	return res;
224 }
225 
226 /*
227  * Encryption/decryption of RPMB FS file data. This is AES CBC with ESSIV.
228  */
tee_fs_crypt_block(const TEE_UUID * uuid,uint8_t * out,const uint8_t * in,size_t size,uint16_t blk_idx,const uint8_t * encrypted_fek,TEE_OperationMode mode)229 TEE_Result tee_fs_crypt_block(const TEE_UUID *uuid, uint8_t *out,
230 			      const uint8_t *in, size_t size,
231 			      uint16_t blk_idx, const uint8_t *encrypted_fek,
232 			      TEE_OperationMode mode)
233 {
234 	TEE_Result res;
235 	uint8_t fek[TEE_FS_KM_FEK_SIZE];
236 	uint8_t iv[TEE_AES_BLOCK_SIZE];
237 	void *ctx;
238 
239 	DMSG("%scrypt block #%u", (mode == TEE_MODE_ENCRYPT) ? "En" : "De",
240 	     blk_idx);
241 
242 	/* Decrypt FEK */
243 	res = tee_fs_fek_crypt(uuid, TEE_MODE_DECRYPT, encrypted_fek,
244 			       TEE_FS_KM_FEK_SIZE, fek);
245 	if (res != TEE_SUCCESS)
246 		goto wipe;
247 
248 	/* Compute initialization vector for this block */
249 	res = essiv(iv, fek, blk_idx);
250 	if (res != TEE_SUCCESS)
251 		goto wipe;
252 
253 	/* Run AES CBC */
254 	res = crypto_cipher_alloc_ctx(&ctx, TEE_ALG_AES_CBC_NOPAD);
255 	if (res != TEE_SUCCESS)
256 		goto wipe;
257 
258 	res = crypto_cipher_init(ctx, mode, fek, sizeof(fek), NULL,
259 				 0, iv, TEE_AES_BLOCK_SIZE);
260 	if (res != TEE_SUCCESS)
261 		goto exit;
262 	res = crypto_cipher_update(ctx, mode, true, in, size, out);
263 	if (res != TEE_SUCCESS)
264 		goto exit;
265 
266 	crypto_cipher_final(ctx);
267 
268 exit:
269 	crypto_cipher_free_ctx(ctx);
270 wipe:
271 	memzero_explicit(fek, sizeof(fek));
272 	memzero_explicit(iv, sizeof(iv));
273 	return res;
274 }
275 
276 service_init_late(tee_fs_init_key_manager);
277