pf_contex
struct pf_context {
metadata_node_t file_metadata; // actual data from disk's meta data node
pf_status_t last_error;
metadata_encrypted_t encrypted_part_plain; // encrypted part of metadata node, decrypted
file_node_t root_mht; // the root of the mht is always needed (for files bigger than 3KB)
pf_handle_t file;
pf_file_mode_t mode;
uint64_t offset; // current file position (user's view)
bool end_of_file;
uint64_t real_file_size;
bool need_writing;
pf_status_t file_status;
pf_key_t user_kdk_key;
pf_key_t cur_key;
lruc_context_t* cache;
#ifdef DEBUG
char* debug_buffer; // buffer for debug output
#endif
};
See also: SGX_PF_Class
How nodes organized
In the PF implementation, there is a function called get_node_numbers
, and the comments implies the node structure of a PF:
What's child MHT node? why 32?- Three types of nodes: metadata, data, and mht
- metadata: TODO
- data: just to store encrypted data
- mht: each mht node can contain
key
andgmac
of 96 data nodes and 32 child mht nodes. Every pf has at least one root mht node, and a mht (child) node is added to this pf after every 96 consecutive data nodes.
// this is a very 'specific' function, tied to the architecture of the file layout,
// returning the node numbers according to the data offset in the file
static void get_node_numbers(uint64_t offset, uint64_t* mht_node_number, uint64_t* data_node_number,
uint64_t* physical_mht_node_number,
uint64_t* physical_data_node_number) {
// physical nodes (file layout):
// node 0 - meta data node
// node 1 - mht
// nodes 2-97 - data (ATTACHED_DATA_NODES_COUNT == 96)
// node 98 - mht
// node 99-195 - data
// etc.
uint64_t _physical_mht_node_number;
uint64_t _physical_data_node_number;
// "logical" nodes: sequential index of the corresponding mht/data node in all mht/data nodes
uint64_t _mht_node_number;
uint64_t _data_node_number;
assert(offset >= MD_USER_DATA_SIZE);
_data_node_number = (offset - MD_USER_DATA_SIZE) / PF_NODE_SIZE;
_mht_node_number = _data_node_number / ATTACHED_DATA_NODES_COUNT;
_physical_data_node_number = _data_node_number
+ 1 // meta data node
+ 1 // mht root
+ _mht_node_number; // number of mht nodes in the middle
// (the root mht mht_node_number is 0)
_physical_mht_node_number = _physical_data_node_number
- _data_node_number % ATTACHED_DATA_NODES_COUNT // now we are at
// the first data node attached to this mht node
- 1; // and now at the mht node itself!
if (mht_node_number != NULL)
*mht_node_number = _mht_node_number;
if (data_node_number != NULL)
*data_node_number = _data_node_number;
if (physical_mht_node_number != NULL)
*physical_mht_node_number = _physical_mht_node_number;
if (physical_data_node_number != NULL)
*physical_data_node_number = _physical_data_node_number;
}
file_node_t
- This macro also defines a linked list of
file_node_t
- Two types of decrypted data in this node
DEFINE_LIST(_file_node);
typedef struct _file_node {
LIST_TYPE(_file_node) list;
uint8_t type;
uint64_t node_number;
struct _file_node* parent;
bool need_writing;
bool new_node;
struct {
uint64_t physical_node_number;
encrypted_node_t encrypted; // the actual data from the disk
};
union { // decrypted data
mht_node_t mht;
data_node_t data;
} decrypted;
} file_node_t;
DEFINE_LISTP(_file_node);
typedef struct _mht_node {
gcm_crypto_data_t data_nodes_crypto[ATTACHED_DATA_NODES_COUNT];
gcm_crypto_data_t mht_nodes_crypto[CHILD_MHT_NODES_COUNT];
} mht_node_t;
typedef struct _data_node {
uint8_t data[PF_NODE_SIZE];
} data_node_t;
typedef struct _encrypted_node {
uint8_t cipher[PF_NODE_SIZE];
} encrypted_node_t;
See also: SDK_PF_DataNode
metadata_node_t
It seems like in graphene pf, the metadata node will be padded rather than filled in with user data.- Similar to SDK:
#define PF_NODE_SIZE 4096U
and#define MD_USER_DATA_SIZE (PF_NODE_SIZE * 3 / 4)
typedef struct _metadata_node {
metadata_plain_t plain_part;
metadata_encrypted_blob_t encrypted_part;
metadata_padding_t padding;
} metadata_node_t;
typedef struct _metadata_plain {
uint64_t file_id;
uint8_t major_version;
uint8_t minor_version;
pf_keyid_t metadata_key_id;
pf_mac_t metadata_gmac; /* GCM mac */
} metadata_plain_t;
typedef struct _metadata_encrypted {
char path[PATH_MAX_SIZE];
uint64_t size;
pf_key_t mht_key;
pf_mac_t mht_gmac;
uint8_t data[MD_USER_DATA_SIZE];
} metadata_encrypted_t;
typedef uint8_t metadata_encrypted_blob_t[sizeof(metadata_encrypted_t)];
typedef uint8_t metadata_padding_t[METADATA_NODE_SIZE -
(sizeof(metadata_plain_t) + sizeof(metadata_encrypted_blob_t))];
See also: SDK_PF_metadata