blob: ed15c972082d00feddf1f1e8c04dfe3186c6e121 [file] [log] [blame] [view] [edit]
# Secure storage service
The secure storage service provides encrypted and tamper proof storage to
secure apps. All operations that modify the file system state are transactional.
Files can be opened, create or deleted by name (where the name is local to the
app). Open files support read, write, get-size and set-size operations. There is
currently no support for sparse files, permissions, quotas or directory
operations.
The server provides three client ports that provide various minimum
capabilities.
- The STORAGE_CLIENT_TD_PORT port offers tamper and rollback detection once the
non-secure OS has booted. This port should be used by most apps as it can offer
more storage and better performance than the other choices.
- The STORAGE_CLIENT_TDEA_PORT port also offers tamper and rollback detection
but can be available before the non-secure OS has booted if the boot loader
supports it.
- The STORAGE_CLIENT_TP_PORT port offers tamper proof storage. An app can for
instance use this port to store data needed by the boot loader that the
non-secure OS cannot erase. Note that non-secure code can prevent read and
write operations from succeeding, but it cannot modify on-disk data.
In the current code STORAGE_CLIENT_TDEA_PORT and STORAGE_CLIENT_TP_PORT map to
the same file system. Apps should not create files with the same name using
different ports, as it is device specific which ports share file systems.
## Code Organization
### Misc
- crypt - Encrypt/decrypt, mac and hash functions.
- rpmb - MMC rpmb protocol.
### File System Components
- block_device - Low level block IO.
- block_mac - Helper functions to bundle block numbers and mac values.
- block_cache - High level block IO.
- super - Super block load/store and file system initialization.
- block_tree - B+ tree implementation.
- block_set - Set operations built on top of B+ tree.
- block_allocator - Keeps track of free vs allocated blocks.
- transaction - Transaction init and complete code.
- block_map - Maps a logical block number to a physical block number and a mac.
- file - File management.
### IPC Specific Components
- ipc - IPC library
- proxy - Creates port that the non-secure OS connects to to provide.
- tipc_ns - Helper functions to send requests to non-secure proxy server.
- block_device_tipc - Implements block operations needed by the file system.
- client_tipc - Implement the secure storage tipc api on top of the file system.
## Disk layout
The file system stores two super-blocks on a device that has tamper detection.
The rest of the data can be stored in a non-secure partition or file. The
default implementation has two file systems. One file system stores the
super-blocks at the start of the mmc rpmb partition and all other blocks in a
file in the file system of the non-secure OS. The other file system stores all
data in the rpmb partition.
Both file systems use the same basic storage format but are configured to use
different block, block number and mac sizes. Two super blocks are used to allow
devices that don't provide atomic block write operations. Two version bits are
used to identify the most recent super block version. The main purpose of the
super block is to locate and validate the root of the free and file B+ trees.
Every block in the file system starts with a 16 byte iv struct. Each time the
data in the block changes, this is assigned a new random value. The rest of the
block is encrypted using this value and a device specific key.
The free set B+ tree list every free block in the file system as a set of
ranges. The key value in the B+ tree is the start of a free range and the data
value is the first block number not in the free range. Overlapping or adjacent
ranges are not allowed, so the data value is also the start of an allocated
range or, for the last free range, the number of blocks in the file system.
The file tree stores all the files in the file system. The key value is a hash
of the file name and is the same size and the block number size for the file
system. The data value is a block-mac that points to a file-entry block.
The file-entry block stores the full file name, file size and the root of a
block map where the file data can be found.
The block map tree is similar to the file tree except the key is the file block
plus one (0 keys are not supported), and the data points to file data.
The super block always points to a valid file system. To make changes to the
file system, any block that needs to change is copied to a new location. These
changes are tracked by in-memory transaction objects. Before a transaction is
complete it uses three block sets (the same storage format as the free set
described above) to keep track of allocated and freed blocks. Blocks that will
not be needed after the transaction completes are stored in the tmp_allocated
set. Blocks that will be needed are stored in allocated, and blocks that should
be added to the free set are stored in freed. To allow concurrent transactions
to update independent files without conflict, files modified by a transaction
are stored in temporary trees until the transaction is complete.
Example file system states of a file system using a 2k block size, 64 bit block
numbers and 16 byte mac values:
- Empty file system example.
![Empty File System Diagram](doc/empty_fs.png)
- Active Transaction state after creating a new file and writing one byte to it.
Note that at this point all the added nodes may only be in the block cache.
![Active Transaction Diagram](doc/active_transaction.png)
- State after completing transaction. The second super block is now the most
recent one. The first super block still points to a valid file system, but
as soon as the next transaction starts, those blocks may be reused. Block 3072
and above may not be on disk and their cache entries are invalid.
![Completed Transaction Diagram](doc/completed_transaction.png)