xref: /optee_os/core/tee/fs_htree.c (revision 50a814981d8b4bfe9d035bb16eeba6ac759e572f)
1*50a81498SJens Wiklander /*
2*50a81498SJens Wiklander  * Copyright (c) 2017, Linaro Limited
3*50a81498SJens Wiklander  * All rights reserved.
4*50a81498SJens Wiklander  *
5*50a81498SJens Wiklander  * Redistribution and use in source and binary forms, with or without
6*50a81498SJens Wiklander  * modification, are permitted provided that the following conditions are met:
7*50a81498SJens Wiklander  *
8*50a81498SJens Wiklander  * 1. Redistributions of source code must retain the above copyright notice,
9*50a81498SJens Wiklander  * this list of conditions and the following disclaimer.
10*50a81498SJens Wiklander  *
11*50a81498SJens Wiklander  * 2. Redistributions in binary form must reproduce the above copyright notice,
12*50a81498SJens Wiklander  * this list of conditions and the following disclaimer in the documentation
13*50a81498SJens Wiklander  * and/or other materials provided with the distribution.
14*50a81498SJens Wiklander  *
15*50a81498SJens Wiklander  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
16*50a81498SJens Wiklander  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17*50a81498SJens Wiklander  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18*50a81498SJens Wiklander  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
19*50a81498SJens Wiklander  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
20*50a81498SJens Wiklander  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
21*50a81498SJens Wiklander  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
22*50a81498SJens Wiklander  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
23*50a81498SJens Wiklander  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
24*50a81498SJens Wiklander  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
25*50a81498SJens Wiklander  * POSSIBILITY OF SUCH DAMAGE.
26*50a81498SJens Wiklander  */
27*50a81498SJens Wiklander 
28*50a81498SJens Wiklander #include <assert.h>
29*50a81498SJens Wiklander #include <initcall.h>
30*50a81498SJens Wiklander #include <kernel/tee_common_otp.h>
31*50a81498SJens Wiklander #include <optee_msg_supplicant.h>
32*50a81498SJens Wiklander #include <stdlib.h>
33*50a81498SJens Wiklander #include <string_ext.h>
34*50a81498SJens Wiklander #include <string.h>
35*50a81498SJens Wiklander #include <tee/fs_htree.h>
36*50a81498SJens Wiklander #include <tee/tee_cryp_provider.h>
37*50a81498SJens Wiklander #include <tee/tee_fs_key_manager.h>
38*50a81498SJens Wiklander #include <tee/tee_fs_rpc.h>
39*50a81498SJens Wiklander #include <utee_defines.h>
40*50a81498SJens Wiklander #include <util.h>
41*50a81498SJens Wiklander 
42*50a81498SJens Wiklander #define TEE_FS_HTREE_CHIP_ID_SIZE	32
43*50a81498SJens Wiklander #define TEE_FS_HTREE_HASH_ALG		TEE_ALG_SHA256
44*50a81498SJens Wiklander #define TEE_FS_HTREE_TSK_SIZE		TEE_FS_HTREE_HASH_SIZE
45*50a81498SJens Wiklander #define TEE_FS_HTREE_ENC_ALG		TEE_ALG_AES_ECB_NOPAD
46*50a81498SJens Wiklander #define TEE_FS_HTREE_ENC_SIZE		TEE_AES_BLOCK_SIZE
47*50a81498SJens Wiklander #define TEE_FS_HTREE_SSK_SIZE		TEE_FS_HTREE_HASH_SIZE
48*50a81498SJens Wiklander 
49*50a81498SJens Wiklander #define TEE_FS_HTREE_AUTH_ENC_ALG	TEE_ALG_AES_GCM
50*50a81498SJens Wiklander #define TEE_FS_HTREE_HMAC_ALG		TEE_ALG_HMAC_SHA256
51*50a81498SJens Wiklander 
52*50a81498SJens Wiklander #define BLOCK_NUM_TO_NODE_ID(num)	((num) + 1)
53*50a81498SJens Wiklander 
54*50a81498SJens Wiklander #define NODE_ID_TO_BLOCK_NUM(id)	((id) - 1)
55*50a81498SJens Wiklander 
56*50a81498SJens Wiklander /*
57*50a81498SJens Wiklander  * The hash tree is implemented as a binary tree with the purpose to ensure
58*50a81498SJens Wiklander  * integrity of the data in the nodes. The data in the nodes their turn
59*50a81498SJens Wiklander  * provides both integrity and confidentiality of the data blocks.
60*50a81498SJens Wiklander  *
61*50a81498SJens Wiklander  * The hash tree is saved in a file as:
62*50a81498SJens Wiklander  * +----------------------------+
63*50a81498SJens Wiklander  * | htree_image.0		|
64*50a81498SJens Wiklander  * | htree_image.1		|
65*50a81498SJens Wiklander  * +----------------------------+
66*50a81498SJens Wiklander  * | htree_node_image.1.0	|
67*50a81498SJens Wiklander  * | htree_node_image.1.1	|
68*50a81498SJens Wiklander  * +----------------------------+
69*50a81498SJens Wiklander  * | htree_node_image.2.0	|
70*50a81498SJens Wiklander  * | htree_node_image.2.1	|
71*50a81498SJens Wiklander  * +----------------------------+
72*50a81498SJens Wiklander  * | htree_node_image.3.0	|
73*50a81498SJens Wiklander  * | htree_node_image.3.1	|
74*50a81498SJens Wiklander  * +----------------------------+
75*50a81498SJens Wiklander  * | htree_node_image.4.0	|
76*50a81498SJens Wiklander  * | htree_node_image.4.1	|
77*50a81498SJens Wiklander  * +----------------------------+
78*50a81498SJens Wiklander  * ...
79*50a81498SJens Wiklander  *
80*50a81498SJens Wiklander  * htree_image is the header of the file, there's two instances of it. One
81*50a81498SJens Wiklander  * which is committed and the other is used when updating the file. Which
82*50a81498SJens Wiklander  * is committed is indicated by the "counter" field, the one with the
83*50a81498SJens Wiklander  * largest value is selected.
84*50a81498SJens Wiklander  *
85*50a81498SJens Wiklander  * htree_node_image is a node in the hash tree, each node has two instances
86*50a81498SJens Wiklander  * which is committed is decided by the parent node .flag bit
87*50a81498SJens Wiklander  * HTREE_NODE_CHILD_COMMITTED. Which version is the committed version of
88*50a81498SJens Wiklander  * node 1 is determined by the by the lowest bit of the counter field in
89*50a81498SJens Wiklander  * the header.
90*50a81498SJens Wiklander  *
91*50a81498SJens Wiklander  * Note that nodes start counting at 1 while blocks at 0, this means that
92*50a81498SJens Wiklander  * block 0 is represented by node 1.
93*50a81498SJens Wiklander  *
94*50a81498SJens Wiklander  * Where different elements are stored in the file is managed by the file
95*50a81498SJens Wiklander  * system. In the case of SQL FS the version of the node/block is ignored
96*50a81498SJens Wiklander  * as the atomic update is finalized with a call to
97*50a81498SJens Wiklander  * tee_fs_rpc_end_transaction().
98*50a81498SJens Wiklander  */
99*50a81498SJens Wiklander 
100*50a81498SJens Wiklander #define HTREE_NODE_COMMITTED_BLOCK	BIT32(0)
101*50a81498SJens Wiklander /* n is 0 or 1 */
102*50a81498SJens Wiklander #define HTREE_NODE_COMMITTED_CHILD(n)	BIT32(1 + (n))
103*50a81498SJens Wiklander 
104*50a81498SJens Wiklander struct htree_node {
105*50a81498SJens Wiklander 	size_t id;
106*50a81498SJens Wiklander 	bool dirty;
107*50a81498SJens Wiklander 	uint8_t committed_block;
108*50a81498SJens Wiklander 	struct tee_fs_htree_node_image node;
109*50a81498SJens Wiklander 	struct htree_node *parent;
110*50a81498SJens Wiklander 	struct htree_node *child[2];
111*50a81498SJens Wiklander };
112*50a81498SJens Wiklander 
113*50a81498SJens Wiklander struct tee_fs_htree {
114*50a81498SJens Wiklander 	struct htree_node root;
115*50a81498SJens Wiklander 	struct tee_fs_htree_image head;
116*50a81498SJens Wiklander 	uint8_t fek[TEE_FS_HTREE_FEK_SIZE];
117*50a81498SJens Wiklander 	struct tee_fs_htree_imeta imeta;
118*50a81498SJens Wiklander 	bool dirty;
119*50a81498SJens Wiklander 	const struct tee_fs_htree_storage *stor;
120*50a81498SJens Wiklander 	void *stor_aux;
121*50a81498SJens Wiklander };
122*50a81498SJens Wiklander 
123*50a81498SJens Wiklander struct traverse_arg;
124*50a81498SJens Wiklander typedef TEE_Result (*traverse_cb_t)(struct traverse_arg *targ,
125*50a81498SJens Wiklander 				    struct htree_node *node);
126*50a81498SJens Wiklander struct traverse_arg {
127*50a81498SJens Wiklander 	struct tee_fs_htree *ht;
128*50a81498SJens Wiklander 	traverse_cb_t cb;
129*50a81498SJens Wiklander 	void *arg;
130*50a81498SJens Wiklander };
131*50a81498SJens Wiklander 
132*50a81498SJens Wiklander static TEE_Result rpc_read(struct tee_fs_htree *ht, enum tee_fs_htree_type type,
133*50a81498SJens Wiklander 			   size_t idx, size_t vers, void *data, size_t dlen)
134*50a81498SJens Wiklander {
135*50a81498SJens Wiklander 	TEE_Result res;
136*50a81498SJens Wiklander 	struct tee_fs_rpc_operation op;
137*50a81498SJens Wiklander 	size_t bytes;
138*50a81498SJens Wiklander 	void *p;
139*50a81498SJens Wiklander 
140*50a81498SJens Wiklander 	res = ht->stor->rpc_read_init(ht->stor_aux, &op, type, idx, vers, &p);
141*50a81498SJens Wiklander 	if (res != TEE_SUCCESS)
142*50a81498SJens Wiklander 		return res;
143*50a81498SJens Wiklander 
144*50a81498SJens Wiklander 	res = tee_fs_rpc_read_final(&op, &bytes);
145*50a81498SJens Wiklander 	if (res != TEE_SUCCESS)
146*50a81498SJens Wiklander 		return res;
147*50a81498SJens Wiklander 
148*50a81498SJens Wiklander 	if (bytes != dlen)
149*50a81498SJens Wiklander 		return TEE_ERROR_CORRUPT_OBJECT;
150*50a81498SJens Wiklander 
151*50a81498SJens Wiklander 	memcpy(data, p, dlen);
152*50a81498SJens Wiklander 	return TEE_SUCCESS;
153*50a81498SJens Wiklander }
154*50a81498SJens Wiklander 
155*50a81498SJens Wiklander static TEE_Result rpc_read_head(struct tee_fs_htree *ht, size_t vers,
156*50a81498SJens Wiklander 				struct tee_fs_htree_image *head)
157*50a81498SJens Wiklander {
158*50a81498SJens Wiklander 	return rpc_read(ht, TEE_FS_HTREE_TYPE_HEAD, 0, vers,
159*50a81498SJens Wiklander 			head, sizeof(*head));
160*50a81498SJens Wiklander }
161*50a81498SJens Wiklander 
162*50a81498SJens Wiklander static TEE_Result rpc_read_node(struct tee_fs_htree *ht, size_t node_id,
163*50a81498SJens Wiklander 				size_t vers,
164*50a81498SJens Wiklander 				struct tee_fs_htree_node_image *node)
165*50a81498SJens Wiklander {
166*50a81498SJens Wiklander 	return rpc_read(ht, TEE_FS_HTREE_TYPE_NODE, node_id - 1, vers,
167*50a81498SJens Wiklander 			node, sizeof(*node));
168*50a81498SJens Wiklander }
169*50a81498SJens Wiklander 
170*50a81498SJens Wiklander static TEE_Result rpc_write(struct tee_fs_htree *ht,
171*50a81498SJens Wiklander 			    enum tee_fs_htree_type type, size_t idx,
172*50a81498SJens Wiklander 			    size_t vers, const void *data, size_t dlen)
173*50a81498SJens Wiklander {
174*50a81498SJens Wiklander 	TEE_Result res;
175*50a81498SJens Wiklander 	struct tee_fs_rpc_operation op;
176*50a81498SJens Wiklander 	void *p;
177*50a81498SJens Wiklander 
178*50a81498SJens Wiklander 	res = ht->stor->rpc_write_init(ht->stor_aux, &op, type, idx, vers, &p);
179*50a81498SJens Wiklander 	if (res != TEE_SUCCESS)
180*50a81498SJens Wiklander 		return res;
181*50a81498SJens Wiklander 
182*50a81498SJens Wiklander 	memcpy(p, data, dlen);
183*50a81498SJens Wiklander 	return tee_fs_rpc_write_final(&op);
184*50a81498SJens Wiklander }
185*50a81498SJens Wiklander 
186*50a81498SJens Wiklander static TEE_Result rpc_write_head(struct tee_fs_htree *ht, size_t vers,
187*50a81498SJens Wiklander 				 const struct tee_fs_htree_image *head)
188*50a81498SJens Wiklander {
189*50a81498SJens Wiklander 	return rpc_write(ht, TEE_FS_HTREE_TYPE_HEAD, 0, vers,
190*50a81498SJens Wiklander 			 head, sizeof(*head));
191*50a81498SJens Wiklander }
192*50a81498SJens Wiklander 
193*50a81498SJens Wiklander static TEE_Result rpc_write_node(struct tee_fs_htree *ht, size_t node_id,
194*50a81498SJens Wiklander 				 size_t vers,
195*50a81498SJens Wiklander 				 const struct tee_fs_htree_node_image *node)
196*50a81498SJens Wiklander {
197*50a81498SJens Wiklander 	return rpc_write(ht, TEE_FS_HTREE_TYPE_NODE, node_id - 1, vers,
198*50a81498SJens Wiklander 			 node, sizeof(*node));
199*50a81498SJens Wiklander }
200*50a81498SJens Wiklander 
201*50a81498SJens Wiklander static TEE_Result traverse_post_order(struct traverse_arg *targ,
202*50a81498SJens Wiklander 				      struct htree_node *node)
203*50a81498SJens Wiklander {
204*50a81498SJens Wiklander 	TEE_Result res;
205*50a81498SJens Wiklander 
206*50a81498SJens Wiklander 	/*
207*50a81498SJens Wiklander 	 * This function is recursing but not very deep, only with Log(N)
208*50a81498SJens Wiklander 	 * maximum depth.
209*50a81498SJens Wiklander 	 */
210*50a81498SJens Wiklander 
211*50a81498SJens Wiklander 	if (!node)
212*50a81498SJens Wiklander 		return TEE_SUCCESS;
213*50a81498SJens Wiklander 
214*50a81498SJens Wiklander 	res = traverse_post_order(targ, node->child[0]);
215*50a81498SJens Wiklander 	if (res != TEE_SUCCESS)
216*50a81498SJens Wiklander 		return res;
217*50a81498SJens Wiklander 
218*50a81498SJens Wiklander 	res = traverse_post_order(targ, node->child[1]);
219*50a81498SJens Wiklander 	if (res != TEE_SUCCESS)
220*50a81498SJens Wiklander 		return res;
221*50a81498SJens Wiklander 
222*50a81498SJens Wiklander 	return targ->cb(targ, node);
223*50a81498SJens Wiklander }
224*50a81498SJens Wiklander 
225*50a81498SJens Wiklander static TEE_Result htree_traverse_post_order(struct tee_fs_htree *ht,
226*50a81498SJens Wiklander 					    traverse_cb_t cb, void *arg)
227*50a81498SJens Wiklander {
228*50a81498SJens Wiklander 	struct traverse_arg targ = { ht, cb, arg };
229*50a81498SJens Wiklander 
230*50a81498SJens Wiklander 	return traverse_post_order(&targ, &ht->root);
231*50a81498SJens Wiklander }
232*50a81498SJens Wiklander 
233*50a81498SJens Wiklander static size_t node_id_to_level(size_t node_id)
234*50a81498SJens Wiklander {
235*50a81498SJens Wiklander 	assert(node_id && node_id < UINT_MAX);
236*50a81498SJens Wiklander 	/* Calculate level of the node, root node (1) has level 1 */
237*50a81498SJens Wiklander 	return sizeof(unsigned int) * 8 - __builtin_clz(node_id);
238*50a81498SJens Wiklander }
239*50a81498SJens Wiklander 
240*50a81498SJens Wiklander static struct htree_node *find_closest_node(struct tee_fs_htree *ht,
241*50a81498SJens Wiklander 					    size_t node_id)
242*50a81498SJens Wiklander {
243*50a81498SJens Wiklander 	struct htree_node *node = &ht->root;
244*50a81498SJens Wiklander 	size_t level = node_id_to_level(node_id);
245*50a81498SJens Wiklander 	size_t n;
246*50a81498SJens Wiklander 
247*50a81498SJens Wiklander 	/* n = 1 because root node is level 1 */
248*50a81498SJens Wiklander 	for (n = 1; n < level; n++) {
249*50a81498SJens Wiklander 		struct htree_node *child;
250*50a81498SJens Wiklander 		size_t bit_idx;
251*50a81498SJens Wiklander 
252*50a81498SJens Wiklander 		/*
253*50a81498SJens Wiklander 		 * The difference between levels of the current node and
254*50a81498SJens Wiklander 		 * the node we're looking for tells which bit decides
255*50a81498SJens Wiklander 		 * direction in the tree.
256*50a81498SJens Wiklander 		 *
257*50a81498SJens Wiklander 		 * As the first bit has index 0 we'll subtract 1
258*50a81498SJens Wiklander 		 */
259*50a81498SJens Wiklander 		bit_idx = level - n - 1;
260*50a81498SJens Wiklander 		child = node->child[((node_id >> bit_idx) & 1)];
261*50a81498SJens Wiklander 		if (!child)
262*50a81498SJens Wiklander 			return node;
263*50a81498SJens Wiklander 		node = child;
264*50a81498SJens Wiklander 	}
265*50a81498SJens Wiklander 
266*50a81498SJens Wiklander 	return node;
267*50a81498SJens Wiklander }
268*50a81498SJens Wiklander 
269*50a81498SJens Wiklander static struct htree_node *find_node(struct tee_fs_htree *ht, size_t node_id)
270*50a81498SJens Wiklander {
271*50a81498SJens Wiklander 	struct htree_node *node = find_closest_node(ht, node_id);
272*50a81498SJens Wiklander 
273*50a81498SJens Wiklander 	if (node && node->id == node_id)
274*50a81498SJens Wiklander 		return node;
275*50a81498SJens Wiklander 	return NULL;
276*50a81498SJens Wiklander }
277*50a81498SJens Wiklander 
278*50a81498SJens Wiklander static TEE_Result get_node(struct tee_fs_htree *ht, bool create,
279*50a81498SJens Wiklander 			   size_t node_id, struct htree_node **node_ret)
280*50a81498SJens Wiklander {
281*50a81498SJens Wiklander 	struct htree_node *node;
282*50a81498SJens Wiklander 	struct htree_node *nc;
283*50a81498SJens Wiklander 	size_t n;
284*50a81498SJens Wiklander 
285*50a81498SJens Wiklander 	node = find_closest_node(ht, node_id);
286*50a81498SJens Wiklander 	if (!node)
287*50a81498SJens Wiklander 		return TEE_ERROR_GENERIC;
288*50a81498SJens Wiklander 	if (node->id == node_id)
289*50a81498SJens Wiklander 		goto ret_node;
290*50a81498SJens Wiklander 
291*50a81498SJens Wiklander 	/*
292*50a81498SJens Wiklander 	 * Trying to read beyond end of file should be caught earlier than
293*50a81498SJens Wiklander 	 * here.
294*50a81498SJens Wiklander 	 */
295*50a81498SJens Wiklander 	if (!create)
296*50a81498SJens Wiklander 		return TEE_ERROR_GENERIC;
297*50a81498SJens Wiklander 
298*50a81498SJens Wiklander 	/*
299*50a81498SJens Wiklander 	 * Add missing nodes, some nodes may already be there. When we've
300*50a81498SJens Wiklander 	 * processed the range all nodes up to node_id will be in the tree.
301*50a81498SJens Wiklander 	 */
302*50a81498SJens Wiklander 	for (n = node->id + 1; n <= node_id; n++) {
303*50a81498SJens Wiklander 		node = find_closest_node(ht, n);
304*50a81498SJens Wiklander 		if (node->id == n)
305*50a81498SJens Wiklander 			continue;
306*50a81498SJens Wiklander 		/* Node id n should be a child of node */
307*50a81498SJens Wiklander 		assert((n >> 1) == node->id);
308*50a81498SJens Wiklander 		assert(!node->child[n & 1]);
309*50a81498SJens Wiklander 
310*50a81498SJens Wiklander 		nc = calloc(1, sizeof(*nc));
311*50a81498SJens Wiklander 		if (!nc)
312*50a81498SJens Wiklander 			return TEE_ERROR_OUT_OF_MEMORY;
313*50a81498SJens Wiklander 		nc->id = n;
314*50a81498SJens Wiklander 		nc->parent = node;
315*50a81498SJens Wiklander 		node->child[n & 1] = nc;
316*50a81498SJens Wiklander 		node = nc;
317*50a81498SJens Wiklander 	}
318*50a81498SJens Wiklander 
319*50a81498SJens Wiklander 	if (node->id > ht->imeta.max_node_id)
320*50a81498SJens Wiklander 		ht->imeta.max_node_id = node->id;
321*50a81498SJens Wiklander 
322*50a81498SJens Wiklander ret_node:
323*50a81498SJens Wiklander 	*node_ret = node;
324*50a81498SJens Wiklander 	return TEE_SUCCESS;
325*50a81498SJens Wiklander }
326*50a81498SJens Wiklander 
327*50a81498SJens Wiklander static int get_idx_from_counter(uint32_t counter0, uint32_t counter1)
328*50a81498SJens Wiklander {
329*50a81498SJens Wiklander 	if (!(counter0 & 1)) {
330*50a81498SJens Wiklander 		if (!(counter1 & 1))
331*50a81498SJens Wiklander 			return 0;
332*50a81498SJens Wiklander 		if (counter0 > counter1)
333*50a81498SJens Wiklander 			return 0;
334*50a81498SJens Wiklander 		else
335*50a81498SJens Wiklander 			return 1;
336*50a81498SJens Wiklander 	}
337*50a81498SJens Wiklander 
338*50a81498SJens Wiklander 	if (counter1 & 1)
339*50a81498SJens Wiklander 		return 1;
340*50a81498SJens Wiklander 	else
341*50a81498SJens Wiklander 		return -1;
342*50a81498SJens Wiklander }
343*50a81498SJens Wiklander 
344*50a81498SJens Wiklander static TEE_Result init_head_from_data(struct tee_fs_htree *ht)
345*50a81498SJens Wiklander {
346*50a81498SJens Wiklander 	TEE_Result res;
347*50a81498SJens Wiklander 	struct tee_fs_htree_image head[2];
348*50a81498SJens Wiklander 	int idx;
349*50a81498SJens Wiklander 
350*50a81498SJens Wiklander 	for (idx = 0; idx < 2; idx++) {
351*50a81498SJens Wiklander 		res = rpc_read_head(ht, idx, head + idx);
352*50a81498SJens Wiklander 		if (res != TEE_SUCCESS)
353*50a81498SJens Wiklander 			return res;
354*50a81498SJens Wiklander 	}
355*50a81498SJens Wiklander 
356*50a81498SJens Wiklander 	idx = get_idx_from_counter(head[0].counter, head[1].counter);
357*50a81498SJens Wiklander 	if (idx < 0)
358*50a81498SJens Wiklander 		return TEE_ERROR_SECURITY;
359*50a81498SJens Wiklander 
360*50a81498SJens Wiklander 	res = rpc_read_node(ht, 1, idx, &ht->root.node);
361*50a81498SJens Wiklander 	if (res != TEE_SUCCESS)
362*50a81498SJens Wiklander 		return res;
363*50a81498SJens Wiklander 
364*50a81498SJens Wiklander 	ht->head = head[idx];
365*50a81498SJens Wiklander 	ht->root.id = 1;
366*50a81498SJens Wiklander 
367*50a81498SJens Wiklander 	return TEE_SUCCESS;
368*50a81498SJens Wiklander }
369*50a81498SJens Wiklander 
370*50a81498SJens Wiklander static TEE_Result init_tree_from_data(struct tee_fs_htree *ht)
371*50a81498SJens Wiklander {
372*50a81498SJens Wiklander 	TEE_Result res;
373*50a81498SJens Wiklander 	struct tee_fs_htree_node_image node_image;
374*50a81498SJens Wiklander 	struct htree_node *node;
375*50a81498SJens Wiklander 	struct htree_node *nc;
376*50a81498SJens Wiklander 	size_t committed_version;
377*50a81498SJens Wiklander 	size_t node_id = 2;
378*50a81498SJens Wiklander 
379*50a81498SJens Wiklander 	while (node_id <= ht->imeta.max_node_id) {
380*50a81498SJens Wiklander 		node = find_node(ht, node_id >> 1);
381*50a81498SJens Wiklander 		if (!node)
382*50a81498SJens Wiklander 			return TEE_ERROR_GENERIC;
383*50a81498SJens Wiklander 		committed_version = !!(node->node.flags &
384*50a81498SJens Wiklander 				    HTREE_NODE_COMMITTED_CHILD(node_id & 1));
385*50a81498SJens Wiklander 
386*50a81498SJens Wiklander 		res = rpc_read_node(ht, node_id, committed_version,
387*50a81498SJens Wiklander 				    &node_image);
388*50a81498SJens Wiklander 		if (res != TEE_SUCCESS)
389*50a81498SJens Wiklander 			return res;
390*50a81498SJens Wiklander 
391*50a81498SJens Wiklander 		res = get_node(ht, true, node_id, &nc);
392*50a81498SJens Wiklander 		if (res != TEE_SUCCESS)
393*50a81498SJens Wiklander 			return res;
394*50a81498SJens Wiklander 		nc->node = node_image;
395*50a81498SJens Wiklander 		node_id++;
396*50a81498SJens Wiklander 	}
397*50a81498SJens Wiklander 
398*50a81498SJens Wiklander 	return TEE_SUCCESS;
399*50a81498SJens Wiklander }
400*50a81498SJens Wiklander 
401*50a81498SJens Wiklander static TEE_Result calc_node_hash(struct htree_node *node, void *ctx,
402*50a81498SJens Wiklander 				 uint8_t *digest)
403*50a81498SJens Wiklander {
404*50a81498SJens Wiklander 	TEE_Result res;
405*50a81498SJens Wiklander 	uint32_t alg = TEE_FS_HTREE_HASH_ALG;
406*50a81498SJens Wiklander 	uint8_t *ndata = (uint8_t *)&node->node + sizeof(node->node.hash);
407*50a81498SJens Wiklander 	size_t nsize = sizeof(node->node) - sizeof(node->node.hash);
408*50a81498SJens Wiklander 
409*50a81498SJens Wiklander 	res = crypto_ops.hash.init(ctx, alg);
410*50a81498SJens Wiklander 	if (res != TEE_SUCCESS)
411*50a81498SJens Wiklander 		return res;
412*50a81498SJens Wiklander 
413*50a81498SJens Wiklander 	res = crypto_ops.hash.update(ctx, alg, ndata, nsize);
414*50a81498SJens Wiklander 	if (res != TEE_SUCCESS)
415*50a81498SJens Wiklander 		return res;
416*50a81498SJens Wiklander 
417*50a81498SJens Wiklander 	if (node->child[0]) {
418*50a81498SJens Wiklander 		res = crypto_ops.hash.update(ctx, alg,
419*50a81498SJens Wiklander 					     node->child[0]->node.hash,
420*50a81498SJens Wiklander 					     sizeof(node->child[0]->node.hash));
421*50a81498SJens Wiklander 		if (res != TEE_SUCCESS)
422*50a81498SJens Wiklander 			return res;
423*50a81498SJens Wiklander 	}
424*50a81498SJens Wiklander 
425*50a81498SJens Wiklander 	if (node->child[1]) {
426*50a81498SJens Wiklander 		res = crypto_ops.hash.update(ctx, alg,
427*50a81498SJens Wiklander 					     node->child[1]->node.hash,
428*50a81498SJens Wiklander 					     sizeof(node->child[1]->node.hash));
429*50a81498SJens Wiklander 		if (res != TEE_SUCCESS)
430*50a81498SJens Wiklander 			return res;
431*50a81498SJens Wiklander 	}
432*50a81498SJens Wiklander 
433*50a81498SJens Wiklander 	return crypto_ops.hash.final(ctx, alg, digest, TEE_FS_HTREE_HASH_SIZE);
434*50a81498SJens Wiklander }
435*50a81498SJens Wiklander 
436*50a81498SJens Wiklander static TEE_Result authenc_init(void **ctx_ret, TEE_OperationMode mode,
437*50a81498SJens Wiklander 			       struct tee_fs_htree *ht,
438*50a81498SJens Wiklander 			       struct tee_fs_htree_node_image *ni,
439*50a81498SJens Wiklander 			       size_t payload_len)
440*50a81498SJens Wiklander {
441*50a81498SJens Wiklander 	TEE_Result res = TEE_SUCCESS;
442*50a81498SJens Wiklander 	const uint32_t alg = TEE_FS_HTREE_AUTH_ENC_ALG;
443*50a81498SJens Wiklander 	uint8_t *ctx;
444*50a81498SJens Wiklander 	size_t ctx_size;
445*50a81498SJens Wiklander 	size_t aad_len = TEE_FS_HTREE_FEK_SIZE + TEE_FS_HTREE_IV_SIZE;
446*50a81498SJens Wiklander 	uint8_t *iv;
447*50a81498SJens Wiklander 
448*50a81498SJens Wiklander 	if (ni) {
449*50a81498SJens Wiklander 		iv = ni->iv;
450*50a81498SJens Wiklander 	} else {
451*50a81498SJens Wiklander 		iv = ht->head.iv;
452*50a81498SJens Wiklander 		aad_len += TEE_FS_HTREE_HASH_SIZE + sizeof(ht->head.counter);
453*50a81498SJens Wiklander 	}
454*50a81498SJens Wiklander 
455*50a81498SJens Wiklander 	if (mode == TEE_MODE_ENCRYPT) {
456*50a81498SJens Wiklander 		res = crypto_ops.prng.read(iv, TEE_FS_HTREE_IV_SIZE);
457*50a81498SJens Wiklander 		if (res != TEE_SUCCESS)
458*50a81498SJens Wiklander 			return res;
459*50a81498SJens Wiklander 	}
460*50a81498SJens Wiklander 
461*50a81498SJens Wiklander 	res = crypto_ops.authenc.get_ctx_size(alg, &ctx_size);
462*50a81498SJens Wiklander 	if (res != TEE_SUCCESS)
463*50a81498SJens Wiklander 		return res;
464*50a81498SJens Wiklander 
465*50a81498SJens Wiklander 	ctx = malloc(ctx_size);
466*50a81498SJens Wiklander 	if (!ctx) {
467*50a81498SJens Wiklander 		EMSG("request memory size %zu failed", ctx_size);
468*50a81498SJens Wiklander 		return TEE_ERROR_OUT_OF_MEMORY;
469*50a81498SJens Wiklander 	}
470*50a81498SJens Wiklander 
471*50a81498SJens Wiklander 	res = crypto_ops.authenc.init(ctx, alg, mode,
472*50a81498SJens Wiklander 				      ht->fek, TEE_FS_HTREE_FEK_SIZE,
473*50a81498SJens Wiklander 				      iv, TEE_FS_HTREE_IV_SIZE,
474*50a81498SJens Wiklander 				      TEE_FS_HTREE_TAG_SIZE, aad_len,
475*50a81498SJens Wiklander 				      payload_len);
476*50a81498SJens Wiklander 	if (res != TEE_SUCCESS)
477*50a81498SJens Wiklander 		goto exit;
478*50a81498SJens Wiklander 
479*50a81498SJens Wiklander 	if (!ni) {
480*50a81498SJens Wiklander 		res = crypto_ops.authenc.update_aad(ctx, alg, mode,
481*50a81498SJens Wiklander 						    ht->root.node.hash,
482*50a81498SJens Wiklander 						    TEE_FS_HTREE_FEK_SIZE);
483*50a81498SJens Wiklander 		if (res != TEE_SUCCESS)
484*50a81498SJens Wiklander 			goto exit;
485*50a81498SJens Wiklander 
486*50a81498SJens Wiklander 		res = crypto_ops.authenc.update_aad(ctx, alg, mode,
487*50a81498SJens Wiklander 						    (void *)&ht->head.counter,
488*50a81498SJens Wiklander 						    sizeof(ht->head.counter));
489*50a81498SJens Wiklander 		if (res != TEE_SUCCESS)
490*50a81498SJens Wiklander 			goto exit;
491*50a81498SJens Wiklander 	}
492*50a81498SJens Wiklander 
493*50a81498SJens Wiklander 	res = crypto_ops.authenc.update_aad(ctx, alg, mode, ht->head.enc_fek,
494*50a81498SJens Wiklander 					    TEE_FS_HTREE_FEK_SIZE);
495*50a81498SJens Wiklander 	if (res != TEE_SUCCESS)
496*50a81498SJens Wiklander 		goto exit;
497*50a81498SJens Wiklander 
498*50a81498SJens Wiklander 	res = crypto_ops.authenc.update_aad(ctx, alg, mode, iv,
499*50a81498SJens Wiklander 					    TEE_FS_HTREE_IV_SIZE);
500*50a81498SJens Wiklander 
501*50a81498SJens Wiklander exit:
502*50a81498SJens Wiklander 	if (res == TEE_SUCCESS)
503*50a81498SJens Wiklander 		*ctx_ret = ctx;
504*50a81498SJens Wiklander 	else
505*50a81498SJens Wiklander 		free(ctx);
506*50a81498SJens Wiklander 
507*50a81498SJens Wiklander 	return res;
508*50a81498SJens Wiklander }
509*50a81498SJens Wiklander 
510*50a81498SJens Wiklander static TEE_Result authenc_decrypt_final(void *ctx, const uint8_t *tag,
511*50a81498SJens Wiklander 					const void *crypt, size_t len,
512*50a81498SJens Wiklander 					void *plain)
513*50a81498SJens Wiklander {
514*50a81498SJens Wiklander 	TEE_Result res;
515*50a81498SJens Wiklander 	size_t out_size = len;
516*50a81498SJens Wiklander 
517*50a81498SJens Wiklander 	res = crypto_ops.authenc.dec_final(ctx, TEE_FS_HTREE_AUTH_ENC_ALG,
518*50a81498SJens Wiklander 					   crypt, len, plain, &out_size,
519*50a81498SJens Wiklander 					   tag, TEE_FS_HTREE_TAG_SIZE);
520*50a81498SJens Wiklander 	crypto_ops.authenc.final(ctx, TEE_FS_HTREE_AUTH_ENC_ALG);
521*50a81498SJens Wiklander 	free(ctx);
522*50a81498SJens Wiklander 
523*50a81498SJens Wiklander 	if (res == TEE_SUCCESS && out_size != len)
524*50a81498SJens Wiklander 		return TEE_ERROR_GENERIC;
525*50a81498SJens Wiklander 	if (res == TEE_ERROR_MAC_INVALID)
526*50a81498SJens Wiklander 		return TEE_ERROR_CORRUPT_OBJECT;
527*50a81498SJens Wiklander 
528*50a81498SJens Wiklander 	return res;
529*50a81498SJens Wiklander }
530*50a81498SJens Wiklander 
531*50a81498SJens Wiklander static TEE_Result authenc_encrypt_final(void *ctx, uint8_t *tag,
532*50a81498SJens Wiklander 					const void *plain, size_t len,
533*50a81498SJens Wiklander 					void *crypt)
534*50a81498SJens Wiklander {
535*50a81498SJens Wiklander 	TEE_Result res;
536*50a81498SJens Wiklander 	size_t out_size = len;
537*50a81498SJens Wiklander 	size_t out_tag_size = TEE_FS_HTREE_TAG_SIZE;
538*50a81498SJens Wiklander 
539*50a81498SJens Wiklander 	res = crypto_ops.authenc.enc_final(ctx, TEE_FS_HTREE_AUTH_ENC_ALG,
540*50a81498SJens Wiklander 					   plain, len, crypt, &out_size,
541*50a81498SJens Wiklander 					   tag, &out_tag_size);
542*50a81498SJens Wiklander 	crypto_ops.authenc.final(ctx, TEE_FS_HTREE_AUTH_ENC_ALG);
543*50a81498SJens Wiklander 	free(ctx);
544*50a81498SJens Wiklander 
545*50a81498SJens Wiklander 	if (res == TEE_SUCCESS &&
546*50a81498SJens Wiklander 	    (out_size != len || out_tag_size != TEE_FS_HTREE_TAG_SIZE))
547*50a81498SJens Wiklander 		return TEE_ERROR_GENERIC;
548*50a81498SJens Wiklander 
549*50a81498SJens Wiklander 	return res;
550*50a81498SJens Wiklander }
551*50a81498SJens Wiklander 
552*50a81498SJens Wiklander static TEE_Result verify_root(struct tee_fs_htree *ht)
553*50a81498SJens Wiklander {
554*50a81498SJens Wiklander 	TEE_Result res;
555*50a81498SJens Wiklander 	void *ctx;
556*50a81498SJens Wiklander 
557*50a81498SJens Wiklander 	res = tee_fs_fek_crypt(TEE_MODE_DECRYPT, ht->head.enc_fek,
558*50a81498SJens Wiklander 			       sizeof(ht->fek), ht->fek);
559*50a81498SJens Wiklander 	if (res != TEE_SUCCESS)
560*50a81498SJens Wiklander 		return res;
561*50a81498SJens Wiklander 
562*50a81498SJens Wiklander 	res = authenc_init(&ctx, TEE_MODE_DECRYPT, ht, NULL, sizeof(ht->imeta));
563*50a81498SJens Wiklander 	if (res != TEE_SUCCESS)
564*50a81498SJens Wiklander 		return res;
565*50a81498SJens Wiklander 
566*50a81498SJens Wiklander 	return authenc_decrypt_final(ctx, ht->head.tag, ht->head.imeta,
567*50a81498SJens Wiklander 				     sizeof(ht->imeta), &ht->imeta);
568*50a81498SJens Wiklander }
569*50a81498SJens Wiklander 
570*50a81498SJens Wiklander static TEE_Result verify_node(struct traverse_arg *targ,
571*50a81498SJens Wiklander 			      struct htree_node *node)
572*50a81498SJens Wiklander {
573*50a81498SJens Wiklander 	void *ctx = targ->arg;
574*50a81498SJens Wiklander 	TEE_Result res;
575*50a81498SJens Wiklander 	uint8_t digest[TEE_FS_HTREE_HASH_SIZE];
576*50a81498SJens Wiklander 
577*50a81498SJens Wiklander 	res = calc_node_hash(node, ctx, digest);
578*50a81498SJens Wiklander 	if (res == TEE_SUCCESS &&
579*50a81498SJens Wiklander 	    buf_compare_ct(digest, node->node.hash, sizeof(digest)))
580*50a81498SJens Wiklander 		return TEE_ERROR_CORRUPT_OBJECT;
581*50a81498SJens Wiklander 
582*50a81498SJens Wiklander 	return res;
583*50a81498SJens Wiklander }
584*50a81498SJens Wiklander 
585*50a81498SJens Wiklander static TEE_Result verify_tree(struct tee_fs_htree *ht)
586*50a81498SJens Wiklander {
587*50a81498SJens Wiklander 	TEE_Result res;
588*50a81498SJens Wiklander 	size_t size;
589*50a81498SJens Wiklander 	void *ctx;
590*50a81498SJens Wiklander 
591*50a81498SJens Wiklander 	if (!crypto_ops.hash.get_ctx_size || !crypto_ops.hash.init ||
592*50a81498SJens Wiklander 	    !crypto_ops.hash.update || !crypto_ops.hash.final)
593*50a81498SJens Wiklander 		return TEE_ERROR_NOT_SUPPORTED;
594*50a81498SJens Wiklander 
595*50a81498SJens Wiklander 	res = crypto_ops.hash.get_ctx_size(TEE_FS_HTREE_HASH_ALG, &size);
596*50a81498SJens Wiklander 	if (res != TEE_SUCCESS)
597*50a81498SJens Wiklander 		return res;
598*50a81498SJens Wiklander 
599*50a81498SJens Wiklander 	ctx = malloc(size);
600*50a81498SJens Wiklander 	if (!ctx)
601*50a81498SJens Wiklander 		return TEE_ERROR_OUT_OF_MEMORY;
602*50a81498SJens Wiklander 
603*50a81498SJens Wiklander 	res = htree_traverse_post_order(ht, verify_node, ctx);
604*50a81498SJens Wiklander 	free(ctx);
605*50a81498SJens Wiklander 
606*50a81498SJens Wiklander 	return res;
607*50a81498SJens Wiklander }
608*50a81498SJens Wiklander 
609*50a81498SJens Wiklander static TEE_Result init_root_node(struct tee_fs_htree *ht)
610*50a81498SJens Wiklander {
611*50a81498SJens Wiklander 	TEE_Result res;
612*50a81498SJens Wiklander 	size_t size;
613*50a81498SJens Wiklander 	void *ctx;
614*50a81498SJens Wiklander 
615*50a81498SJens Wiklander 	res = crypto_ops.hash.get_ctx_size(TEE_FS_HTREE_HASH_ALG, &size);
616*50a81498SJens Wiklander 	if (res != TEE_SUCCESS)
617*50a81498SJens Wiklander 		return res;
618*50a81498SJens Wiklander 	ctx = malloc(size);
619*50a81498SJens Wiklander 	if (!ctx)
620*50a81498SJens Wiklander 		return TEE_ERROR_OUT_OF_MEMORY;
621*50a81498SJens Wiklander 
622*50a81498SJens Wiklander 	ht->root.id = 1;
623*50a81498SJens Wiklander 
624*50a81498SJens Wiklander 	res = calc_node_hash(&ht->root, ctx, ht->root.node.hash);
625*50a81498SJens Wiklander 	free(ctx);
626*50a81498SJens Wiklander 
627*50a81498SJens Wiklander 	return res;
628*50a81498SJens Wiklander }
629*50a81498SJens Wiklander 
630*50a81498SJens Wiklander TEE_Result tee_fs_htree_open(bool create,
631*50a81498SJens Wiklander 			     const struct tee_fs_htree_storage *stor,
632*50a81498SJens Wiklander 			     void *stor_aux, struct tee_fs_htree **ht_ret)
633*50a81498SJens Wiklander {
634*50a81498SJens Wiklander 	TEE_Result res;
635*50a81498SJens Wiklander 	struct tee_fs_htree *ht = calloc(1, sizeof(*ht));
636*50a81498SJens Wiklander 
637*50a81498SJens Wiklander 	if (!ht)
638*50a81498SJens Wiklander 		return TEE_ERROR_OUT_OF_MEMORY;
639*50a81498SJens Wiklander 
640*50a81498SJens Wiklander 	ht->stor = stor;
641*50a81498SJens Wiklander 	ht->stor_aux = stor_aux;
642*50a81498SJens Wiklander 
643*50a81498SJens Wiklander 	if (create) {
644*50a81498SJens Wiklander 		res = crypto_ops.prng.read(ht->fek, sizeof(ht->fek));
645*50a81498SJens Wiklander 		if (res != TEE_SUCCESS)
646*50a81498SJens Wiklander 			goto out;
647*50a81498SJens Wiklander 
648*50a81498SJens Wiklander 		res = tee_fs_fek_crypt(TEE_MODE_ENCRYPT, ht->fek,
649*50a81498SJens Wiklander 				       sizeof(ht->fek), ht->head.enc_fek);
650*50a81498SJens Wiklander 		if (res != TEE_SUCCESS)
651*50a81498SJens Wiklander 			goto out;
652*50a81498SJens Wiklander 
653*50a81498SJens Wiklander 		res = init_root_node(ht);
654*50a81498SJens Wiklander 		if (res != TEE_SUCCESS)
655*50a81498SJens Wiklander 			goto out;
656*50a81498SJens Wiklander 
657*50a81498SJens Wiklander 		ht->dirty = true;
658*50a81498SJens Wiklander 		res = tee_fs_htree_sync_to_storage(&ht);
659*50a81498SJens Wiklander 	} else {
660*50a81498SJens Wiklander 		res = init_head_from_data(ht);
661*50a81498SJens Wiklander 		if (res != TEE_SUCCESS)
662*50a81498SJens Wiklander 			goto out;
663*50a81498SJens Wiklander 
664*50a81498SJens Wiklander 		res = verify_root(ht);
665*50a81498SJens Wiklander 		if (res != TEE_SUCCESS)
666*50a81498SJens Wiklander 			goto out;
667*50a81498SJens Wiklander 
668*50a81498SJens Wiklander 		res = init_tree_from_data(ht);
669*50a81498SJens Wiklander 		if (res != TEE_SUCCESS)
670*50a81498SJens Wiklander 			goto out;
671*50a81498SJens Wiklander 
672*50a81498SJens Wiklander 		res = verify_tree(ht);
673*50a81498SJens Wiklander 	}
674*50a81498SJens Wiklander out:
675*50a81498SJens Wiklander 	if (res == TEE_SUCCESS)
676*50a81498SJens Wiklander 		*ht_ret = ht;
677*50a81498SJens Wiklander 	else
678*50a81498SJens Wiklander 		tee_fs_htree_close(&ht);
679*50a81498SJens Wiklander 	return res;
680*50a81498SJens Wiklander }
681*50a81498SJens Wiklander 
682*50a81498SJens Wiklander struct tee_fs_htree_meta *tee_fs_htree_get_meta(struct tee_fs_htree *ht)
683*50a81498SJens Wiklander {
684*50a81498SJens Wiklander 	return &ht->imeta.meta;
685*50a81498SJens Wiklander }
686*50a81498SJens Wiklander 
687*50a81498SJens Wiklander static TEE_Result free_node(struct traverse_arg *targ __unused,
688*50a81498SJens Wiklander 			    struct htree_node *node)
689*50a81498SJens Wiklander {
690*50a81498SJens Wiklander 	if (node->parent)
691*50a81498SJens Wiklander 		free(node);
692*50a81498SJens Wiklander 	return TEE_SUCCESS;
693*50a81498SJens Wiklander }
694*50a81498SJens Wiklander 
695*50a81498SJens Wiklander void tee_fs_htree_close(struct tee_fs_htree **ht)
696*50a81498SJens Wiklander {
697*50a81498SJens Wiklander 	if (!*ht)
698*50a81498SJens Wiklander 		return;
699*50a81498SJens Wiklander 	htree_traverse_post_order(*ht, free_node, NULL);
700*50a81498SJens Wiklander 	free(*ht);
701*50a81498SJens Wiklander 	*ht = NULL;
702*50a81498SJens Wiklander }
703*50a81498SJens Wiklander 
704*50a81498SJens Wiklander static TEE_Result htree_sync_node_to_storage(struct traverse_arg *targ,
705*50a81498SJens Wiklander 					     struct htree_node *node)
706*50a81498SJens Wiklander {
707*50a81498SJens Wiklander 	TEE_Result res;
708*50a81498SJens Wiklander 	uint8_t vers;
709*50a81498SJens Wiklander 
710*50a81498SJens Wiklander 	if (!node->dirty)
711*50a81498SJens Wiklander 		return TEE_SUCCESS;
712*50a81498SJens Wiklander 
713*50a81498SJens Wiklander 	if (node->parent) {
714*50a81498SJens Wiklander 		uint32_t f = HTREE_NODE_COMMITTED_CHILD(node->id & 1);
715*50a81498SJens Wiklander 
716*50a81498SJens Wiklander 		node->parent->dirty = true;
717*50a81498SJens Wiklander 		node->parent->node.flags ^= f;
718*50a81498SJens Wiklander 		vers = !!(node->parent->node.flags & f);
719*50a81498SJens Wiklander 	} else {
720*50a81498SJens Wiklander 		/*
721*50a81498SJens Wiklander 		 * Counter isn't updated yet, it's increased just before
722*50a81498SJens Wiklander 		 * writing the header.
723*50a81498SJens Wiklander 		 */
724*50a81498SJens Wiklander 		vers = !(targ->ht->head.counter & 1);
725*50a81498SJens Wiklander 	}
726*50a81498SJens Wiklander 	if (node->committed_block !=
727*50a81498SJens Wiklander 	    !!(node->node.flags & HTREE_NODE_COMMITTED_BLOCK))
728*50a81498SJens Wiklander 		node->node.flags ^= HTREE_NODE_COMMITTED_BLOCK;
729*50a81498SJens Wiklander 
730*50a81498SJens Wiklander 
731*50a81498SJens Wiklander 	res = calc_node_hash(node, targ->arg, node->node.hash);
732*50a81498SJens Wiklander 	if (res != TEE_SUCCESS)
733*50a81498SJens Wiklander 		return res;
734*50a81498SJens Wiklander 
735*50a81498SJens Wiklander 	node->dirty = false;
736*50a81498SJens Wiklander 
737*50a81498SJens Wiklander 	return rpc_write_node(targ->ht, node->id, vers, &node->node);
738*50a81498SJens Wiklander }
739*50a81498SJens Wiklander 
740*50a81498SJens Wiklander static TEE_Result update_root(struct tee_fs_htree *ht)
741*50a81498SJens Wiklander {
742*50a81498SJens Wiklander 	TEE_Result res;
743*50a81498SJens Wiklander 	void *ctx;
744*50a81498SJens Wiklander 
745*50a81498SJens Wiklander 	ht->head.counter++;
746*50a81498SJens Wiklander 
747*50a81498SJens Wiklander 	res = authenc_init(&ctx, TEE_MODE_ENCRYPT, ht, NULL, sizeof(ht->imeta));
748*50a81498SJens Wiklander 	if (res != TEE_SUCCESS)
749*50a81498SJens Wiklander 		return res;
750*50a81498SJens Wiklander 
751*50a81498SJens Wiklander 	return authenc_encrypt_final(ctx, ht->head.tag, &ht->imeta,
752*50a81498SJens Wiklander 				     sizeof(ht->imeta), &ht->head.imeta);
753*50a81498SJens Wiklander }
754*50a81498SJens Wiklander 
755*50a81498SJens Wiklander TEE_Result tee_fs_htree_sync_to_storage(struct tee_fs_htree **ht_arg)
756*50a81498SJens Wiklander {
757*50a81498SJens Wiklander 	TEE_Result res;
758*50a81498SJens Wiklander 	struct tee_fs_htree *ht = *ht_arg;
759*50a81498SJens Wiklander 	size_t size;
760*50a81498SJens Wiklander 	void *ctx;
761*50a81498SJens Wiklander 
762*50a81498SJens Wiklander 	if (!ht)
763*50a81498SJens Wiklander 		return TEE_ERROR_CORRUPT_OBJECT;
764*50a81498SJens Wiklander 
765*50a81498SJens Wiklander 	res = crypto_ops.hash.get_ctx_size(TEE_FS_HTREE_HASH_ALG, &size);
766*50a81498SJens Wiklander 	if (res != TEE_SUCCESS)
767*50a81498SJens Wiklander 		return res;
768*50a81498SJens Wiklander 	ctx = malloc(size);
769*50a81498SJens Wiklander 	if (!ctx)
770*50a81498SJens Wiklander 		return TEE_ERROR_OUT_OF_MEMORY;
771*50a81498SJens Wiklander 
772*50a81498SJens Wiklander 	if (!ht->dirty)
773*50a81498SJens Wiklander 		return TEE_SUCCESS;
774*50a81498SJens Wiklander 
775*50a81498SJens Wiklander 	res = htree_traverse_post_order(ht, htree_sync_node_to_storage, ctx);
776*50a81498SJens Wiklander 	if (res != TEE_SUCCESS)
777*50a81498SJens Wiklander 		goto out;
778*50a81498SJens Wiklander 
779*50a81498SJens Wiklander 	/* All the nodes are written to storage now. Time to update root. */
780*50a81498SJens Wiklander 	res = update_root(ht);
781*50a81498SJens Wiklander 	if (res != TEE_SUCCESS)
782*50a81498SJens Wiklander 		goto out;
783*50a81498SJens Wiklander 
784*50a81498SJens Wiklander 	res = rpc_write_head(ht, ht->head.counter & 1, &ht->head);
785*50a81498SJens Wiklander 	if (res != TEE_SUCCESS)
786*50a81498SJens Wiklander 		goto out;
787*50a81498SJens Wiklander 
788*50a81498SJens Wiklander 	ht->dirty = false;
789*50a81498SJens Wiklander out:
790*50a81498SJens Wiklander 	free(ctx);
791*50a81498SJens Wiklander 	if (res != TEE_SUCCESS)
792*50a81498SJens Wiklander 		tee_fs_htree_close(ht_arg);
793*50a81498SJens Wiklander 	return res;
794*50a81498SJens Wiklander }
795*50a81498SJens Wiklander 
796*50a81498SJens Wiklander static TEE_Result get_block_node(struct tee_fs_htree *ht, bool create,
797*50a81498SJens Wiklander 				 size_t block_num, uint8_t *block_vers,
798*50a81498SJens Wiklander 				 struct htree_node **node)
799*50a81498SJens Wiklander {
800*50a81498SJens Wiklander 	TEE_Result res;
801*50a81498SJens Wiklander 	struct htree_node *nd;
802*50a81498SJens Wiklander 
803*50a81498SJens Wiklander 	res = get_node(ht, create, BLOCK_NUM_TO_NODE_ID(block_num), &nd);
804*50a81498SJens Wiklander 	if (res == TEE_SUCCESS) {
805*50a81498SJens Wiklander 		*block_vers = nd->committed_block;
806*50a81498SJens Wiklander 		*node = nd;
807*50a81498SJens Wiklander 	}
808*50a81498SJens Wiklander 
809*50a81498SJens Wiklander 	return res;
810*50a81498SJens Wiklander }
811*50a81498SJens Wiklander 
812*50a81498SJens Wiklander TEE_Result tee_fs_htree_write_block(struct tee_fs_htree **ht_arg,
813*50a81498SJens Wiklander 				    size_t block_num, const void *block)
814*50a81498SJens Wiklander {
815*50a81498SJens Wiklander 	struct tee_fs_htree *ht = *ht_arg;
816*50a81498SJens Wiklander 	TEE_Result res;
817*50a81498SJens Wiklander 	struct tee_fs_rpc_operation op;
818*50a81498SJens Wiklander 	struct htree_node *node = NULL;
819*50a81498SJens Wiklander 	uint8_t block_vers;
820*50a81498SJens Wiklander 	void *ctx;
821*50a81498SJens Wiklander 	void *enc_block;
822*50a81498SJens Wiklander 
823*50a81498SJens Wiklander 	if (!ht)
824*50a81498SJens Wiklander 		return TEE_ERROR_CORRUPT_OBJECT;
825*50a81498SJens Wiklander 
826*50a81498SJens Wiklander 	res = get_block_node(ht, true, block_num, &block_vers, &node);
827*50a81498SJens Wiklander 	if (res != TEE_SUCCESS)
828*50a81498SJens Wiklander 		goto out;
829*50a81498SJens Wiklander 
830*50a81498SJens Wiklander 	res = ht->stor->rpc_write_init(ht->stor_aux, &op,
831*50a81498SJens Wiklander 				       TEE_FS_HTREE_TYPE_BLOCK, block_num,
832*50a81498SJens Wiklander 				       block_vers, &enc_block);
833*50a81498SJens Wiklander 	if (res != TEE_SUCCESS)
834*50a81498SJens Wiklander 		goto out;
835*50a81498SJens Wiklander 
836*50a81498SJens Wiklander 	res = authenc_init(&ctx, TEE_MODE_ENCRYPT, ht, &node->node,
837*50a81498SJens Wiklander 			   ht->stor->block_size);
838*50a81498SJens Wiklander 	if (res != TEE_SUCCESS)
839*50a81498SJens Wiklander 		goto out;
840*50a81498SJens Wiklander 	res = authenc_encrypt_final(ctx, node->node.tag, block,
841*50a81498SJens Wiklander 				    ht->stor->block_size, enc_block);
842*50a81498SJens Wiklander 	if (res != TEE_SUCCESS)
843*50a81498SJens Wiklander 		goto out;
844*50a81498SJens Wiklander 
845*50a81498SJens Wiklander 	res = tee_fs_rpc_write_final(&op);
846*50a81498SJens Wiklander 	if (res != TEE_SUCCESS)
847*50a81498SJens Wiklander 		goto out;
848*50a81498SJens Wiklander 
849*50a81498SJens Wiklander 	if (node->committed_block !=
850*50a81498SJens Wiklander 	    !!(node->node.flags & HTREE_NODE_COMMITTED_BLOCK))
851*50a81498SJens Wiklander 		node->committed_block = !node->committed_block;
852*50a81498SJens Wiklander 
853*50a81498SJens Wiklander 	node->dirty = true;
854*50a81498SJens Wiklander 	ht->dirty = true;
855*50a81498SJens Wiklander out:
856*50a81498SJens Wiklander 	if (res != TEE_SUCCESS)
857*50a81498SJens Wiklander 		tee_fs_htree_close(ht_arg);
858*50a81498SJens Wiklander 	return res;
859*50a81498SJens Wiklander }
860*50a81498SJens Wiklander 
861*50a81498SJens Wiklander TEE_Result tee_fs_htree_read_block(struct tee_fs_htree **ht_arg,
862*50a81498SJens Wiklander 				   size_t block_num, void *block)
863*50a81498SJens Wiklander {
864*50a81498SJens Wiklander 	struct tee_fs_htree *ht = *ht_arg;
865*50a81498SJens Wiklander 	TEE_Result res;
866*50a81498SJens Wiklander 	struct tee_fs_rpc_operation op;
867*50a81498SJens Wiklander 	struct htree_node *node;
868*50a81498SJens Wiklander 	uint8_t block_vers;
869*50a81498SJens Wiklander 	size_t len;
870*50a81498SJens Wiklander 	void *ctx;
871*50a81498SJens Wiklander 	void *enc_block;
872*50a81498SJens Wiklander 
873*50a81498SJens Wiklander 	if (!ht)
874*50a81498SJens Wiklander 		return TEE_ERROR_CORRUPT_OBJECT;
875*50a81498SJens Wiklander 
876*50a81498SJens Wiklander 	res = get_block_node(ht, false, block_num, &block_vers, &node);
877*50a81498SJens Wiklander 	if (res != TEE_SUCCESS)
878*50a81498SJens Wiklander 		goto out;
879*50a81498SJens Wiklander 
880*50a81498SJens Wiklander 	res = ht->stor->rpc_read_init(ht->stor_aux, &op,
881*50a81498SJens Wiklander 				      TEE_FS_HTREE_TYPE_BLOCK, block_num,
882*50a81498SJens Wiklander 				      block_vers, &enc_block);
883*50a81498SJens Wiklander 	if (res != TEE_SUCCESS)
884*50a81498SJens Wiklander 		goto out;
885*50a81498SJens Wiklander 
886*50a81498SJens Wiklander 	res = tee_fs_rpc_read_final(&op, &len);
887*50a81498SJens Wiklander 	if (res != TEE_SUCCESS)
888*50a81498SJens Wiklander 		goto out;
889*50a81498SJens Wiklander 	if (len != ht->stor->block_size) {
890*50a81498SJens Wiklander 		res = TEE_ERROR_CORRUPT_OBJECT;
891*50a81498SJens Wiklander 		goto out;
892*50a81498SJens Wiklander 	}
893*50a81498SJens Wiklander 
894*50a81498SJens Wiklander 	res = authenc_init(&ctx, TEE_MODE_DECRYPT, ht, &node->node,
895*50a81498SJens Wiklander 			   ht->stor->block_size);
896*50a81498SJens Wiklander 	if (res != TEE_SUCCESS)
897*50a81498SJens Wiklander 		goto out;
898*50a81498SJens Wiklander 
899*50a81498SJens Wiklander 	res = authenc_decrypt_final(ctx, node->node.tag, enc_block,
900*50a81498SJens Wiklander 				    ht->stor->block_size, block);
901*50a81498SJens Wiklander out:
902*50a81498SJens Wiklander 	if (res != TEE_SUCCESS)
903*50a81498SJens Wiklander 		tee_fs_htree_close(ht_arg);
904*50a81498SJens Wiklander 	return res;
905*50a81498SJens Wiklander }
906*50a81498SJens Wiklander 
907*50a81498SJens Wiklander TEE_Result tee_fs_htree_truncate(struct tee_fs_htree **ht_arg, size_t block_num)
908*50a81498SJens Wiklander {
909*50a81498SJens Wiklander 	struct tee_fs_htree *ht = *ht_arg;
910*50a81498SJens Wiklander 	size_t node_id = BLOCK_NUM_TO_NODE_ID(block_num);
911*50a81498SJens Wiklander 	struct htree_node *node;
912*50a81498SJens Wiklander 
913*50a81498SJens Wiklander 	if (!ht)
914*50a81498SJens Wiklander 		return TEE_ERROR_CORRUPT_OBJECT;
915*50a81498SJens Wiklander 
916*50a81498SJens Wiklander 	while (node_id < ht->imeta.max_node_id) {
917*50a81498SJens Wiklander 		node = find_closest_node(ht, ht->imeta.max_node_id);
918*50a81498SJens Wiklander 		assert(node && node->id == ht->imeta.max_node_id);
919*50a81498SJens Wiklander 		assert(!node->child[0] && !node->child[1]);
920*50a81498SJens Wiklander 		assert(node->parent);
921*50a81498SJens Wiklander 		assert(node->parent->child[node->id & 1] == node);
922*50a81498SJens Wiklander 		node->parent->child[node->id & 1] = NULL;
923*50a81498SJens Wiklander 		free(node);
924*50a81498SJens Wiklander 		ht->imeta.max_node_id--;
925*50a81498SJens Wiklander 		ht->dirty = true;
926*50a81498SJens Wiklander 	}
927*50a81498SJens Wiklander 
928*50a81498SJens Wiklander 	return TEE_SUCCESS;
929*50a81498SJens Wiklander }
930