xref: /optee_os/core/tee/tee_fs_key_manager.c (revision 5ca2c36555d169a2be60964e2cbe39340c5245a4)
11bb92983SJerome Forissier // SPDX-License-Identifier: BSD-2-Clause
2c7856574SJames Kung /*
3c7856574SJames Kung  * Copyright (c) 2015, Linaro Limited
4c7856574SJames Kung  */
5c7856574SJames Kung 
6c7856574SJames Kung 
7fde4a756SJerome Forissier /*
8fde4a756SJerome Forissier  * Acronyms:
9c7856574SJames Kung  *
10c7856574SJames Kung  * FEK - File Encryption Key
11c7856574SJames Kung  * SSK - Secure Storage Key
12fde4a756SJerome Forissier  * TSK - Trusted app Storage Key
13c7856574SJames Kung  * IV  - Initial vector
14c7856574SJames Kung  * HUK - Hardware Unique Key
15c7856574SJames Kung  * RNG - Random Number Generator
16fde4a756SJerome Forissier  */
17c7856574SJames Kung 
18df91a522SJens Wiklander #include <assert.h>
19e1770e71SJens Wiklander #include <compiler.h>
20e1770e71SJens Wiklander #include <crypto/crypto.h>
21c7856574SJames Kung #include <initcall.h>
22df91a522SJens Wiklander #include <kernel/huk_subkey.h>
23c7856574SJames Kung #include <kernel/tee_common_otp.h>
24fde4a756SJerome Forissier #include <kernel/tee_ta_manager.h>
25e1770e71SJens Wiklander #include <stdlib.h>
26e1770e71SJens Wiklander #include <string.h>
273ca4a1caSJerome Forissier #include <string_ext.h>
28c7856574SJames Kung #include <tee/tee_cryp_utl.h>
29c7856574SJames Kung #include <tee/tee_fs_key_manager.h>
30c7856574SJames Kung #include <trace.h>
319e84c17eSJerome Forissier #include <util.h>
32c7856574SJames Kung 
33c7856574SJames Kung struct tee_fs_ssk {
34c7856574SJames Kung 	bool is_init;
35c7856574SJames Kung 	uint8_t key[TEE_FS_KM_SSK_SIZE];
36c7856574SJames Kung };
37c7856574SJames Kung 
38c7856574SJames Kung static struct tee_fs_ssk tee_fs_ssk;
39c7856574SJames Kung 
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)400c4e1284SJens Wiklander static TEE_Result do_hmac(void *out_key, size_t out_key_size,
410c4e1284SJens Wiklander 			  const void *in_key, size_t in_key_size,
420c4e1284SJens Wiklander 			  const void *message, size_t message_size)
43fde4a756SJerome Forissier {
4482ef73bcSJens Wiklander 	TEE_Result res;
4582ef73bcSJens Wiklander 	void *ctx = NULL;
46fde4a756SJerome Forissier 
47fde4a756SJerome Forissier 	if (!out_key || !in_key || !message)
48fde4a756SJerome Forissier 		return TEE_ERROR_BAD_PARAMETERS;
49fde4a756SJerome Forissier 
5082ef73bcSJens Wiklander 	res = crypto_mac_alloc_ctx(&ctx, TEE_FS_KM_HMAC_ALG);
51fde4a756SJerome Forissier 	if (res != TEE_SUCCESS)
52fde4a756SJerome Forissier 		return res;
53fde4a756SJerome Forissier 
54*c69bc615SJens Wiklander 	res = crypto_mac_init(ctx, in_key, in_key_size);
55fde4a756SJerome Forissier 	if (res != TEE_SUCCESS)
56fde4a756SJerome Forissier 		goto exit;
57fde4a756SJerome Forissier 
58*c69bc615SJens Wiklander 	res = crypto_mac_update(ctx, message, message_size);
59fde4a756SJerome Forissier 	if (res != TEE_SUCCESS)
60fde4a756SJerome Forissier 		goto exit;
61fde4a756SJerome Forissier 
62*c69bc615SJens Wiklander 	res = crypto_mac_final(ctx, out_key, out_key_size);
63fde4a756SJerome Forissier 	if (res != TEE_SUCCESS)
64fde4a756SJerome Forissier 		goto exit;
65fde4a756SJerome Forissier 
66fde4a756SJerome Forissier 	res = TEE_SUCCESS;
67fde4a756SJerome Forissier 
68fde4a756SJerome Forissier exit:
69*c69bc615SJens Wiklander 	crypto_mac_free_ctx(ctx);
70fde4a756SJerome Forissier 	return res;
71fde4a756SJerome Forissier }
72fde4a756SJerome Forissier 
tee_fs_fek_crypt(const TEE_UUID * uuid,TEE_OperationMode mode,const uint8_t * in_key,size_t size,uint8_t * out_key)730c4e1284SJens Wiklander TEE_Result tee_fs_fek_crypt(const TEE_UUID *uuid, TEE_OperationMode mode,
740c4e1284SJens Wiklander 			    const uint8_t *in_key, size_t size,
750c4e1284SJens Wiklander 			    uint8_t *out_key)
76c7856574SJames Kung {
77c7856574SJames Kung 	TEE_Result res;
7872a9b1a0SJens Wiklander 	void *ctx = NULL;
79fde4a756SJerome Forissier 	uint8_t tsk[TEE_FS_KM_TSK_SIZE];
80366f8a64SJens Wiklander 	uint8_t dst_key[size];
81c7856574SJames Kung 
82366f8a64SJens Wiklander 	if (!in_key || !out_key)
83c7856574SJames Kung 		return TEE_ERROR_BAD_PARAMETERS;
84c7856574SJames Kung 
85c7856574SJames Kung 	if (size != TEE_FS_KM_FEK_SIZE)
86c7856574SJames Kung 		return TEE_ERROR_BAD_PARAMETERS;
87c7856574SJames Kung 
88c7856574SJames Kung 	if (tee_fs_ssk.is_init == 0)
89c7856574SJames Kung 		return TEE_ERROR_GENERIC;
90c7856574SJames Kung 
910c4e1284SJens Wiklander 	if (uuid) {
920c4e1284SJens Wiklander 		res = do_hmac(tsk, sizeof(tsk), tee_fs_ssk.key,
930c4e1284SJens Wiklander 			      TEE_FS_KM_SSK_SIZE, uuid, sizeof(*uuid));
94fde4a756SJerome Forissier 		if (res != TEE_SUCCESS)
95fde4a756SJerome Forissier 			return res;
960c4e1284SJens Wiklander 	} else {
970c4e1284SJens Wiklander 		/*
980c4e1284SJens Wiklander 		 * Pick something of a different size than TEE_UUID to
990c4e1284SJens Wiklander 		 * guarantee that there's never a conflict.
1000c4e1284SJens Wiklander 		 */
1010c4e1284SJens Wiklander 		uint8_t dummy[1] = { 0 };
102fde4a756SJerome Forissier 
1030c4e1284SJens Wiklander 		res = do_hmac(tsk, sizeof(tsk), tee_fs_ssk.key,
1040c4e1284SJens Wiklander 			      TEE_FS_KM_SSK_SIZE, dummy, sizeof(dummy));
105fde4a756SJerome Forissier 		if (res != TEE_SUCCESS)
106fde4a756SJerome Forissier 			return res;
1070c4e1284SJens Wiklander 	}
108fde4a756SJerome Forissier 
10972a9b1a0SJens Wiklander 	res = crypto_cipher_alloc_ctx(&ctx, TEE_FS_KM_ENC_FEK_ALG);
110c7856574SJames Kung 	if (res != TEE_SUCCESS)
111c7856574SJames Kung 		return res;
112c7856574SJames Kung 
113cbda7091SJens Wiklander 	res = crypto_cipher_init(ctx, mode, tsk, sizeof(tsk), NULL, 0, NULL, 0);
114c7856574SJames Kung 	if (res != TEE_SUCCESS)
115c7856574SJames Kung 		goto exit;
116c7856574SJames Kung 
117cbda7091SJens Wiklander 	res = crypto_cipher_update(ctx, mode, true, in_key, size, dst_key);
118c7856574SJames Kung 	if (res != TEE_SUCCESS)
119c7856574SJames Kung 		goto exit;
120c7856574SJames Kung 
121cbda7091SJens Wiklander 	crypto_cipher_final(ctx);
122c7856574SJames Kung 
123366f8a64SJens Wiklander 	memcpy(out_key, dst_key, sizeof(dst_key));
124c7856574SJames Kung 
125c7856574SJames Kung exit:
126cbda7091SJens Wiklander 	crypto_cipher_free_ctx(ctx);
1273ca4a1caSJerome Forissier 	memzero_explicit(tsk, sizeof(tsk));
1283ca4a1caSJerome Forissier 	memzero_explicit(dst_key, sizeof(dst_key));
129c7856574SJames Kung 
130c7856574SJames Kung 	return res;
131c7856574SJames Kung }
132c7856574SJames Kung 
generate_fek(uint8_t * key,uint8_t len)133c7856574SJames Kung static TEE_Result generate_fek(uint8_t *key, uint8_t len)
134c7856574SJames Kung {
13536a063efSJens Wiklander 	return crypto_rng_read(key, len);
136c7856574SJames Kung }
137c7856574SJames Kung 
tee_fs_init_key_manager(void)138c7856574SJames Kung static TEE_Result tee_fs_init_key_manager(void)
139c7856574SJames Kung {
140df91a522SJens Wiklander 	TEE_Result res = TEE_SUCCESS;
141c7856574SJames Kung 
142df91a522SJens Wiklander 	COMPILE_TIME_ASSERT(TEE_FS_KM_SSK_SIZE <= HUK_SUBKEY_MAX_LEN);
143c7856574SJames Kung 
144df91a522SJens Wiklander 	res = huk_subkey_derive(HUK_SUBKEY_SSK, NULL, 0,
145df91a522SJens Wiklander 				tee_fs_ssk.key, sizeof(tee_fs_ssk.key));
146c7856574SJames Kung 	if (res == TEE_SUCCESS)
147c7856574SJames Kung 		tee_fs_ssk.is_init = 1;
1483ca4a1caSJerome Forissier 	else
1493ca4a1caSJerome Forissier 		memzero_explicit(&tee_fs_ssk, sizeof(tee_fs_ssk));
150c7856574SJames Kung 
151c7856574SJames Kung 	return res;
152c7856574SJames Kung }
153c7856574SJames Kung 
tee_fs_generate_fek(const TEE_UUID * uuid,void * buf,size_t buf_size)1540c4e1284SJens Wiklander TEE_Result tee_fs_generate_fek(const TEE_UUID *uuid, void *buf, size_t buf_size)
155c7856574SJames Kung {
156c7856574SJames Kung 	TEE_Result res;
157c7856574SJames Kung 
158c7856574SJames Kung 	if (buf_size != TEE_FS_KM_FEK_SIZE)
159b8cceb55SJerome Forissier 		return TEE_ERROR_BAD_PARAMETERS;
160c7856574SJames Kung 
161c7856574SJames Kung 	res = generate_fek(buf, TEE_FS_KM_FEK_SIZE);
162c7856574SJames Kung 	if (res != TEE_SUCCESS)
163c7856574SJames Kung 		return res;
164c7856574SJames Kung 
1650c4e1284SJens Wiklander 	return tee_fs_fek_crypt(uuid, TEE_MODE_ENCRYPT, buf,
1660c4e1284SJens Wiklander 				TEE_FS_KM_FEK_SIZE, buf);
167c7856574SJames Kung }
168c7856574SJames Kung 
sha256(uint8_t * out,size_t out_size,const uint8_t * in,size_t in_size)1699e84c17eSJerome Forissier static TEE_Result sha256(uint8_t *out, size_t out_size, const uint8_t *in,
1709e84c17eSJerome Forissier 			 size_t in_size)
1719e84c17eSJerome Forissier {
172ecf2e014SJens Wiklander 	return tee_hash_createdigest(TEE_ALG_SHA256, in, in_size,
173ecf2e014SJens Wiklander 				     out, out_size);
1749e84c17eSJerome Forissier }
1759e84c17eSJerome Forissier 
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)1769e84c17eSJerome Forissier static TEE_Result aes_ecb(uint8_t out[TEE_AES_BLOCK_SIZE],
1779e84c17eSJerome Forissier 			  const uint8_t in[TEE_AES_BLOCK_SIZE],
1789e84c17eSJerome Forissier 			  const uint8_t *key, size_t key_size)
1799e84c17eSJerome Forissier {
1809e84c17eSJerome Forissier 	TEE_Result res;
18172a9b1a0SJens Wiklander 	void *ctx = NULL;
1829e84c17eSJerome Forissier 
183cbda7091SJens Wiklander 	res = crypto_cipher_alloc_ctx(&ctx, TEE_ALG_AES_ECB_NOPAD);
1849e84c17eSJerome Forissier 	if (res != TEE_SUCCESS)
1859e84c17eSJerome Forissier 		return res;
1869e84c17eSJerome Forissier 
187cbda7091SJens Wiklander 	res = crypto_cipher_init(ctx, TEE_MODE_ENCRYPT, key,
1889e84c17eSJerome Forissier 				 key_size, NULL, 0, NULL, 0);
1899e84c17eSJerome Forissier 	if (res != TEE_SUCCESS)
1909e84c17eSJerome Forissier 		goto out;
1919e84c17eSJerome Forissier 
192cbda7091SJens Wiklander 	res = crypto_cipher_update(ctx, TEE_MODE_ENCRYPT, true, in,
1939e84c17eSJerome Forissier 				   TEE_AES_BLOCK_SIZE, out);
1949e84c17eSJerome Forissier 	if (res != TEE_SUCCESS)
1959e84c17eSJerome Forissier 		goto out;
1969e84c17eSJerome Forissier 
197cbda7091SJens Wiklander 	crypto_cipher_final(ctx);
1989e84c17eSJerome Forissier 	res = TEE_SUCCESS;
1999e84c17eSJerome Forissier 
2009e84c17eSJerome Forissier out:
201cbda7091SJens Wiklander 	crypto_cipher_free_ctx(ctx);
2029e84c17eSJerome Forissier 	return res;
2039e84c17eSJerome Forissier }
2049e84c17eSJerome Forissier 
essiv(uint8_t iv[TEE_AES_BLOCK_SIZE],const uint8_t fek[TEE_FS_KM_FEK_SIZE],uint16_t blk_idx)2059e84c17eSJerome Forissier static TEE_Result essiv(uint8_t iv[TEE_AES_BLOCK_SIZE],
2069e84c17eSJerome Forissier 			const uint8_t fek[TEE_FS_KM_FEK_SIZE],
2079e84c17eSJerome Forissier 			uint16_t blk_idx)
2089e84c17eSJerome Forissier {
2099e84c17eSJerome Forissier 	TEE_Result res;
2109e84c17eSJerome Forissier 	uint8_t sha[TEE_SHA256_HASH_SIZE];
2119e84c17eSJerome Forissier 	uint8_t pad_blkid[TEE_AES_BLOCK_SIZE] = { 0, };
2129e84c17eSJerome Forissier 
2139e84c17eSJerome Forissier 	res = sha256(sha, sizeof(sha), fek, TEE_FS_KM_FEK_SIZE);
2149e84c17eSJerome Forissier 	if (res != TEE_SUCCESS)
2159e84c17eSJerome Forissier 		return res;
2169e84c17eSJerome Forissier 
2179e84c17eSJerome Forissier 	pad_blkid[0] = (blk_idx & 0xFF);
2189e84c17eSJerome Forissier 	pad_blkid[1] = (blk_idx & 0xFF00) >> 8;
2199e84c17eSJerome Forissier 
2203ca4a1caSJerome Forissier 	res = aes_ecb(iv, pad_blkid, sha, 16);
2213ca4a1caSJerome Forissier 
2223ca4a1caSJerome Forissier 	memzero_explicit(sha, sizeof(sha));
2233ca4a1caSJerome Forissier 	return res;
2249e84c17eSJerome Forissier }
2259e84c17eSJerome Forissier 
2269e84c17eSJerome Forissier /*
2279e84c17eSJerome Forissier  * Encryption/decryption of RPMB FS file data. This is AES CBC with ESSIV.
2289e84c17eSJerome Forissier  */
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)2290c4e1284SJens Wiklander TEE_Result tee_fs_crypt_block(const TEE_UUID *uuid, uint8_t *out,
2300c4e1284SJens Wiklander 			      const uint8_t *in, size_t size,
2319e84c17eSJerome Forissier 			      uint16_t blk_idx, const uint8_t *encrypted_fek,
2329e84c17eSJerome Forissier 			      TEE_OperationMode mode)
2339e84c17eSJerome Forissier {
2349e84c17eSJerome Forissier 	TEE_Result res;
2359e84c17eSJerome Forissier 	uint8_t fek[TEE_FS_KM_FEK_SIZE];
2369e84c17eSJerome Forissier 	uint8_t iv[TEE_AES_BLOCK_SIZE];
23772a9b1a0SJens Wiklander 	void *ctx;
2389e84c17eSJerome Forissier 
2399e84c17eSJerome Forissier 	DMSG("%scrypt block #%u", (mode == TEE_MODE_ENCRYPT) ? "En" : "De",
2409e84c17eSJerome Forissier 	     blk_idx);
2419e84c17eSJerome Forissier 
2429e84c17eSJerome Forissier 	/* Decrypt FEK */
2430c4e1284SJens Wiklander 	res = tee_fs_fek_crypt(uuid, TEE_MODE_DECRYPT, encrypted_fek,
244366f8a64SJens Wiklander 			       TEE_FS_KM_FEK_SIZE, fek);
2459e84c17eSJerome Forissier 	if (res != TEE_SUCCESS)
2463ca4a1caSJerome Forissier 		goto wipe;
2479e84c17eSJerome Forissier 
2489e84c17eSJerome Forissier 	/* Compute initialization vector for this block */
2499e84c17eSJerome Forissier 	res = essiv(iv, fek, blk_idx);
2509607c419SJoakim Bech 	if (res != TEE_SUCCESS)
2513ca4a1caSJerome Forissier 		goto wipe;
2529e84c17eSJerome Forissier 
2539e84c17eSJerome Forissier 	/* Run AES CBC */
254cbda7091SJens Wiklander 	res = crypto_cipher_alloc_ctx(&ctx, TEE_ALG_AES_CBC_NOPAD);
2559e84c17eSJerome Forissier 	if (res != TEE_SUCCESS)
2563ca4a1caSJerome Forissier 		goto wipe;
2579e84c17eSJerome Forissier 
258cbda7091SJens Wiklander 	res = crypto_cipher_init(ctx, mode, fek, sizeof(fek), NULL,
2599e84c17eSJerome Forissier 				 0, iv, TEE_AES_BLOCK_SIZE);
2609e84c17eSJerome Forissier 	if (res != TEE_SUCCESS)
2619e84c17eSJerome Forissier 		goto exit;
262cbda7091SJens Wiklander 	res = crypto_cipher_update(ctx, mode, true, in, size, out);
2639e84c17eSJerome Forissier 	if (res != TEE_SUCCESS)
2649e84c17eSJerome Forissier 		goto exit;
2659e84c17eSJerome Forissier 
266cbda7091SJens Wiklander 	crypto_cipher_final(ctx);
2679e84c17eSJerome Forissier 
2689e84c17eSJerome Forissier exit:
269cbda7091SJens Wiklander 	crypto_cipher_free_ctx(ctx);
2703ca4a1caSJerome Forissier wipe:
2713ca4a1caSJerome Forissier 	memzero_explicit(fek, sizeof(fek));
2723ca4a1caSJerome Forissier 	memzero_explicit(iv, sizeof(iv));
2739e84c17eSJerome Forissier 	return res;
2749e84c17eSJerome Forissier }
2759e84c17eSJerome Forissier 
276dbb790c6SJens Wiklander service_init_late(tee_fs_init_key_manager);
277