/* SPDX-License-Identifier: BSD-2-Clause */ /* * Copyright (c) 2017, Linaro Limited */ #ifndef __TEE_FS_HTREE_H #define __TEE_FS_HTREE_H /* * The purpose of this API is to provide file integrity and confidentiality * in order to implement secure storage. On-disk data structures are * duplicated to make updates atomic, an update is finalized to disk with * tee_fs_htree_sync_to_storage(). * * This implementation doesn't provide rollback protection, it only * guarantees the integrity and confidentiality of the file. */ #include #include #include #define TEE_FS_HTREE_HASH_SIZE TEE_SHA256_HASH_SIZE #define TEE_FS_HTREE_IV_SIZE U(16) #define TEE_FS_HTREE_FEK_SIZE U(16) #define TEE_FS_HTREE_TAG_SIZE U(16) /* Internal struct provided to let the rpc callbacks know the size if needed */ struct tee_fs_htree_node_image { /* Note that calc_node_hash() depends on hash first in struct */ uint8_t hash[TEE_FS_HTREE_HASH_SIZE]; uint8_t iv[TEE_FS_HTREE_IV_SIZE]; uint8_t tag[TEE_FS_HTREE_TAG_SIZE]; uint16_t flags; }; /* * This struct is not interpreted by the hash tree, it's up to the user of * the interface to update etc if needed. */ struct tee_fs_htree_meta { uint64_t length; }; /* Internal struct needed by struct tee_fs_htree_image */ struct tee_fs_htree_imeta { struct tee_fs_htree_meta meta; uint32_t max_node_id; }; /* Internal struct provided to let the rpc callbacks know the size if needed */ struct tee_fs_htree_image { uint8_t iv[TEE_FS_HTREE_IV_SIZE]; uint8_t tag[TEE_FS_HTREE_TAG_SIZE]; uint8_t enc_fek[TEE_FS_HTREE_FEK_SIZE]; uint8_t imeta[sizeof(struct tee_fs_htree_imeta)]; uint32_t counter; }; /** * enum tee_fs_htree_type - type of hash tree element * @TEE_FS_HTREE_TYPE_HEAD: indicates a struct tee_fs_htree_image * @TEE_FS_HTREE_TYPE_NODE: indicates a struct tee_fs_htree_node_image * @TEE_FS_HTREE_TYPE_BLOCK: indicates a data block */ enum tee_fs_htree_type { TEE_FS_HTREE_TYPE_HEAD, TEE_FS_HTREE_TYPE_NODE, TEE_FS_HTREE_TYPE_BLOCK, }; struct tee_fs_rpc_operation; /** * struct tee_fs_htree_storage - storage description supplied by user of * this interface * @block_size: size of data blocks * @rpc_read_init: initialize a struct tee_fs_rpc_operation for an RPC read * operation * @rpc_write_init: initialize a struct tee_fs_rpc_operation for an RPC * write operation * * The @idx arguments starts counting from 0. The @vers arguments are either * 0 or 1. The @data arguments is a pointer to a buffer in non-secure shared * memory where the encrypted data is stored. */ struct tee_fs_htree_storage { size_t block_size; TEE_Result (*rpc_read_init)(void *aux, struct tee_fs_rpc_operation *op, enum tee_fs_htree_type type, size_t idx, uint8_t vers, void **data); TEE_Result (*rpc_read_final)(struct tee_fs_rpc_operation *op, size_t *bytes); TEE_Result (*rpc_write_init)(void *aux, struct tee_fs_rpc_operation *op, enum tee_fs_htree_type type, size_t idx, uint8_t vers, void **data); TEE_Result (*rpc_write_final)(struct tee_fs_rpc_operation *op); }; struct tee_fs_htree; /** * tee_fs_htree_open() - opens/creates a hash tree * @create: true if a new hash tree is to be created, else the hash tree * is read in and verified * @hash: hash of root node, ignored if NULL * @uuid: uuid of requesting TA, may be NULL if not from a TA * @stor: storage description * @stor_aux: auxilary pointer supplied to callbacks in struct * tee_fs_htree_storage * @ht: returned hash tree on success */ TEE_Result tee_fs_htree_open(bool create, uint8_t *hash, const TEE_UUID *uuid, const struct tee_fs_htree_storage *stor, void *stor_aux, struct tee_fs_htree **ht); /** * tee_fs_htree_close() - close a hash tree * @ht: hash tree */ void tee_fs_htree_close(struct tee_fs_htree **ht); /** * tee_fs_htree_get_meta() - get a pointer to associated struct * tee_fs_htree_meta * @ht: hash tree */ struct tee_fs_htree_meta *tee_fs_htree_get_meta(struct tee_fs_htree *ht); /** * tee_fs_htree_meta_set_dirty() - tell hash tree that meta were modified */ void tee_fs_htree_meta_set_dirty(struct tee_fs_htree *ht); /** * tee_fs_htree_sync_to_storage() - synchronize hash tree to storage * @ht: hash tree * @hash: hash of root node is copied to this if not NULL * * Frees the hash tree and sets *ht to NULL on failure and returns an error code */ TEE_Result tee_fs_htree_sync_to_storage(struct tee_fs_htree **ht, uint8_t *hash); /** * tee_fs_htree_truncate() - truncate a hash tree * @ht: hash tree * @block_num: the number of nodes to truncate to * * Frees the hash tree and sets *ht to NULL on failure and returns an error code */ TEE_Result tee_fs_htree_truncate(struct tee_fs_htree **ht, size_t block_num); /** * tee_fs_htree_write_block() - encrypt and write a data block to storage * @ht: hash tree * @block_num: block number * @block: pointer to a block of stor->block_size size * * Frees the hash tree and sets *ht to NULL on failure and returns an error code */ TEE_Result tee_fs_htree_write_block(struct tee_fs_htree **ht, size_t block_num, const void *block); /** * tee_fs_htree_write_block() - read and decrypt a data block from storage * @ht: hash tree * @block_num: block number * @block: pointer to a block of stor->block_size size * * Frees the hash tree and sets *ht to NULL on failure and returns an error code */ TEE_Result tee_fs_htree_read_block(struct tee_fs_htree **ht, size_t block_num, void *block); #endif /*__TEE_FS_HTREE_H*/