150a81498SJens Wiklander /* 250a81498SJens Wiklander * Copyright (c) 2017, Linaro Limited 350a81498SJens Wiklander * All rights reserved. 450a81498SJens Wiklander * 550a81498SJens Wiklander * Redistribution and use in source and binary forms, with or without 650a81498SJens Wiklander * modification, are permitted provided that the following conditions are met: 750a81498SJens Wiklander * 850a81498SJens Wiklander * 1. Redistributions of source code must retain the above copyright notice, 950a81498SJens Wiklander * this list of conditions and the following disclaimer. 1050a81498SJens Wiklander * 1150a81498SJens Wiklander * 2. Redistributions in binary form must reproduce the above copyright notice, 1250a81498SJens Wiklander * this list of conditions and the following disclaimer in the documentation 1350a81498SJens Wiklander * and/or other materials provided with the distribution. 1450a81498SJens Wiklander * 1550a81498SJens Wiklander * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 1650a81498SJens Wiklander * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 1750a81498SJens Wiklander * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 1850a81498SJens Wiklander * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 1950a81498SJens Wiklander * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 2050a81498SJens Wiklander * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 2150a81498SJens Wiklander * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 2250a81498SJens Wiklander * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 2350a81498SJens Wiklander * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 2450a81498SJens Wiklander * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 2550a81498SJens Wiklander * POSSIBILITY OF SUCH DAMAGE. 2650a81498SJens Wiklander */ 2750a81498SJens Wiklander 2850a81498SJens Wiklander #include <assert.h> 2950a81498SJens Wiklander #include <initcall.h> 3050a81498SJens Wiklander #include <kernel/tee_common_otp.h> 3150a81498SJens Wiklander #include <optee_msg_supplicant.h> 3250a81498SJens Wiklander #include <stdlib.h> 3350a81498SJens Wiklander #include <string_ext.h> 3450a81498SJens Wiklander #include <string.h> 3550a81498SJens Wiklander #include <tee/fs_htree.h> 3650a81498SJens Wiklander #include <tee/tee_cryp_provider.h> 3750a81498SJens Wiklander #include <tee/tee_fs_key_manager.h> 3850a81498SJens Wiklander #include <tee/tee_fs_rpc.h> 3950a81498SJens Wiklander #include <utee_defines.h> 4050a81498SJens Wiklander #include <util.h> 4150a81498SJens Wiklander 4250a81498SJens Wiklander #define TEE_FS_HTREE_CHIP_ID_SIZE 32 4350a81498SJens Wiklander #define TEE_FS_HTREE_HASH_ALG TEE_ALG_SHA256 4450a81498SJens Wiklander #define TEE_FS_HTREE_TSK_SIZE TEE_FS_HTREE_HASH_SIZE 4550a81498SJens Wiklander #define TEE_FS_HTREE_ENC_ALG TEE_ALG_AES_ECB_NOPAD 4650a81498SJens Wiklander #define TEE_FS_HTREE_ENC_SIZE TEE_AES_BLOCK_SIZE 4750a81498SJens Wiklander #define TEE_FS_HTREE_SSK_SIZE TEE_FS_HTREE_HASH_SIZE 4850a81498SJens Wiklander 4950a81498SJens Wiklander #define TEE_FS_HTREE_AUTH_ENC_ALG TEE_ALG_AES_GCM 5050a81498SJens Wiklander #define TEE_FS_HTREE_HMAC_ALG TEE_ALG_HMAC_SHA256 5150a81498SJens Wiklander 5250a81498SJens Wiklander #define BLOCK_NUM_TO_NODE_ID(num) ((num) + 1) 5350a81498SJens Wiklander 5450a81498SJens Wiklander #define NODE_ID_TO_BLOCK_NUM(id) ((id) - 1) 5550a81498SJens Wiklander 5650a81498SJens Wiklander /* 5750a81498SJens Wiklander * The hash tree is implemented as a binary tree with the purpose to ensure 5850a81498SJens Wiklander * integrity of the data in the nodes. The data in the nodes their turn 5950a81498SJens Wiklander * provides both integrity and confidentiality of the data blocks. 6050a81498SJens Wiklander * 6150a81498SJens Wiklander * The hash tree is saved in a file as: 6250a81498SJens Wiklander * +----------------------------+ 6350a81498SJens Wiklander * | htree_image.0 | 6450a81498SJens Wiklander * | htree_image.1 | 6550a81498SJens Wiklander * +----------------------------+ 6650a81498SJens Wiklander * | htree_node_image.1.0 | 6750a81498SJens Wiklander * | htree_node_image.1.1 | 6850a81498SJens Wiklander * +----------------------------+ 6950a81498SJens Wiklander * | htree_node_image.2.0 | 7050a81498SJens Wiklander * | htree_node_image.2.1 | 7150a81498SJens Wiklander * +----------------------------+ 7250a81498SJens Wiklander * | htree_node_image.3.0 | 7350a81498SJens Wiklander * | htree_node_image.3.1 | 7450a81498SJens Wiklander * +----------------------------+ 7550a81498SJens Wiklander * | htree_node_image.4.0 | 7650a81498SJens Wiklander * | htree_node_image.4.1 | 7750a81498SJens Wiklander * +----------------------------+ 7850a81498SJens Wiklander * ... 7950a81498SJens Wiklander * 8050a81498SJens Wiklander * htree_image is the header of the file, there's two instances of it. One 8150a81498SJens Wiklander * which is committed and the other is used when updating the file. Which 8250a81498SJens Wiklander * is committed is indicated by the "counter" field, the one with the 8350a81498SJens Wiklander * largest value is selected. 8450a81498SJens Wiklander * 8550a81498SJens Wiklander * htree_node_image is a node in the hash tree, each node has two instances 8650a81498SJens Wiklander * which is committed is decided by the parent node .flag bit 87e2adafecSJens Wiklander * HTREE_NODE_COMMITTED_CHILD. Which version is the committed version of 8850a81498SJens Wiklander * node 1 is determined by the by the lowest bit of the counter field in 8950a81498SJens Wiklander * the header. 9050a81498SJens Wiklander * 9150a81498SJens Wiklander * Note that nodes start counting at 1 while blocks at 0, this means that 9250a81498SJens Wiklander * block 0 is represented by node 1. 9350a81498SJens Wiklander * 9450a81498SJens Wiklander * Where different elements are stored in the file is managed by the file 9550a81498SJens Wiklander * system. In the case of SQL FS the version of the node/block is ignored 9650a81498SJens Wiklander * as the atomic update is finalized with a call to 9750a81498SJens Wiklander * tee_fs_rpc_end_transaction(). 9850a81498SJens Wiklander */ 9950a81498SJens Wiklander 10050a81498SJens Wiklander #define HTREE_NODE_COMMITTED_BLOCK BIT32(0) 10150a81498SJens Wiklander /* n is 0 or 1 */ 10250a81498SJens Wiklander #define HTREE_NODE_COMMITTED_CHILD(n) BIT32(1 + (n)) 10350a81498SJens Wiklander 10450a81498SJens Wiklander struct htree_node { 10550a81498SJens Wiklander size_t id; 10650a81498SJens Wiklander bool dirty; 107e2adafecSJens Wiklander bool block_updated; 10850a81498SJens Wiklander struct tee_fs_htree_node_image node; 10950a81498SJens Wiklander struct htree_node *parent; 11050a81498SJens Wiklander struct htree_node *child[2]; 11150a81498SJens Wiklander }; 11250a81498SJens Wiklander 11350a81498SJens Wiklander struct tee_fs_htree { 11450a81498SJens Wiklander struct htree_node root; 11550a81498SJens Wiklander struct tee_fs_htree_image head; 11650a81498SJens Wiklander uint8_t fek[TEE_FS_HTREE_FEK_SIZE]; 11750a81498SJens Wiklander struct tee_fs_htree_imeta imeta; 11850a81498SJens Wiklander bool dirty; 119*0c4e1284SJens Wiklander const TEE_UUID *uuid; 12050a81498SJens Wiklander const struct tee_fs_htree_storage *stor; 12150a81498SJens Wiklander void *stor_aux; 12250a81498SJens Wiklander }; 12350a81498SJens Wiklander 12450a81498SJens Wiklander struct traverse_arg; 12550a81498SJens Wiklander typedef TEE_Result (*traverse_cb_t)(struct traverse_arg *targ, 12650a81498SJens Wiklander struct htree_node *node); 12750a81498SJens Wiklander struct traverse_arg { 12850a81498SJens Wiklander struct tee_fs_htree *ht; 12950a81498SJens Wiklander traverse_cb_t cb; 13050a81498SJens Wiklander void *arg; 13150a81498SJens Wiklander }; 13250a81498SJens Wiklander 13350a81498SJens Wiklander static TEE_Result rpc_read(struct tee_fs_htree *ht, enum tee_fs_htree_type type, 13450a81498SJens Wiklander size_t idx, size_t vers, void *data, size_t dlen) 13550a81498SJens Wiklander { 13650a81498SJens Wiklander TEE_Result res; 13750a81498SJens Wiklander struct tee_fs_rpc_operation op; 13850a81498SJens Wiklander size_t bytes; 13950a81498SJens Wiklander void *p; 14050a81498SJens Wiklander 14150a81498SJens Wiklander res = ht->stor->rpc_read_init(ht->stor_aux, &op, type, idx, vers, &p); 14250a81498SJens Wiklander if (res != TEE_SUCCESS) 14350a81498SJens Wiklander return res; 14450a81498SJens Wiklander 14564fa6c0aSJens Wiklander res = ht->stor->rpc_read_final(&op, &bytes); 14650a81498SJens Wiklander if (res != TEE_SUCCESS) 14750a81498SJens Wiklander return res; 14850a81498SJens Wiklander 14950a81498SJens Wiklander if (bytes != dlen) 15050a81498SJens Wiklander return TEE_ERROR_CORRUPT_OBJECT; 15150a81498SJens Wiklander 15250a81498SJens Wiklander memcpy(data, p, dlen); 15350a81498SJens Wiklander return TEE_SUCCESS; 15450a81498SJens Wiklander } 15550a81498SJens Wiklander 15650a81498SJens Wiklander static TEE_Result rpc_read_head(struct tee_fs_htree *ht, size_t vers, 15750a81498SJens Wiklander struct tee_fs_htree_image *head) 15850a81498SJens Wiklander { 15950a81498SJens Wiklander return rpc_read(ht, TEE_FS_HTREE_TYPE_HEAD, 0, vers, 16050a81498SJens Wiklander head, sizeof(*head)); 16150a81498SJens Wiklander } 16250a81498SJens Wiklander 16350a81498SJens Wiklander static TEE_Result rpc_read_node(struct tee_fs_htree *ht, size_t node_id, 16450a81498SJens Wiklander size_t vers, 16550a81498SJens Wiklander struct tee_fs_htree_node_image *node) 16650a81498SJens Wiklander { 16750a81498SJens Wiklander return rpc_read(ht, TEE_FS_HTREE_TYPE_NODE, node_id - 1, vers, 16850a81498SJens Wiklander node, sizeof(*node)); 16950a81498SJens Wiklander } 17050a81498SJens Wiklander 17150a81498SJens Wiklander static TEE_Result rpc_write(struct tee_fs_htree *ht, 17250a81498SJens Wiklander enum tee_fs_htree_type type, size_t idx, 17350a81498SJens Wiklander size_t vers, const void *data, size_t dlen) 17450a81498SJens Wiklander { 17550a81498SJens Wiklander TEE_Result res; 17650a81498SJens Wiklander struct tee_fs_rpc_operation op; 17750a81498SJens Wiklander void *p; 17850a81498SJens Wiklander 17950a81498SJens Wiklander res = ht->stor->rpc_write_init(ht->stor_aux, &op, type, idx, vers, &p); 18050a81498SJens Wiklander if (res != TEE_SUCCESS) 18150a81498SJens Wiklander return res; 18250a81498SJens Wiklander 18350a81498SJens Wiklander memcpy(p, data, dlen); 18464fa6c0aSJens Wiklander return ht->stor->rpc_write_final(&op); 18550a81498SJens Wiklander } 18650a81498SJens Wiklander 18750a81498SJens Wiklander static TEE_Result rpc_write_head(struct tee_fs_htree *ht, size_t vers, 18850a81498SJens Wiklander const struct tee_fs_htree_image *head) 18950a81498SJens Wiklander { 19050a81498SJens Wiklander return rpc_write(ht, TEE_FS_HTREE_TYPE_HEAD, 0, vers, 19150a81498SJens Wiklander head, sizeof(*head)); 19250a81498SJens Wiklander } 19350a81498SJens Wiklander 19450a81498SJens Wiklander static TEE_Result rpc_write_node(struct tee_fs_htree *ht, size_t node_id, 19550a81498SJens Wiklander size_t vers, 19650a81498SJens Wiklander const struct tee_fs_htree_node_image *node) 19750a81498SJens Wiklander { 19850a81498SJens Wiklander return rpc_write(ht, TEE_FS_HTREE_TYPE_NODE, node_id - 1, vers, 19950a81498SJens Wiklander node, sizeof(*node)); 20050a81498SJens Wiklander } 20150a81498SJens Wiklander 20250a81498SJens Wiklander static TEE_Result traverse_post_order(struct traverse_arg *targ, 20350a81498SJens Wiklander struct htree_node *node) 20450a81498SJens Wiklander { 20550a81498SJens Wiklander TEE_Result res; 20650a81498SJens Wiklander 20750a81498SJens Wiklander /* 20850a81498SJens Wiklander * This function is recursing but not very deep, only with Log(N) 20950a81498SJens Wiklander * maximum depth. 21050a81498SJens Wiklander */ 21150a81498SJens Wiklander 21250a81498SJens Wiklander if (!node) 21350a81498SJens Wiklander return TEE_SUCCESS; 21450a81498SJens Wiklander 21550a81498SJens Wiklander res = traverse_post_order(targ, node->child[0]); 21650a81498SJens Wiklander if (res != TEE_SUCCESS) 21750a81498SJens Wiklander return res; 21850a81498SJens Wiklander 21950a81498SJens Wiklander res = traverse_post_order(targ, node->child[1]); 22050a81498SJens Wiklander if (res != TEE_SUCCESS) 22150a81498SJens Wiklander return res; 22250a81498SJens Wiklander 22350a81498SJens Wiklander return targ->cb(targ, node); 22450a81498SJens Wiklander } 22550a81498SJens Wiklander 22650a81498SJens Wiklander static TEE_Result htree_traverse_post_order(struct tee_fs_htree *ht, 22750a81498SJens Wiklander traverse_cb_t cb, void *arg) 22850a81498SJens Wiklander { 22950a81498SJens Wiklander struct traverse_arg targ = { ht, cb, arg }; 23050a81498SJens Wiklander 23150a81498SJens Wiklander return traverse_post_order(&targ, &ht->root); 23250a81498SJens Wiklander } 23350a81498SJens Wiklander 23450a81498SJens Wiklander static size_t node_id_to_level(size_t node_id) 23550a81498SJens Wiklander { 23650a81498SJens Wiklander assert(node_id && node_id < UINT_MAX); 23750a81498SJens Wiklander /* Calculate level of the node, root node (1) has level 1 */ 23850a81498SJens Wiklander return sizeof(unsigned int) * 8 - __builtin_clz(node_id); 23950a81498SJens Wiklander } 24050a81498SJens Wiklander 24150a81498SJens Wiklander static struct htree_node *find_closest_node(struct tee_fs_htree *ht, 24250a81498SJens Wiklander size_t node_id) 24350a81498SJens Wiklander { 24450a81498SJens Wiklander struct htree_node *node = &ht->root; 24550a81498SJens Wiklander size_t level = node_id_to_level(node_id); 24650a81498SJens Wiklander size_t n; 24750a81498SJens Wiklander 24850a81498SJens Wiklander /* n = 1 because root node is level 1 */ 24950a81498SJens Wiklander for (n = 1; n < level; n++) { 25050a81498SJens Wiklander struct htree_node *child; 25150a81498SJens Wiklander size_t bit_idx; 25250a81498SJens Wiklander 25350a81498SJens Wiklander /* 25450a81498SJens Wiklander * The difference between levels of the current node and 25550a81498SJens Wiklander * the node we're looking for tells which bit decides 25650a81498SJens Wiklander * direction in the tree. 25750a81498SJens Wiklander * 25850a81498SJens Wiklander * As the first bit has index 0 we'll subtract 1 25950a81498SJens Wiklander */ 26050a81498SJens Wiklander bit_idx = level - n - 1; 26150a81498SJens Wiklander child = node->child[((node_id >> bit_idx) & 1)]; 26250a81498SJens Wiklander if (!child) 26350a81498SJens Wiklander return node; 26450a81498SJens Wiklander node = child; 26550a81498SJens Wiklander } 26650a81498SJens Wiklander 26750a81498SJens Wiklander return node; 26850a81498SJens Wiklander } 26950a81498SJens Wiklander 27050a81498SJens Wiklander static struct htree_node *find_node(struct tee_fs_htree *ht, size_t node_id) 27150a81498SJens Wiklander { 27250a81498SJens Wiklander struct htree_node *node = find_closest_node(ht, node_id); 27350a81498SJens Wiklander 27450a81498SJens Wiklander if (node && node->id == node_id) 27550a81498SJens Wiklander return node; 27650a81498SJens Wiklander return NULL; 27750a81498SJens Wiklander } 27850a81498SJens Wiklander 27950a81498SJens Wiklander static TEE_Result get_node(struct tee_fs_htree *ht, bool create, 28050a81498SJens Wiklander size_t node_id, struct htree_node **node_ret) 28150a81498SJens Wiklander { 28250a81498SJens Wiklander struct htree_node *node; 28350a81498SJens Wiklander struct htree_node *nc; 28450a81498SJens Wiklander size_t n; 28550a81498SJens Wiklander 28650a81498SJens Wiklander node = find_closest_node(ht, node_id); 28750a81498SJens Wiklander if (!node) 28850a81498SJens Wiklander return TEE_ERROR_GENERIC; 28950a81498SJens Wiklander if (node->id == node_id) 29050a81498SJens Wiklander goto ret_node; 29150a81498SJens Wiklander 29250a81498SJens Wiklander /* 29350a81498SJens Wiklander * Trying to read beyond end of file should be caught earlier than 29450a81498SJens Wiklander * here. 29550a81498SJens Wiklander */ 29650a81498SJens Wiklander if (!create) 29750a81498SJens Wiklander return TEE_ERROR_GENERIC; 29850a81498SJens Wiklander 29950a81498SJens Wiklander /* 30050a81498SJens Wiklander * Add missing nodes, some nodes may already be there. When we've 30150a81498SJens Wiklander * processed the range all nodes up to node_id will be in the tree. 30250a81498SJens Wiklander */ 30350a81498SJens Wiklander for (n = node->id + 1; n <= node_id; n++) { 30450a81498SJens Wiklander node = find_closest_node(ht, n); 30550a81498SJens Wiklander if (node->id == n) 30650a81498SJens Wiklander continue; 30750a81498SJens Wiklander /* Node id n should be a child of node */ 30850a81498SJens Wiklander assert((n >> 1) == node->id); 30950a81498SJens Wiklander assert(!node->child[n & 1]); 31050a81498SJens Wiklander 31150a81498SJens Wiklander nc = calloc(1, sizeof(*nc)); 31250a81498SJens Wiklander if (!nc) 31350a81498SJens Wiklander return TEE_ERROR_OUT_OF_MEMORY; 31450a81498SJens Wiklander nc->id = n; 31550a81498SJens Wiklander nc->parent = node; 31650a81498SJens Wiklander node->child[n & 1] = nc; 31750a81498SJens Wiklander node = nc; 31850a81498SJens Wiklander } 31950a81498SJens Wiklander 32050a81498SJens Wiklander if (node->id > ht->imeta.max_node_id) 32150a81498SJens Wiklander ht->imeta.max_node_id = node->id; 32250a81498SJens Wiklander 32350a81498SJens Wiklander ret_node: 32450a81498SJens Wiklander *node_ret = node; 32550a81498SJens Wiklander return TEE_SUCCESS; 32650a81498SJens Wiklander } 32750a81498SJens Wiklander 32850a81498SJens Wiklander static int get_idx_from_counter(uint32_t counter0, uint32_t counter1) 32950a81498SJens Wiklander { 33050a81498SJens Wiklander if (!(counter0 & 1)) { 33150a81498SJens Wiklander if (!(counter1 & 1)) 33250a81498SJens Wiklander return 0; 33350a81498SJens Wiklander if (counter0 > counter1) 33450a81498SJens Wiklander return 0; 33550a81498SJens Wiklander else 33650a81498SJens Wiklander return 1; 33750a81498SJens Wiklander } 33850a81498SJens Wiklander 33950a81498SJens Wiklander if (counter1 & 1) 34050a81498SJens Wiklander return 1; 34150a81498SJens Wiklander else 34250a81498SJens Wiklander return -1; 34350a81498SJens Wiklander } 34450a81498SJens Wiklander 345f28e5060SJens Wiklander static TEE_Result init_head_from_data(struct tee_fs_htree *ht, 346f28e5060SJens Wiklander const uint8_t *hash) 34750a81498SJens Wiklander { 34850a81498SJens Wiklander TEE_Result res; 34950a81498SJens Wiklander int idx; 35050a81498SJens Wiklander 351f28e5060SJens Wiklander if (hash) { 352f28e5060SJens Wiklander for (idx = 0;; idx++) { 353f28e5060SJens Wiklander res = rpc_read_node(ht, 1, idx, &ht->root.node); 354f28e5060SJens Wiklander if (res != TEE_SUCCESS) 355f28e5060SJens Wiklander return res; 356f28e5060SJens Wiklander 357f28e5060SJens Wiklander if (!memcmp(ht->root.node.hash, hash, 358f28e5060SJens Wiklander sizeof(ht->root.node.hash))) { 359f28e5060SJens Wiklander res = rpc_read_head(ht, idx, &ht->head); 360f28e5060SJens Wiklander if (res != TEE_SUCCESS) 361f28e5060SJens Wiklander return res; 362f28e5060SJens Wiklander break; 363f28e5060SJens Wiklander } 364f28e5060SJens Wiklander 365f28e5060SJens Wiklander if (idx) 366f28e5060SJens Wiklander return TEE_ERROR_SECURITY; 367f28e5060SJens Wiklander } 368f28e5060SJens Wiklander } else { 369f28e5060SJens Wiklander struct tee_fs_htree_image head[2]; 370f28e5060SJens Wiklander 37150a81498SJens Wiklander for (idx = 0; idx < 2; idx++) { 37250a81498SJens Wiklander res = rpc_read_head(ht, idx, head + idx); 37350a81498SJens Wiklander if (res != TEE_SUCCESS) 37450a81498SJens Wiklander return res; 37550a81498SJens Wiklander } 37650a81498SJens Wiklander 37750a81498SJens Wiklander idx = get_idx_from_counter(head[0].counter, head[1].counter); 37850a81498SJens Wiklander if (idx < 0) 37950a81498SJens Wiklander return TEE_ERROR_SECURITY; 38050a81498SJens Wiklander 38150a81498SJens Wiklander res = rpc_read_node(ht, 1, idx, &ht->root.node); 38250a81498SJens Wiklander if (res != TEE_SUCCESS) 38350a81498SJens Wiklander return res; 38450a81498SJens Wiklander 38550a81498SJens Wiklander ht->head = head[idx]; 386f28e5060SJens Wiklander } 387f28e5060SJens Wiklander 38850a81498SJens Wiklander ht->root.id = 1; 38950a81498SJens Wiklander 39050a81498SJens Wiklander return TEE_SUCCESS; 39150a81498SJens Wiklander } 39250a81498SJens Wiklander 39350a81498SJens Wiklander static TEE_Result init_tree_from_data(struct tee_fs_htree *ht) 39450a81498SJens Wiklander { 39550a81498SJens Wiklander TEE_Result res; 39650a81498SJens Wiklander struct tee_fs_htree_node_image node_image; 39750a81498SJens Wiklander struct htree_node *node; 39850a81498SJens Wiklander struct htree_node *nc; 39950a81498SJens Wiklander size_t committed_version; 40050a81498SJens Wiklander size_t node_id = 2; 40150a81498SJens Wiklander 40250a81498SJens Wiklander while (node_id <= ht->imeta.max_node_id) { 40350a81498SJens Wiklander node = find_node(ht, node_id >> 1); 40450a81498SJens Wiklander if (!node) 40550a81498SJens Wiklander return TEE_ERROR_GENERIC; 40650a81498SJens Wiklander committed_version = !!(node->node.flags & 40750a81498SJens Wiklander HTREE_NODE_COMMITTED_CHILD(node_id & 1)); 40850a81498SJens Wiklander 40950a81498SJens Wiklander res = rpc_read_node(ht, node_id, committed_version, 41050a81498SJens Wiklander &node_image); 41150a81498SJens Wiklander if (res != TEE_SUCCESS) 41250a81498SJens Wiklander return res; 41350a81498SJens Wiklander 41450a81498SJens Wiklander res = get_node(ht, true, node_id, &nc); 41550a81498SJens Wiklander if (res != TEE_SUCCESS) 41650a81498SJens Wiklander return res; 41750a81498SJens Wiklander nc->node = node_image; 41850a81498SJens Wiklander node_id++; 41950a81498SJens Wiklander } 42050a81498SJens Wiklander 42150a81498SJens Wiklander return TEE_SUCCESS; 42250a81498SJens Wiklander } 42350a81498SJens Wiklander 42450a81498SJens Wiklander static TEE_Result calc_node_hash(struct htree_node *node, void *ctx, 42550a81498SJens Wiklander uint8_t *digest) 42650a81498SJens Wiklander { 42750a81498SJens Wiklander TEE_Result res; 42850a81498SJens Wiklander uint32_t alg = TEE_FS_HTREE_HASH_ALG; 42950a81498SJens Wiklander uint8_t *ndata = (uint8_t *)&node->node + sizeof(node->node.hash); 43050a81498SJens Wiklander size_t nsize = sizeof(node->node) - sizeof(node->node.hash); 43150a81498SJens Wiklander 43250a81498SJens Wiklander res = crypto_ops.hash.init(ctx, alg); 43350a81498SJens Wiklander if (res != TEE_SUCCESS) 43450a81498SJens Wiklander return res; 43550a81498SJens Wiklander 43650a81498SJens Wiklander res = crypto_ops.hash.update(ctx, alg, ndata, nsize); 43750a81498SJens Wiklander if (res != TEE_SUCCESS) 43850a81498SJens Wiklander return res; 43950a81498SJens Wiklander 44050a81498SJens Wiklander if (node->child[0]) { 44150a81498SJens Wiklander res = crypto_ops.hash.update(ctx, alg, 44250a81498SJens Wiklander node->child[0]->node.hash, 44350a81498SJens Wiklander sizeof(node->child[0]->node.hash)); 44450a81498SJens Wiklander if (res != TEE_SUCCESS) 44550a81498SJens Wiklander return res; 44650a81498SJens Wiklander } 44750a81498SJens Wiklander 44850a81498SJens Wiklander if (node->child[1]) { 44950a81498SJens Wiklander res = crypto_ops.hash.update(ctx, alg, 45050a81498SJens Wiklander node->child[1]->node.hash, 45150a81498SJens Wiklander sizeof(node->child[1]->node.hash)); 45250a81498SJens Wiklander if (res != TEE_SUCCESS) 45350a81498SJens Wiklander return res; 45450a81498SJens Wiklander } 45550a81498SJens Wiklander 45650a81498SJens Wiklander return crypto_ops.hash.final(ctx, alg, digest, TEE_FS_HTREE_HASH_SIZE); 45750a81498SJens Wiklander } 45850a81498SJens Wiklander 45950a81498SJens Wiklander static TEE_Result authenc_init(void **ctx_ret, TEE_OperationMode mode, 46050a81498SJens Wiklander struct tee_fs_htree *ht, 46150a81498SJens Wiklander struct tee_fs_htree_node_image *ni, 46250a81498SJens Wiklander size_t payload_len) 46350a81498SJens Wiklander { 46450a81498SJens Wiklander TEE_Result res = TEE_SUCCESS; 46550a81498SJens Wiklander const uint32_t alg = TEE_FS_HTREE_AUTH_ENC_ALG; 46650a81498SJens Wiklander uint8_t *ctx; 46750a81498SJens Wiklander size_t ctx_size; 46850a81498SJens Wiklander size_t aad_len = TEE_FS_HTREE_FEK_SIZE + TEE_FS_HTREE_IV_SIZE; 46950a81498SJens Wiklander uint8_t *iv; 47050a81498SJens Wiklander 47150a81498SJens Wiklander if (ni) { 47250a81498SJens Wiklander iv = ni->iv; 47350a81498SJens Wiklander } else { 47450a81498SJens Wiklander iv = ht->head.iv; 47550a81498SJens Wiklander aad_len += TEE_FS_HTREE_HASH_SIZE + sizeof(ht->head.counter); 47650a81498SJens Wiklander } 47750a81498SJens Wiklander 47850a81498SJens Wiklander if (mode == TEE_MODE_ENCRYPT) { 47950a81498SJens Wiklander res = crypto_ops.prng.read(iv, TEE_FS_HTREE_IV_SIZE); 48050a81498SJens Wiklander if (res != TEE_SUCCESS) 48150a81498SJens Wiklander return res; 48250a81498SJens Wiklander } 48350a81498SJens Wiklander 48450a81498SJens Wiklander res = crypto_ops.authenc.get_ctx_size(alg, &ctx_size); 48550a81498SJens Wiklander if (res != TEE_SUCCESS) 48650a81498SJens Wiklander return res; 48750a81498SJens Wiklander 48850a81498SJens Wiklander ctx = malloc(ctx_size); 48950a81498SJens Wiklander if (!ctx) { 49050a81498SJens Wiklander EMSG("request memory size %zu failed", ctx_size); 49150a81498SJens Wiklander return TEE_ERROR_OUT_OF_MEMORY; 49250a81498SJens Wiklander } 49350a81498SJens Wiklander 49450a81498SJens Wiklander res = crypto_ops.authenc.init(ctx, alg, mode, 49550a81498SJens Wiklander ht->fek, TEE_FS_HTREE_FEK_SIZE, 49650a81498SJens Wiklander iv, TEE_FS_HTREE_IV_SIZE, 49750a81498SJens Wiklander TEE_FS_HTREE_TAG_SIZE, aad_len, 49850a81498SJens Wiklander payload_len); 49950a81498SJens Wiklander if (res != TEE_SUCCESS) 50050a81498SJens Wiklander goto exit; 50150a81498SJens Wiklander 50250a81498SJens Wiklander if (!ni) { 50350a81498SJens Wiklander res = crypto_ops.authenc.update_aad(ctx, alg, mode, 50450a81498SJens Wiklander ht->root.node.hash, 50550a81498SJens Wiklander TEE_FS_HTREE_FEK_SIZE); 50650a81498SJens Wiklander if (res != TEE_SUCCESS) 50750a81498SJens Wiklander goto exit; 50850a81498SJens Wiklander 50950a81498SJens Wiklander res = crypto_ops.authenc.update_aad(ctx, alg, mode, 51050a81498SJens Wiklander (void *)&ht->head.counter, 51150a81498SJens Wiklander sizeof(ht->head.counter)); 51250a81498SJens Wiklander if (res != TEE_SUCCESS) 51350a81498SJens Wiklander goto exit; 51450a81498SJens Wiklander } 51550a81498SJens Wiklander 51650a81498SJens Wiklander res = crypto_ops.authenc.update_aad(ctx, alg, mode, ht->head.enc_fek, 51750a81498SJens Wiklander TEE_FS_HTREE_FEK_SIZE); 51850a81498SJens Wiklander if (res != TEE_SUCCESS) 51950a81498SJens Wiklander goto exit; 52050a81498SJens Wiklander 52150a81498SJens Wiklander res = crypto_ops.authenc.update_aad(ctx, alg, mode, iv, 52250a81498SJens Wiklander TEE_FS_HTREE_IV_SIZE); 52350a81498SJens Wiklander 52450a81498SJens Wiklander exit: 52550a81498SJens Wiklander if (res == TEE_SUCCESS) 52650a81498SJens Wiklander *ctx_ret = ctx; 52750a81498SJens Wiklander else 52850a81498SJens Wiklander free(ctx); 52950a81498SJens Wiklander 53050a81498SJens Wiklander return res; 53150a81498SJens Wiklander } 53250a81498SJens Wiklander 53350a81498SJens Wiklander static TEE_Result authenc_decrypt_final(void *ctx, const uint8_t *tag, 53450a81498SJens Wiklander const void *crypt, size_t len, 53550a81498SJens Wiklander void *plain) 53650a81498SJens Wiklander { 53750a81498SJens Wiklander TEE_Result res; 53850a81498SJens Wiklander size_t out_size = len; 53950a81498SJens Wiklander 54050a81498SJens Wiklander res = crypto_ops.authenc.dec_final(ctx, TEE_FS_HTREE_AUTH_ENC_ALG, 54150a81498SJens Wiklander crypt, len, plain, &out_size, 54250a81498SJens Wiklander tag, TEE_FS_HTREE_TAG_SIZE); 54350a81498SJens Wiklander crypto_ops.authenc.final(ctx, TEE_FS_HTREE_AUTH_ENC_ALG); 54450a81498SJens Wiklander free(ctx); 54550a81498SJens Wiklander 54650a81498SJens Wiklander if (res == TEE_SUCCESS && out_size != len) 54750a81498SJens Wiklander return TEE_ERROR_GENERIC; 54850a81498SJens Wiklander if (res == TEE_ERROR_MAC_INVALID) 54950a81498SJens Wiklander return TEE_ERROR_CORRUPT_OBJECT; 55050a81498SJens Wiklander 55150a81498SJens Wiklander return res; 55250a81498SJens Wiklander } 55350a81498SJens Wiklander 55450a81498SJens Wiklander static TEE_Result authenc_encrypt_final(void *ctx, uint8_t *tag, 55550a81498SJens Wiklander const void *plain, size_t len, 55650a81498SJens Wiklander void *crypt) 55750a81498SJens Wiklander { 55850a81498SJens Wiklander TEE_Result res; 55950a81498SJens Wiklander size_t out_size = len; 56050a81498SJens Wiklander size_t out_tag_size = TEE_FS_HTREE_TAG_SIZE; 56150a81498SJens Wiklander 56250a81498SJens Wiklander res = crypto_ops.authenc.enc_final(ctx, TEE_FS_HTREE_AUTH_ENC_ALG, 56350a81498SJens Wiklander plain, len, crypt, &out_size, 56450a81498SJens Wiklander tag, &out_tag_size); 56550a81498SJens Wiklander crypto_ops.authenc.final(ctx, TEE_FS_HTREE_AUTH_ENC_ALG); 56650a81498SJens Wiklander free(ctx); 56750a81498SJens Wiklander 56850a81498SJens Wiklander if (res == TEE_SUCCESS && 56950a81498SJens Wiklander (out_size != len || out_tag_size != TEE_FS_HTREE_TAG_SIZE)) 57050a81498SJens Wiklander return TEE_ERROR_GENERIC; 57150a81498SJens Wiklander 57250a81498SJens Wiklander return res; 57350a81498SJens Wiklander } 57450a81498SJens Wiklander 57550a81498SJens Wiklander static TEE_Result verify_root(struct tee_fs_htree *ht) 57650a81498SJens Wiklander { 57750a81498SJens Wiklander TEE_Result res; 57850a81498SJens Wiklander void *ctx; 57950a81498SJens Wiklander 580*0c4e1284SJens Wiklander res = tee_fs_fek_crypt(ht->uuid, TEE_MODE_DECRYPT, ht->head.enc_fek, 58150a81498SJens Wiklander sizeof(ht->fek), ht->fek); 58250a81498SJens Wiklander if (res != TEE_SUCCESS) 58350a81498SJens Wiklander return res; 58450a81498SJens Wiklander 58550a81498SJens Wiklander res = authenc_init(&ctx, TEE_MODE_DECRYPT, ht, NULL, sizeof(ht->imeta)); 58650a81498SJens Wiklander if (res != TEE_SUCCESS) 58750a81498SJens Wiklander return res; 58850a81498SJens Wiklander 58950a81498SJens Wiklander return authenc_decrypt_final(ctx, ht->head.tag, ht->head.imeta, 59050a81498SJens Wiklander sizeof(ht->imeta), &ht->imeta); 59150a81498SJens Wiklander } 59250a81498SJens Wiklander 59350a81498SJens Wiklander static TEE_Result verify_node(struct traverse_arg *targ, 59450a81498SJens Wiklander struct htree_node *node) 59550a81498SJens Wiklander { 59650a81498SJens Wiklander void *ctx = targ->arg; 59750a81498SJens Wiklander TEE_Result res; 59850a81498SJens Wiklander uint8_t digest[TEE_FS_HTREE_HASH_SIZE]; 59950a81498SJens Wiklander 60050a81498SJens Wiklander res = calc_node_hash(node, ctx, digest); 60150a81498SJens Wiklander if (res == TEE_SUCCESS && 60250a81498SJens Wiklander buf_compare_ct(digest, node->node.hash, sizeof(digest))) 60350a81498SJens Wiklander return TEE_ERROR_CORRUPT_OBJECT; 60450a81498SJens Wiklander 60550a81498SJens Wiklander return res; 60650a81498SJens Wiklander } 60750a81498SJens Wiklander 60850a81498SJens Wiklander static TEE_Result verify_tree(struct tee_fs_htree *ht) 60950a81498SJens Wiklander { 61050a81498SJens Wiklander TEE_Result res; 61150a81498SJens Wiklander size_t size; 61250a81498SJens Wiklander void *ctx; 61350a81498SJens Wiklander 61450a81498SJens Wiklander if (!crypto_ops.hash.get_ctx_size || !crypto_ops.hash.init || 61550a81498SJens Wiklander !crypto_ops.hash.update || !crypto_ops.hash.final) 61650a81498SJens Wiklander return TEE_ERROR_NOT_SUPPORTED; 61750a81498SJens Wiklander 61850a81498SJens Wiklander res = crypto_ops.hash.get_ctx_size(TEE_FS_HTREE_HASH_ALG, &size); 61950a81498SJens Wiklander if (res != TEE_SUCCESS) 62050a81498SJens Wiklander return res; 62150a81498SJens Wiklander 62250a81498SJens Wiklander ctx = malloc(size); 62350a81498SJens Wiklander if (!ctx) 62450a81498SJens Wiklander return TEE_ERROR_OUT_OF_MEMORY; 62550a81498SJens Wiklander 62650a81498SJens Wiklander res = htree_traverse_post_order(ht, verify_node, ctx); 62750a81498SJens Wiklander free(ctx); 62850a81498SJens Wiklander 62950a81498SJens Wiklander return res; 63050a81498SJens Wiklander } 63150a81498SJens Wiklander 63250a81498SJens Wiklander static TEE_Result init_root_node(struct tee_fs_htree *ht) 63350a81498SJens Wiklander { 63450a81498SJens Wiklander TEE_Result res; 63550a81498SJens Wiklander size_t size; 63650a81498SJens Wiklander void *ctx; 63750a81498SJens Wiklander 63850a81498SJens Wiklander res = crypto_ops.hash.get_ctx_size(TEE_FS_HTREE_HASH_ALG, &size); 63950a81498SJens Wiklander if (res != TEE_SUCCESS) 64050a81498SJens Wiklander return res; 64150a81498SJens Wiklander ctx = malloc(size); 64250a81498SJens Wiklander if (!ctx) 64350a81498SJens Wiklander return TEE_ERROR_OUT_OF_MEMORY; 64450a81498SJens Wiklander 64550a81498SJens Wiklander ht->root.id = 1; 64650a81498SJens Wiklander 64750a81498SJens Wiklander res = calc_node_hash(&ht->root, ctx, ht->root.node.hash); 64850a81498SJens Wiklander free(ctx); 64950a81498SJens Wiklander 65050a81498SJens Wiklander return res; 65150a81498SJens Wiklander } 65250a81498SJens Wiklander 653*0c4e1284SJens Wiklander TEE_Result tee_fs_htree_open(bool create, uint8_t *hash, const TEE_UUID *uuid, 65450a81498SJens Wiklander const struct tee_fs_htree_storage *stor, 65550a81498SJens Wiklander void *stor_aux, struct tee_fs_htree **ht_ret) 65650a81498SJens Wiklander { 65750a81498SJens Wiklander TEE_Result res; 65850a81498SJens Wiklander struct tee_fs_htree *ht = calloc(1, sizeof(*ht)); 65950a81498SJens Wiklander 66050a81498SJens Wiklander if (!ht) 66150a81498SJens Wiklander return TEE_ERROR_OUT_OF_MEMORY; 66250a81498SJens Wiklander 663*0c4e1284SJens Wiklander ht->uuid = uuid; 66450a81498SJens Wiklander ht->stor = stor; 66550a81498SJens Wiklander ht->stor_aux = stor_aux; 66650a81498SJens Wiklander 66750a81498SJens Wiklander if (create) { 668e2adafecSJens Wiklander const struct tee_fs_htree_image dummy_head = { .counter = 0 }; 669e2adafecSJens Wiklander 67050a81498SJens Wiklander res = crypto_ops.prng.read(ht->fek, sizeof(ht->fek)); 67150a81498SJens Wiklander if (res != TEE_SUCCESS) 67250a81498SJens Wiklander goto out; 67350a81498SJens Wiklander 674*0c4e1284SJens Wiklander res = tee_fs_fek_crypt(ht->uuid, TEE_MODE_ENCRYPT, ht->fek, 67550a81498SJens Wiklander sizeof(ht->fek), ht->head.enc_fek); 67650a81498SJens Wiklander if (res != TEE_SUCCESS) 67750a81498SJens Wiklander goto out; 67850a81498SJens Wiklander 67950a81498SJens Wiklander res = init_root_node(ht); 68050a81498SJens Wiklander if (res != TEE_SUCCESS) 68150a81498SJens Wiklander goto out; 68250a81498SJens Wiklander 68350a81498SJens Wiklander ht->dirty = true; 684f28e5060SJens Wiklander res = tee_fs_htree_sync_to_storage(&ht, hash); 685e2adafecSJens Wiklander if (res != TEE_SUCCESS) 686e2adafecSJens Wiklander goto out; 687e2adafecSJens Wiklander res = rpc_write_head(ht, 0, &dummy_head); 68850a81498SJens Wiklander } else { 689f28e5060SJens Wiklander res = init_head_from_data(ht, hash); 69050a81498SJens Wiklander if (res != TEE_SUCCESS) 69150a81498SJens Wiklander goto out; 69250a81498SJens Wiklander 69350a81498SJens Wiklander res = verify_root(ht); 69450a81498SJens Wiklander if (res != TEE_SUCCESS) 69550a81498SJens Wiklander goto out; 69650a81498SJens Wiklander 69750a81498SJens Wiklander res = init_tree_from_data(ht); 69850a81498SJens Wiklander if (res != TEE_SUCCESS) 69950a81498SJens Wiklander goto out; 70050a81498SJens Wiklander 70150a81498SJens Wiklander res = verify_tree(ht); 70250a81498SJens Wiklander } 70350a81498SJens Wiklander out: 70450a81498SJens Wiklander if (res == TEE_SUCCESS) 70550a81498SJens Wiklander *ht_ret = ht; 70650a81498SJens Wiklander else 70750a81498SJens Wiklander tee_fs_htree_close(&ht); 70850a81498SJens Wiklander return res; 70950a81498SJens Wiklander } 71050a81498SJens Wiklander 71150a81498SJens Wiklander struct tee_fs_htree_meta *tee_fs_htree_get_meta(struct tee_fs_htree *ht) 71250a81498SJens Wiklander { 71350a81498SJens Wiklander return &ht->imeta.meta; 71450a81498SJens Wiklander } 71550a81498SJens Wiklander 71650a81498SJens Wiklander static TEE_Result free_node(struct traverse_arg *targ __unused, 71750a81498SJens Wiklander struct htree_node *node) 71850a81498SJens Wiklander { 71950a81498SJens Wiklander if (node->parent) 72050a81498SJens Wiklander free(node); 72150a81498SJens Wiklander return TEE_SUCCESS; 72250a81498SJens Wiklander } 72350a81498SJens Wiklander 72450a81498SJens Wiklander void tee_fs_htree_close(struct tee_fs_htree **ht) 72550a81498SJens Wiklander { 72650a81498SJens Wiklander if (!*ht) 72750a81498SJens Wiklander return; 72850a81498SJens Wiklander htree_traverse_post_order(*ht, free_node, NULL); 72950a81498SJens Wiklander free(*ht); 73050a81498SJens Wiklander *ht = NULL; 73150a81498SJens Wiklander } 73250a81498SJens Wiklander 73350a81498SJens Wiklander static TEE_Result htree_sync_node_to_storage(struct traverse_arg *targ, 73450a81498SJens Wiklander struct htree_node *node) 73550a81498SJens Wiklander { 73650a81498SJens Wiklander TEE_Result res; 73750a81498SJens Wiklander uint8_t vers; 73850a81498SJens Wiklander 739e2adafecSJens Wiklander /* 740e2adafecSJens Wiklander * The node can be dirty while the block isn't updated due to 741e2adafecSJens Wiklander * updated children, but if block is updated the node has to be 742e2adafecSJens Wiklander * dirty. 743e2adafecSJens Wiklander */ 744e2adafecSJens Wiklander assert(node->dirty >= node->block_updated); 745e2adafecSJens Wiklander 74650a81498SJens Wiklander if (!node->dirty) 74750a81498SJens Wiklander return TEE_SUCCESS; 74850a81498SJens Wiklander 74950a81498SJens Wiklander if (node->parent) { 75050a81498SJens Wiklander uint32_t f = HTREE_NODE_COMMITTED_CHILD(node->id & 1); 75150a81498SJens Wiklander 75250a81498SJens Wiklander node->parent->dirty = true; 75350a81498SJens Wiklander node->parent->node.flags ^= f; 75450a81498SJens Wiklander vers = !!(node->parent->node.flags & f); 75550a81498SJens Wiklander } else { 75650a81498SJens Wiklander /* 75750a81498SJens Wiklander * Counter isn't updated yet, it's increased just before 75850a81498SJens Wiklander * writing the header. 75950a81498SJens Wiklander */ 76050a81498SJens Wiklander vers = !(targ->ht->head.counter & 1); 76150a81498SJens Wiklander } 76250a81498SJens Wiklander 76350a81498SJens Wiklander res = calc_node_hash(node, targ->arg, node->node.hash); 76450a81498SJens Wiklander if (res != TEE_SUCCESS) 76550a81498SJens Wiklander return res; 76650a81498SJens Wiklander 76750a81498SJens Wiklander node->dirty = false; 768e2adafecSJens Wiklander node->block_updated = false; 76950a81498SJens Wiklander 77050a81498SJens Wiklander return rpc_write_node(targ->ht, node->id, vers, &node->node); 77150a81498SJens Wiklander } 77250a81498SJens Wiklander 77350a81498SJens Wiklander static TEE_Result update_root(struct tee_fs_htree *ht) 77450a81498SJens Wiklander { 77550a81498SJens Wiklander TEE_Result res; 77650a81498SJens Wiklander void *ctx; 77750a81498SJens Wiklander 77850a81498SJens Wiklander ht->head.counter++; 77950a81498SJens Wiklander 78050a81498SJens Wiklander res = authenc_init(&ctx, TEE_MODE_ENCRYPT, ht, NULL, sizeof(ht->imeta)); 78150a81498SJens Wiklander if (res != TEE_SUCCESS) 78250a81498SJens Wiklander return res; 78350a81498SJens Wiklander 78450a81498SJens Wiklander return authenc_encrypt_final(ctx, ht->head.tag, &ht->imeta, 78550a81498SJens Wiklander sizeof(ht->imeta), &ht->head.imeta); 78650a81498SJens Wiklander } 78750a81498SJens Wiklander 788f28e5060SJens Wiklander TEE_Result tee_fs_htree_sync_to_storage(struct tee_fs_htree **ht_arg, 789f28e5060SJens Wiklander uint8_t *hash) 79050a81498SJens Wiklander { 79150a81498SJens Wiklander TEE_Result res; 79250a81498SJens Wiklander struct tee_fs_htree *ht = *ht_arg; 79350a81498SJens Wiklander size_t size; 79450a81498SJens Wiklander void *ctx; 79550a81498SJens Wiklander 79650a81498SJens Wiklander if (!ht) 79750a81498SJens Wiklander return TEE_ERROR_CORRUPT_OBJECT; 79850a81498SJens Wiklander 799a48d0254SJens Wiklander if (!ht->dirty) 800a48d0254SJens Wiklander return TEE_SUCCESS; 801a48d0254SJens Wiklander 80250a81498SJens Wiklander res = crypto_ops.hash.get_ctx_size(TEE_FS_HTREE_HASH_ALG, &size); 80350a81498SJens Wiklander if (res != TEE_SUCCESS) 80450a81498SJens Wiklander return res; 80550a81498SJens Wiklander ctx = malloc(size); 80650a81498SJens Wiklander if (!ctx) 80750a81498SJens Wiklander return TEE_ERROR_OUT_OF_MEMORY; 80850a81498SJens Wiklander 80950a81498SJens Wiklander res = htree_traverse_post_order(ht, htree_sync_node_to_storage, ctx); 81050a81498SJens Wiklander if (res != TEE_SUCCESS) 81150a81498SJens Wiklander goto out; 81250a81498SJens Wiklander 81350a81498SJens Wiklander /* All the nodes are written to storage now. Time to update root. */ 81450a81498SJens Wiklander res = update_root(ht); 81550a81498SJens Wiklander if (res != TEE_SUCCESS) 81650a81498SJens Wiklander goto out; 81750a81498SJens Wiklander 81850a81498SJens Wiklander res = rpc_write_head(ht, ht->head.counter & 1, &ht->head); 81950a81498SJens Wiklander if (res != TEE_SUCCESS) 82050a81498SJens Wiklander goto out; 82150a81498SJens Wiklander 82250a81498SJens Wiklander ht->dirty = false; 823f28e5060SJens Wiklander if (hash) 824f28e5060SJens Wiklander memcpy(hash, ht->root.node.hash, sizeof(ht->root.node.hash)); 82550a81498SJens Wiklander out: 82650a81498SJens Wiklander free(ctx); 82750a81498SJens Wiklander if (res != TEE_SUCCESS) 82850a81498SJens Wiklander tee_fs_htree_close(ht_arg); 82950a81498SJens Wiklander return res; 83050a81498SJens Wiklander } 83150a81498SJens Wiklander 83250a81498SJens Wiklander static TEE_Result get_block_node(struct tee_fs_htree *ht, bool create, 833e2adafecSJens Wiklander size_t block_num, struct htree_node **node) 83450a81498SJens Wiklander { 83550a81498SJens Wiklander TEE_Result res; 83650a81498SJens Wiklander struct htree_node *nd; 83750a81498SJens Wiklander 83850a81498SJens Wiklander res = get_node(ht, create, BLOCK_NUM_TO_NODE_ID(block_num), &nd); 839e2adafecSJens Wiklander if (res == TEE_SUCCESS) 84050a81498SJens Wiklander *node = nd; 84150a81498SJens Wiklander 84250a81498SJens Wiklander return res; 84350a81498SJens Wiklander } 84450a81498SJens Wiklander 84550a81498SJens Wiklander TEE_Result tee_fs_htree_write_block(struct tee_fs_htree **ht_arg, 84650a81498SJens Wiklander size_t block_num, const void *block) 84750a81498SJens Wiklander { 84850a81498SJens Wiklander struct tee_fs_htree *ht = *ht_arg; 84950a81498SJens Wiklander TEE_Result res; 85050a81498SJens Wiklander struct tee_fs_rpc_operation op; 85150a81498SJens Wiklander struct htree_node *node = NULL; 85250a81498SJens Wiklander uint8_t block_vers; 85350a81498SJens Wiklander void *ctx; 85450a81498SJens Wiklander void *enc_block; 85550a81498SJens Wiklander 85650a81498SJens Wiklander if (!ht) 85750a81498SJens Wiklander return TEE_ERROR_CORRUPT_OBJECT; 85850a81498SJens Wiklander 859e2adafecSJens Wiklander res = get_block_node(ht, true, block_num, &node); 86050a81498SJens Wiklander if (res != TEE_SUCCESS) 86150a81498SJens Wiklander goto out; 86250a81498SJens Wiklander 863e2adafecSJens Wiklander if (!node->block_updated) 864e2adafecSJens Wiklander node->node.flags ^= HTREE_NODE_COMMITTED_BLOCK; 865e2adafecSJens Wiklander 866e2adafecSJens Wiklander block_vers = !!(node->node.flags & HTREE_NODE_COMMITTED_BLOCK); 86750a81498SJens Wiklander res = ht->stor->rpc_write_init(ht->stor_aux, &op, 86850a81498SJens Wiklander TEE_FS_HTREE_TYPE_BLOCK, block_num, 86950a81498SJens Wiklander block_vers, &enc_block); 87050a81498SJens Wiklander if (res != TEE_SUCCESS) 87150a81498SJens Wiklander goto out; 87250a81498SJens Wiklander 87350a81498SJens Wiklander res = authenc_init(&ctx, TEE_MODE_ENCRYPT, ht, &node->node, 87450a81498SJens Wiklander ht->stor->block_size); 87550a81498SJens Wiklander if (res != TEE_SUCCESS) 87650a81498SJens Wiklander goto out; 87750a81498SJens Wiklander res = authenc_encrypt_final(ctx, node->node.tag, block, 87850a81498SJens Wiklander ht->stor->block_size, enc_block); 87950a81498SJens Wiklander if (res != TEE_SUCCESS) 88050a81498SJens Wiklander goto out; 88150a81498SJens Wiklander 88264fa6c0aSJens Wiklander res = ht->stor->rpc_write_final(&op); 88350a81498SJens Wiklander if (res != TEE_SUCCESS) 88450a81498SJens Wiklander goto out; 88550a81498SJens Wiklander 886e2adafecSJens Wiklander node->block_updated = true; 88750a81498SJens Wiklander node->dirty = true; 88850a81498SJens Wiklander ht->dirty = true; 88950a81498SJens Wiklander out: 89050a81498SJens Wiklander if (res != TEE_SUCCESS) 89150a81498SJens Wiklander tee_fs_htree_close(ht_arg); 89250a81498SJens Wiklander return res; 89350a81498SJens Wiklander } 89450a81498SJens Wiklander 89550a81498SJens Wiklander TEE_Result tee_fs_htree_read_block(struct tee_fs_htree **ht_arg, 89650a81498SJens Wiklander size_t block_num, void *block) 89750a81498SJens Wiklander { 89850a81498SJens Wiklander struct tee_fs_htree *ht = *ht_arg; 89950a81498SJens Wiklander TEE_Result res; 90050a81498SJens Wiklander struct tee_fs_rpc_operation op; 90150a81498SJens Wiklander struct htree_node *node; 90250a81498SJens Wiklander uint8_t block_vers; 90350a81498SJens Wiklander size_t len; 90450a81498SJens Wiklander void *ctx; 90550a81498SJens Wiklander void *enc_block; 90650a81498SJens Wiklander 90750a81498SJens Wiklander if (!ht) 90850a81498SJens Wiklander return TEE_ERROR_CORRUPT_OBJECT; 90950a81498SJens Wiklander 910e2adafecSJens Wiklander res = get_block_node(ht, false, block_num, &node); 91150a81498SJens Wiklander if (res != TEE_SUCCESS) 91250a81498SJens Wiklander goto out; 91350a81498SJens Wiklander 914e2adafecSJens Wiklander block_vers = !!(node->node.flags & HTREE_NODE_COMMITTED_BLOCK); 91550a81498SJens Wiklander res = ht->stor->rpc_read_init(ht->stor_aux, &op, 91650a81498SJens Wiklander TEE_FS_HTREE_TYPE_BLOCK, block_num, 91750a81498SJens Wiklander block_vers, &enc_block); 91850a81498SJens Wiklander if (res != TEE_SUCCESS) 91950a81498SJens Wiklander goto out; 92050a81498SJens Wiklander 92164fa6c0aSJens Wiklander res = ht->stor->rpc_read_final(&op, &len); 92250a81498SJens Wiklander if (res != TEE_SUCCESS) 92350a81498SJens Wiklander goto out; 92450a81498SJens Wiklander if (len != ht->stor->block_size) { 92550a81498SJens Wiklander res = TEE_ERROR_CORRUPT_OBJECT; 92650a81498SJens Wiklander goto out; 92750a81498SJens Wiklander } 92850a81498SJens Wiklander 92950a81498SJens Wiklander res = authenc_init(&ctx, TEE_MODE_DECRYPT, ht, &node->node, 93050a81498SJens Wiklander ht->stor->block_size); 93150a81498SJens Wiklander if (res != TEE_SUCCESS) 93250a81498SJens Wiklander goto out; 93350a81498SJens Wiklander 93450a81498SJens Wiklander res = authenc_decrypt_final(ctx, node->node.tag, enc_block, 93550a81498SJens Wiklander ht->stor->block_size, block); 93650a81498SJens Wiklander out: 93750a81498SJens Wiklander if (res != TEE_SUCCESS) 93850a81498SJens Wiklander tee_fs_htree_close(ht_arg); 93950a81498SJens Wiklander return res; 94050a81498SJens Wiklander } 94150a81498SJens Wiklander 94250a81498SJens Wiklander TEE_Result tee_fs_htree_truncate(struct tee_fs_htree **ht_arg, size_t block_num) 94350a81498SJens Wiklander { 94450a81498SJens Wiklander struct tee_fs_htree *ht = *ht_arg; 94550a81498SJens Wiklander size_t node_id = BLOCK_NUM_TO_NODE_ID(block_num); 94650a81498SJens Wiklander struct htree_node *node; 94750a81498SJens Wiklander 94850a81498SJens Wiklander if (!ht) 94950a81498SJens Wiklander return TEE_ERROR_CORRUPT_OBJECT; 95050a81498SJens Wiklander 95150a81498SJens Wiklander while (node_id < ht->imeta.max_node_id) { 95250a81498SJens Wiklander node = find_closest_node(ht, ht->imeta.max_node_id); 95350a81498SJens Wiklander assert(node && node->id == ht->imeta.max_node_id); 95450a81498SJens Wiklander assert(!node->child[0] && !node->child[1]); 95550a81498SJens Wiklander assert(node->parent); 95650a81498SJens Wiklander assert(node->parent->child[node->id & 1] == node); 95750a81498SJens Wiklander node->parent->child[node->id & 1] = NULL; 95850a81498SJens Wiklander free(node); 95950a81498SJens Wiklander ht->imeta.max_node_id--; 96050a81498SJens Wiklander ht->dirty = true; 96150a81498SJens Wiklander } 96250a81498SJens Wiklander 96350a81498SJens Wiklander return TEE_SUCCESS; 96450a81498SJens Wiklander } 965