2 * Copyright (c) 2017, Linaro Limited
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are met:
8 * 1. Redistributions of source code must retain the above copyright notice,
9 * this list of conditions and the following disclaimer.
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.
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.
30 #include <kernel/tee_common_otp.h>
31 #include <optee_msg_supplicant.h>
33 #include <string_ext.h>
35 #include <tee/fs_htree.h>
36 #include <tee/tee_cryp_provider.h>
37 #include <tee/tee_fs_key_manager.h>
38 #include <tee/tee_fs_rpc.h>
39 #include <utee_defines.h>
42 #define TEE_FS_HTREE_CHIP_ID_SIZE 32
43 #define TEE_FS_HTREE_HASH_ALG TEE_ALG_SHA256
44 #define TEE_FS_HTREE_TSK_SIZE TEE_FS_HTREE_HASH_SIZE
45 #define TEE_FS_HTREE_ENC_ALG TEE_ALG_AES_ECB_NOPAD
46 #define TEE_FS_HTREE_ENC_SIZE TEE_AES_BLOCK_SIZE
47 #define TEE_FS_HTREE_SSK_SIZE TEE_FS_HTREE_HASH_SIZE
49 #define TEE_FS_HTREE_AUTH_ENC_ALG TEE_ALG_AES_GCM
50 #define TEE_FS_HTREE_HMAC_ALG TEE_ALG_HMAC_SHA256
52 #define BLOCK_NUM_TO_NODE_ID(num) ((num) + 1)
54 #define NODE_ID_TO_BLOCK_NUM(id) ((id) - 1)
57 * The hash tree is implemented as a binary tree with the purpose to ensure
58 * integrity of the data in the nodes. The data in the nodes their turn
59 * provides both integrity and confidentiality of the data blocks.
61 * The hash tree is saved in a file as:
62 * +----------------------------+
65 * +----------------------------+
66 * | htree_node_image.1.0 |
67 * | htree_node_image.1.1 |
68 * +----------------------------+
69 * | htree_node_image.2.0 |
70 * | htree_node_image.2.1 |
71 * +----------------------------+
72 * | htree_node_image.3.0 |
73 * | htree_node_image.3.1 |
74 * +----------------------------+
75 * | htree_node_image.4.0 |
76 * | htree_node_image.4.1 |
77 * +----------------------------+
80 * htree_image is the header of the file, there's two instances of it. One
81 * which is committed and the other is used when updating the file. Which
82 * is committed is indicated by the "counter" field, the one with the
83 * largest value is selected.
85 * htree_node_image is a node in the hash tree, each node has two instances
86 * which is committed is decided by the parent node .flag bit
87 * HTREE_NODE_COMMITTED_CHILD. Which version is the committed version of
88 * node 1 is determined by the by the lowest bit of the counter field in
91 * Note that nodes start counting at 1 while blocks at 0, this means that
92 * block 0 is represented by node 1.
94 * Where different elements are stored in the file is managed by the file
95 * system. In the case of SQL FS the version of the node/block is ignored
96 * as the atomic update is finalized with a call to
97 * tee_fs_rpc_end_transaction().
100 #define HTREE_NODE_COMMITTED_BLOCK BIT32(0)
102 #define HTREE_NODE_COMMITTED_CHILD(n) BIT32(1 + (n))
108 struct tee_fs_htree_node_image node;
109 struct htree_node *parent;
110 struct htree_node *child[2];
113 struct tee_fs_htree {
114 struct htree_node root;
115 struct tee_fs_htree_image head;
116 uint8_t fek[TEE_FS_HTREE_FEK_SIZE];
117 struct tee_fs_htree_imeta imeta;
119 const struct tee_fs_htree_storage *stor;
124 typedef TEE_Result (*traverse_cb_t)(struct traverse_arg *targ,
125 struct htree_node *node);
126 struct traverse_arg {
127 struct tee_fs_htree *ht;
132 static TEE_Result rpc_read(struct tee_fs_htree *ht, enum tee_fs_htree_type type,
133 size_t idx, size_t vers, void *data, size_t dlen)
136 struct tee_fs_rpc_operation op;
140 res = ht->stor->rpc_read_init(ht->stor_aux, &op, type, idx, vers, &p);
141 if (res != TEE_SUCCESS)
144 res = ht->stor->rpc_read_final(&op, &bytes);
145 if (res != TEE_SUCCESS)
149 return TEE_ERROR_CORRUPT_OBJECT;
151 memcpy(data, p, dlen);
155 static TEE_Result rpc_read_head(struct tee_fs_htree *ht, size_t vers,
156 struct tee_fs_htree_image *head)
158 return rpc_read(ht, TEE_FS_HTREE_TYPE_HEAD, 0, vers,
159 head, sizeof(*head));
162 static TEE_Result rpc_read_node(struct tee_fs_htree *ht, size_t node_id,
164 struct tee_fs_htree_node_image *node)
166 return rpc_read(ht, TEE_FS_HTREE_TYPE_NODE, node_id - 1, vers,
167 node, sizeof(*node));
170 static TEE_Result rpc_write(struct tee_fs_htree *ht,
171 enum tee_fs_htree_type type, size_t idx,
172 size_t vers, const void *data, size_t dlen)
175 struct tee_fs_rpc_operation op;
178 res = ht->stor->rpc_write_init(ht->stor_aux, &op, type, idx, vers, &p);
179 if (res != TEE_SUCCESS)
182 memcpy(p, data, dlen);
183 return ht->stor->rpc_write_final(&op);
186 static TEE_Result rpc_write_head(struct tee_fs_htree *ht, size_t vers,
187 const struct tee_fs_htree_image *head)
189 return rpc_write(ht, TEE_FS_HTREE_TYPE_HEAD, 0, vers,
190 head, sizeof(*head));
193 static TEE_Result rpc_write_node(struct tee_fs_htree *ht, size_t node_id,
195 const struct tee_fs_htree_node_image *node)
197 return rpc_write(ht, TEE_FS_HTREE_TYPE_NODE, node_id - 1, vers,
198 node, sizeof(*node));
201 static TEE_Result traverse_post_order(struct traverse_arg *targ,
202 struct htree_node *node)
207 * This function is recursing but not very deep, only with Log(N)
214 res = traverse_post_order(targ, node->child[0]);
215 if (res != TEE_SUCCESS)
218 res = traverse_post_order(targ, node->child[1]);
219 if (res != TEE_SUCCESS)
222 return targ->cb(targ, node);
225 static TEE_Result htree_traverse_post_order(struct tee_fs_htree *ht,
226 traverse_cb_t cb, void *arg)
228 struct traverse_arg targ = { ht, cb, arg };
230 return traverse_post_order(&targ, &ht->root);
233 static size_t node_id_to_level(size_t node_id)
235 assert(node_id && node_id < UINT_MAX);
236 /* Calculate level of the node, root node (1) has level 1 */
237 return sizeof(unsigned int) * 8 - __builtin_clz(node_id);
240 static struct htree_node *find_closest_node(struct tee_fs_htree *ht,
243 struct htree_node *node = &ht->root;
244 size_t level = node_id_to_level(node_id);
247 /* n = 1 because root node is level 1 */
248 for (n = 1; n < level; n++) {
249 struct htree_node *child;
253 * The difference between levels of the current node and
254 * the node we're looking for tells which bit decides
255 * direction in the tree.
257 * As the first bit has index 0 we'll subtract 1
259 bit_idx = level - n - 1;
260 child = node->child[((node_id >> bit_idx) & 1)];
269 static struct htree_node *find_node(struct tee_fs_htree *ht, size_t node_id)
271 struct htree_node *node = find_closest_node(ht, node_id);
273 if (node && node->id == node_id)
278 static TEE_Result get_node(struct tee_fs_htree *ht, bool create,
279 size_t node_id, struct htree_node **node_ret)
281 struct htree_node *node;
282 struct htree_node *nc;
285 node = find_closest_node(ht, node_id);
287 return TEE_ERROR_GENERIC;
288 if (node->id == node_id)
292 * Trying to read beyond end of file should be caught earlier than
296 return TEE_ERROR_GENERIC;
299 * Add missing nodes, some nodes may already be there. When we've
300 * processed the range all nodes up to node_id will be in the tree.
302 for (n = node->id + 1; n <= node_id; n++) {
303 node = find_closest_node(ht, n);
306 /* Node id n should be a child of node */
307 assert((n >> 1) == node->id);
308 assert(!node->child[n & 1]);
310 nc = calloc(1, sizeof(*nc));
312 return TEE_ERROR_OUT_OF_MEMORY;
315 node->child[n & 1] = nc;
319 if (node->id > ht->imeta.max_node_id)
320 ht->imeta.max_node_id = node->id;
327 static int get_idx_from_counter(uint32_t counter0, uint32_t counter1)
329 if (!(counter0 & 1)) {
332 if (counter0 > counter1)
344 static TEE_Result init_head_from_data(struct tee_fs_htree *ht)
347 struct tee_fs_htree_image head[2];
350 for (idx = 0; idx < 2; idx++) {
351 res = rpc_read_head(ht, idx, head + idx);
352 if (res != TEE_SUCCESS)
356 idx = get_idx_from_counter(head[0].counter, head[1].counter);
358 return TEE_ERROR_SECURITY;
360 res = rpc_read_node(ht, 1, idx, &ht->root.node);
361 if (res != TEE_SUCCESS)
364 ht->head = head[idx];
370 static TEE_Result init_tree_from_data(struct tee_fs_htree *ht)
373 struct tee_fs_htree_node_image node_image;
374 struct htree_node *node;
375 struct htree_node *nc;
376 size_t committed_version;
379 while (node_id <= ht->imeta.max_node_id) {
380 node = find_node(ht, node_id >> 1);
382 return TEE_ERROR_GENERIC;
383 committed_version = !!(node->node.flags &
384 HTREE_NODE_COMMITTED_CHILD(node_id & 1));
386 res = rpc_read_node(ht, node_id, committed_version,
388 if (res != TEE_SUCCESS)
391 res = get_node(ht, true, node_id, &nc);
392 if (res != TEE_SUCCESS)
394 nc->node = node_image;
401 static TEE_Result calc_node_hash(struct htree_node *node, void *ctx,
405 uint32_t alg = TEE_FS_HTREE_HASH_ALG;
406 uint8_t *ndata = (uint8_t *)&node->node + sizeof(node->node.hash);
407 size_t nsize = sizeof(node->node) - sizeof(node->node.hash);
409 res = crypto_ops.hash.init(ctx, alg);
410 if (res != TEE_SUCCESS)
413 res = crypto_ops.hash.update(ctx, alg, ndata, nsize);
414 if (res != TEE_SUCCESS)
417 if (node->child[0]) {
418 res = crypto_ops.hash.update(ctx, alg,
419 node->child[0]->node.hash,
420 sizeof(node->child[0]->node.hash));
421 if (res != TEE_SUCCESS)
425 if (node->child[1]) {
426 res = crypto_ops.hash.update(ctx, alg,
427 node->child[1]->node.hash,
428 sizeof(node->child[1]->node.hash));
429 if (res != TEE_SUCCESS)
433 return crypto_ops.hash.final(ctx, alg, digest, TEE_FS_HTREE_HASH_SIZE);
436 static TEE_Result authenc_init(void **ctx_ret, TEE_OperationMode mode,
437 struct tee_fs_htree *ht,
438 struct tee_fs_htree_node_image *ni,
441 TEE_Result res = TEE_SUCCESS;
442 const uint32_t alg = TEE_FS_HTREE_AUTH_ENC_ALG;
445 size_t aad_len = TEE_FS_HTREE_FEK_SIZE + TEE_FS_HTREE_IV_SIZE;
452 aad_len += TEE_FS_HTREE_HASH_SIZE + sizeof(ht->head.counter);
455 if (mode == TEE_MODE_ENCRYPT) {
456 res = crypto_ops.prng.read(iv, TEE_FS_HTREE_IV_SIZE);
457 if (res != TEE_SUCCESS)
461 res = crypto_ops.authenc.get_ctx_size(alg, &ctx_size);
462 if (res != TEE_SUCCESS)
465 ctx = malloc(ctx_size);
467 EMSG("request memory size %zu failed", ctx_size);
468 return TEE_ERROR_OUT_OF_MEMORY;
471 res = crypto_ops.authenc.init(ctx, alg, mode,
472 ht->fek, TEE_FS_HTREE_FEK_SIZE,
473 iv, TEE_FS_HTREE_IV_SIZE,
474 TEE_FS_HTREE_TAG_SIZE, aad_len,
476 if (res != TEE_SUCCESS)
480 res = crypto_ops.authenc.update_aad(ctx, alg, mode,
482 TEE_FS_HTREE_FEK_SIZE);
483 if (res != TEE_SUCCESS)
486 res = crypto_ops.authenc.update_aad(ctx, alg, mode,
487 (void *)&ht->head.counter,
488 sizeof(ht->head.counter));
489 if (res != TEE_SUCCESS)
493 res = crypto_ops.authenc.update_aad(ctx, alg, mode, ht->head.enc_fek,
494 TEE_FS_HTREE_FEK_SIZE);
495 if (res != TEE_SUCCESS)
498 res = crypto_ops.authenc.update_aad(ctx, alg, mode, iv,
499 TEE_FS_HTREE_IV_SIZE);
502 if (res == TEE_SUCCESS)
510 static TEE_Result authenc_decrypt_final(void *ctx, const uint8_t *tag,
511 const void *crypt, size_t len,
515 size_t out_size = len;
517 res = crypto_ops.authenc.dec_final(ctx, TEE_FS_HTREE_AUTH_ENC_ALG,
518 crypt, len, plain, &out_size,
519 tag, TEE_FS_HTREE_TAG_SIZE);
520 crypto_ops.authenc.final(ctx, TEE_FS_HTREE_AUTH_ENC_ALG);
523 if (res == TEE_SUCCESS && out_size != len)
524 return TEE_ERROR_GENERIC;
525 if (res == TEE_ERROR_MAC_INVALID)
526 return TEE_ERROR_CORRUPT_OBJECT;
531 static TEE_Result authenc_encrypt_final(void *ctx, uint8_t *tag,
532 const void *plain, size_t len,
536 size_t out_size = len;
537 size_t out_tag_size = TEE_FS_HTREE_TAG_SIZE;
539 res = crypto_ops.authenc.enc_final(ctx, TEE_FS_HTREE_AUTH_ENC_ALG,
540 plain, len, crypt, &out_size,
542 crypto_ops.authenc.final(ctx, TEE_FS_HTREE_AUTH_ENC_ALG);
545 if (res == TEE_SUCCESS &&
546 (out_size != len || out_tag_size != TEE_FS_HTREE_TAG_SIZE))
547 return TEE_ERROR_GENERIC;
552 static TEE_Result verify_root(struct tee_fs_htree *ht)
557 res = tee_fs_fek_crypt(TEE_MODE_DECRYPT, ht->head.enc_fek,
558 sizeof(ht->fek), ht->fek);
559 if (res != TEE_SUCCESS)
562 res = authenc_init(&ctx, TEE_MODE_DECRYPT, ht, NULL, sizeof(ht->imeta));
563 if (res != TEE_SUCCESS)
566 return authenc_decrypt_final(ctx, ht->head.tag, ht->head.imeta,
567 sizeof(ht->imeta), &ht->imeta);
570 static TEE_Result verify_node(struct traverse_arg *targ,
571 struct htree_node *node)
573 void *ctx = targ->arg;
575 uint8_t digest[TEE_FS_HTREE_HASH_SIZE];
577 res = calc_node_hash(node, ctx, digest);
578 if (res == TEE_SUCCESS &&
579 buf_compare_ct(digest, node->node.hash, sizeof(digest)))
580 return TEE_ERROR_CORRUPT_OBJECT;
585 static TEE_Result verify_tree(struct tee_fs_htree *ht)
591 if (!crypto_ops.hash.get_ctx_size || !crypto_ops.hash.init ||
592 !crypto_ops.hash.update || !crypto_ops.hash.final)
593 return TEE_ERROR_NOT_SUPPORTED;
595 res = crypto_ops.hash.get_ctx_size(TEE_FS_HTREE_HASH_ALG, &size);
596 if (res != TEE_SUCCESS)
601 return TEE_ERROR_OUT_OF_MEMORY;
603 res = htree_traverse_post_order(ht, verify_node, ctx);
609 static TEE_Result init_root_node(struct tee_fs_htree *ht)
615 res = crypto_ops.hash.get_ctx_size(TEE_FS_HTREE_HASH_ALG, &size);
616 if (res != TEE_SUCCESS)
620 return TEE_ERROR_OUT_OF_MEMORY;
624 res = calc_node_hash(&ht->root, ctx, ht->root.node.hash);
630 TEE_Result tee_fs_htree_open(bool create,
631 const struct tee_fs_htree_storage *stor,
632 void *stor_aux, struct tee_fs_htree **ht_ret)
635 struct tee_fs_htree *ht = calloc(1, sizeof(*ht));
638 return TEE_ERROR_OUT_OF_MEMORY;
641 ht->stor_aux = stor_aux;
644 const struct tee_fs_htree_image dummy_head = { .counter = 0 };
646 res = crypto_ops.prng.read(ht->fek, sizeof(ht->fek));
647 if (res != TEE_SUCCESS)
650 res = tee_fs_fek_crypt(TEE_MODE_ENCRYPT, ht->fek,
651 sizeof(ht->fek), ht->head.enc_fek);
652 if (res != TEE_SUCCESS)
655 res = init_root_node(ht);
656 if (res != TEE_SUCCESS)
660 res = tee_fs_htree_sync_to_storage(&ht);
661 if (res != TEE_SUCCESS)
663 res = rpc_write_head(ht, 0, &dummy_head);
665 res = init_head_from_data(ht);
666 if (res != TEE_SUCCESS)
669 res = verify_root(ht);
670 if (res != TEE_SUCCESS)
673 res = init_tree_from_data(ht);
674 if (res != TEE_SUCCESS)
677 res = verify_tree(ht);
680 if (res == TEE_SUCCESS)
683 tee_fs_htree_close(&ht);
687 struct tee_fs_htree_meta *tee_fs_htree_get_meta(struct tee_fs_htree *ht)
689 return &ht->imeta.meta;
692 static TEE_Result free_node(struct traverse_arg *targ __unused,
693 struct htree_node *node)
700 void tee_fs_htree_close(struct tee_fs_htree **ht)
704 htree_traverse_post_order(*ht, free_node, NULL);
709 static TEE_Result htree_sync_node_to_storage(struct traverse_arg *targ,
710 struct htree_node *node)
716 * The node can be dirty while the block isn't updated due to
717 * updated children, but if block is updated the node has to be
720 assert(node->dirty >= node->block_updated);
726 uint32_t f = HTREE_NODE_COMMITTED_CHILD(node->id & 1);
728 node->parent->dirty = true;
729 node->parent->node.flags ^= f;
730 vers = !!(node->parent->node.flags & f);
733 * Counter isn't updated yet, it's increased just before
734 * writing the header.
736 vers = !(targ->ht->head.counter & 1);
739 res = calc_node_hash(node, targ->arg, node->node.hash);
740 if (res != TEE_SUCCESS)
744 node->block_updated = false;
746 return rpc_write_node(targ->ht, node->id, vers, &node->node);
749 static TEE_Result update_root(struct tee_fs_htree *ht)
756 res = authenc_init(&ctx, TEE_MODE_ENCRYPT, ht, NULL, sizeof(ht->imeta));
757 if (res != TEE_SUCCESS)
760 return authenc_encrypt_final(ctx, ht->head.tag, &ht->imeta,
761 sizeof(ht->imeta), &ht->head.imeta);
764 TEE_Result tee_fs_htree_sync_to_storage(struct tee_fs_htree **ht_arg)
767 struct tee_fs_htree *ht = *ht_arg;
772 return TEE_ERROR_CORRUPT_OBJECT;
777 res = crypto_ops.hash.get_ctx_size(TEE_FS_HTREE_HASH_ALG, &size);
778 if (res != TEE_SUCCESS)
782 return TEE_ERROR_OUT_OF_MEMORY;
784 res = htree_traverse_post_order(ht, htree_sync_node_to_storage, ctx);
785 if (res != TEE_SUCCESS)
788 /* All the nodes are written to storage now. Time to update root. */
789 res = update_root(ht);
790 if (res != TEE_SUCCESS)
793 res = rpc_write_head(ht, ht->head.counter & 1, &ht->head);
794 if (res != TEE_SUCCESS)
800 if (res != TEE_SUCCESS)
801 tee_fs_htree_close(ht_arg);
805 static TEE_Result get_block_node(struct tee_fs_htree *ht, bool create,
806 size_t block_num, struct htree_node **node)
809 struct htree_node *nd;
811 res = get_node(ht, create, BLOCK_NUM_TO_NODE_ID(block_num), &nd);
812 if (res == TEE_SUCCESS)
818 TEE_Result tee_fs_htree_write_block(struct tee_fs_htree **ht_arg,
819 size_t block_num, const void *block)
821 struct tee_fs_htree *ht = *ht_arg;
823 struct tee_fs_rpc_operation op;
824 struct htree_node *node = NULL;
830 return TEE_ERROR_CORRUPT_OBJECT;
832 res = get_block_node(ht, true, block_num, &node);
833 if (res != TEE_SUCCESS)
836 if (!node->block_updated)
837 node->node.flags ^= HTREE_NODE_COMMITTED_BLOCK;
839 block_vers = !!(node->node.flags & HTREE_NODE_COMMITTED_BLOCK);
840 res = ht->stor->rpc_write_init(ht->stor_aux, &op,
841 TEE_FS_HTREE_TYPE_BLOCK, block_num,
842 block_vers, &enc_block);
843 if (res != TEE_SUCCESS)
846 res = authenc_init(&ctx, TEE_MODE_ENCRYPT, ht, &node->node,
847 ht->stor->block_size);
848 if (res != TEE_SUCCESS)
850 res = authenc_encrypt_final(ctx, node->node.tag, block,
851 ht->stor->block_size, enc_block);
852 if (res != TEE_SUCCESS)
855 res = ht->stor->rpc_write_final(&op);
856 if (res != TEE_SUCCESS)
859 node->block_updated = true;
863 if (res != TEE_SUCCESS)
864 tee_fs_htree_close(ht_arg);
868 TEE_Result tee_fs_htree_read_block(struct tee_fs_htree **ht_arg,
869 size_t block_num, void *block)
871 struct tee_fs_htree *ht = *ht_arg;
873 struct tee_fs_rpc_operation op;
874 struct htree_node *node;
881 return TEE_ERROR_CORRUPT_OBJECT;
883 res = get_block_node(ht, false, block_num, &node);
884 if (res != TEE_SUCCESS)
887 block_vers = !!(node->node.flags & HTREE_NODE_COMMITTED_BLOCK);
888 res = ht->stor->rpc_read_init(ht->stor_aux, &op,
889 TEE_FS_HTREE_TYPE_BLOCK, block_num,
890 block_vers, &enc_block);
891 if (res != TEE_SUCCESS)
894 res = ht->stor->rpc_read_final(&op, &len);
895 if (res != TEE_SUCCESS)
897 if (len != ht->stor->block_size) {
898 res = TEE_ERROR_CORRUPT_OBJECT;
902 res = authenc_init(&ctx, TEE_MODE_DECRYPT, ht, &node->node,
903 ht->stor->block_size);
904 if (res != TEE_SUCCESS)
907 res = authenc_decrypt_final(ctx, node->node.tag, enc_block,
908 ht->stor->block_size, block);
910 if (res != TEE_SUCCESS)
911 tee_fs_htree_close(ht_arg);
915 TEE_Result tee_fs_htree_truncate(struct tee_fs_htree **ht_arg, size_t block_num)
917 struct tee_fs_htree *ht = *ht_arg;
918 size_t node_id = BLOCK_NUM_TO_NODE_ID(block_num);
919 struct htree_node *node;
922 return TEE_ERROR_CORRUPT_OBJECT;
924 while (node_id < ht->imeta.max_node_id) {
925 node = find_closest_node(ht, ht->imeta.max_node_id);
926 assert(node && node->id == ht->imeta.max_node_id);
927 assert(!node->child[0] && !node->child[1]);
928 assert(node->parent);
929 assert(node->parent->child[node->id & 1] == node);
930 node->parent->child[node->id & 1] = NULL;
932 ht->imeta.max_node_id--;