| /* 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 <tee_api_types.h> |
| #include <utee_defines.h> |
| |
| #define TEE_FS_HTREE_HASH_SIZE TEE_SHA256_HASH_SIZE |
| #define TEE_FS_HTREE_IV_SIZE 16 |
| #define TEE_FS_HTREE_FEK_SIZE 16 |
| #define TEE_FS_HTREE_TAG_SIZE 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*/ |