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