diff options
author | Franklin Wei <me@fwei.tk> | 2018-06-26 17:37:28 -0400 |
---|---|---|
committer | Franklin Wei <me@fwei.tk> | 2018-06-26 17:37:28 -0400 |
commit | 1e3acc575e82210955774897eecbe0c5567b10ca (patch) | |
tree | 012b46e9b8d5791c0c1f33e10fe16f4ac6a5cb92 | |
parent | 42aa4d804e7e8f42745e32d23080f0b895dddb32 (diff) | |
download | csaa-1e3acc575e82210955774897eecbe0c5567b10ca.zip csaa-1e3acc575e82210955774897eecbe0c5567b10ca.tar.gz csaa-1e3acc575e82210955774897eecbe0c5567b10ca.tar.bz2 csaa-1e3acc575e82210955774897eecbe0c5567b10ca.tar.xz |
WIP on database backend
-rw-r--r-- | Makefile | 6 | ||||
-rw-r--r-- | client.c | 1 | ||||
-rw-r--r-- | crypto.c | 359 | ||||
-rw-r--r-- | crypto.h | 77 | ||||
-rw-r--r-- | helper.c | 6 | ||||
-rw-r--r-- | iomt.c | 384 | ||||
-rw-r--r-- | iomt.h | 102 | ||||
-rw-r--r-- | service_provider.c | 269 | ||||
-rwxr-xr-x | testcreate.sh | 2 | ||||
-rwxr-xr-x | testmodify.sh | 4 | ||||
-rw-r--r-- | trusted_module.h | 1 |
11 files changed, 698 insertions, 513 deletions
@@ -1,9 +1,9 @@ all: client server Makefile -CFLAGS = -g -Wall -O0 +CFLAGS = -g -Wall -O0 -lsqlite3 -client: client.o crypto.o test.o +client: client.o crypto.o test.o iomt.o cc -o $@ $^ -lcrypto $(CFLAGS) -server: service_provider.o crypto.o helper.o trusted_module.o main.o test.o +server: service_provider.o crypto.o helper.o trusted_module.o main.o test.o iomt.o cc -o $@ $^ -lcrypto $(CFLAGS) clean: rm -f *.o a.out client server @@ -22,6 +22,7 @@ #define CLIENT #include "crypto.h" +#include "iomt.h" #include "service_provider.h" #include "trusted_module.h" #include "test.h" @@ -1,4 +1,5 @@ #include "crypto.h" +#include "iomt.h" #include "trusted_module.h" #include "test.h" @@ -22,11 +23,6 @@ bool encloses(uint64_t b, uint64_t bprime, uint64_t a) return (b < a && a < bprime) || (bprime <= b && b < a) || (a < bprime && bprime <= b); } -hash_t hash_node(const struct iomt_node *node) -{ - return sha256(node, sizeof(*node)); -} - hash_t hmac_sha256(const void *data, size_t datalen, const void *key, size_t keylen) { hash_t h; @@ -167,14 +163,6 @@ int *bintree_complement(int leafidx, int logleaves, int **orders) return comp; } -hash_t *merkle_complement(const struct iomt *tree, int leafidx, int **orders) -{ - int *compidx = bintree_complement(leafidx, tree->mt_logleaves, orders); - hash_t *comp = lookup_nodes(tree->mt_nodes, compidx, tree->mt_logleaves); - free(compidx); - return comp; -} - int *bintree_ancestors(int leafidx, int logleaves) { int *dep = calloc(logleaves, sizeof(int)); @@ -197,330 +185,6 @@ int *bintree_complement_ordersonly(int leafidx, int logleaves) return orders; } -/* Index-Ordered Merkle Tree routines: */ -/* Calculate the value of all the nodes of the tree, given the IOMT - * leaves in mt_leaves. Leaf count *must* be an integer power of two, - * otherwise bad things will happen. This function should only need to - * be called once, namely when the service provider is created. */ -void iomt_fill(struct iomt *tree) -{ - for(int i = 0; i < tree->mt_leafcount; ++i) - { - uint64_t mt_idx = (1 << tree->mt_logleaves) - 1 + i; - tree->mt_nodes[mt_idx] = hash_node(tree->mt_leaves + i); - } - /* now loop up from the bottom level, calculating the parent of - * each pair of nodes */ - for(int i = tree->mt_logleaves - 1; i >= 0; --i) - { - uint64_t baseidx = (1 << i) - 1; - for(int j = 0; j < (1 << i); ++j) - { - uint64_t mt_idx = baseidx + j; - tree->mt_nodes[mt_idx] = merkle_parent(tree->mt_nodes[2 * mt_idx + 1], - tree->mt_nodes[2 * mt_idx + 2], - 0); - } - } -} - -/* A bit of a hack: our complement calculation returns the *indices* - * complementary nodes, which is good because the indices are much - * smaller than the actual nodes (which are 32 bytes each with - * SHA-256). However, the trusted module requires an array of the - * actual hash values of the complementary nodes. It would be optimal - * to modify each function to take the array of all nodes in the tree - * in addition to the complement indices, but this function will serve - * as a shim in the meantime. */ -hash_t *lookup_nodes(const hash_t *nodes, const int *indices, int n) -{ - hash_t *ret = calloc(n, sizeof(hash_t)); - for(int i = 0; i < n; ++i) - ret[i] = nodes[indices[i]]; - return ret; -} - -void restore_nodes(hash_t *nodes, const int *indices, const hash_t *values, int n) -{ - for(int i = 0; i < n; ++i) - nodes[indices[i]] = values[i]; -} - -/* Update mt_nodes to reflect a change to a leaf node's - * value. Optionally, if old_dep is not NULL, *old_dep will be made to - * point to an array of length mt_logleaves that contains the old node - * values (whose indices are returned by bintree_ancestors()). NOTE: - * this function will NOT set the corresponding IOMT leaf; use - * iomt_update_leaf_full for that. */ -void merkle_update(struct iomt *tree, uint64_t leafidx, hash_t newval, hash_t **old_dep) -{ - if(old_dep) - *old_dep = calloc(tree->mt_logleaves, sizeof(hash_t)); - - uint64_t idx = (1 << tree->mt_logleaves) - 1 + leafidx; - - tree->mt_nodes[idx] = newval; - for(int i = 0; i < tree->mt_logleaves; ++i) - { - /* find the merkle parent of the two children first */ - hash_t parent = merkle_parent(tree->mt_nodes[idx], - tree->mt_nodes[bintree_sibling(idx)], - (idx + 1) & 1); - - idx = bintree_parent(idx); - - /* save old value */ - if(old_dep) - (*old_dep)[i] = tree->mt_nodes[idx]; - - tree->mt_nodes[idx] = parent; - } -} - -hash_t iomt_getroot(const struct iomt *tree) -{ - return tree->mt_nodes[0]; -} - -struct iomt_node *iomt_get_leaf_by_idx(const struct iomt *tree, uint64_t leafidx) -{ - return tree->mt_leaves + leafidx; -} - -/* find a node with given idx */ -struct iomt_node *iomt_find_leaf(const struct iomt *tree, uint64_t idx, uint64_t *leafidx) -{ - for(int i = 0; i < tree->mt_leafcount; ++i) - if(idx == tree->mt_leaves[i].idx) - { - if(leafidx) - *leafidx = i; - return tree->mt_leaves + i; - } - return NULL; -} - -struct iomt_node *iomt_find_encloser(const struct iomt *tree, uint64_t idx, uint64_t *leafidx) -{ - for(int i = 0; i < tree->mt_leafcount; ++i) - if(encloses(tree->mt_leaves[i].idx, tree->mt_leaves[i].next_idx, idx)) - { - if(leafidx) - *leafidx = i; - return tree->mt_leaves + i; - } - return NULL; -} - -struct iomt_node *iomt_find_leaf_or_encloser(const struct iomt *tree, uint64_t idx, uint64_t *leafidx) -{ - for(int i = 0; i < tree->mt_leafcount; ++i) - { - if(tree->mt_leaves[i].idx == idx || - encloses(tree->mt_leaves[i].idx, tree->mt_leaves[i].next_idx, idx)) - { - if(leafidx) - *leafidx = i; - return tree->mt_leaves + i; - } - } - return NULL; -} - -void iomt_update(struct iomt *tree, uint64_t idx, hash_t newval) -{ - /* update the leaf first, then use merkle_update */ - uint64_t leafidx; - struct iomt_node *leaf = iomt_find_leaf(tree, idx, &leafidx); - leaf->val = newval; - - merkle_update(tree, leafidx, hash_node(leaf), NULL); -} - -void iomt_update_leaf_full(struct iomt *tree, uint64_t leafidx, - uint64_t new_idx, uint64_t new_next_idx, hash_t new_val) -{ - struct iomt_node *leaf = tree->mt_leaves + leafidx; - leaf->idx = new_idx; - leaf->next_idx = new_next_idx; - leaf->val = new_val; - - merkle_update(tree, leafidx, hash_node(leaf), NULL); -} - -void iomt_update_leaf_idx(struct iomt *tree, uint64_t leafidx, - uint64_t new_idx) -{ - struct iomt_node *leaf = tree->mt_leaves + leafidx; - leaf->idx = new_idx; - - merkle_update(tree, leafidx, hash_node(leaf), NULL); -} - -void iomt_update_leaf_nextidx(struct iomt *tree, uint64_t leafidx, - uint64_t new_next_idx) -{ - struct iomt_node *leaf = tree->mt_leaves + leafidx; - leaf->next_idx = new_next_idx; - - merkle_update(tree, leafidx, hash_node(leaf), NULL); -} - -void iomt_update_leaf_hash(struct iomt *tree, uint64_t leafidx, - hash_t new_val) -{ - struct iomt_node *leaf = tree->mt_leaves + leafidx; - leaf->val = new_val; - - merkle_update(tree, leafidx, hash_node(leaf), NULL); -} - -/* Create a merkle tree with 2^logleaves leaves, each initialized to a - * zero leaf (not a placeholder!) */ -struct iomt *iomt_new(int logleaves) -{ - struct iomt *tree = calloc(1, sizeof(struct iomt)); - tree->mt_leafcount = 1 << logleaves; - tree->mt_logleaves = logleaves; - tree->mt_leaves = calloc(tree->mt_leafcount, sizeof(struct iomt_node)); - - tree->mt_nodes = calloc(2 * tree->mt_leafcount - 1, sizeof(hash_t)); - - return tree; -} - -struct iomt *iomt_dup(const struct iomt *tree) -{ - if(!tree) - return NULL; - struct iomt *newtree = calloc(1, sizeof(struct iomt)); - newtree->mt_leafcount = tree->mt_leafcount; - newtree->mt_logleaves = tree->mt_logleaves; - - newtree->mt_leaves = calloc(tree->mt_leafcount, sizeof(struct iomt_node)); - memcpy(newtree->mt_leaves, tree->mt_leaves, tree->mt_leafcount * sizeof(struct iomt_node)); - - newtree->mt_nodes = calloc(2 * tree->mt_leafcount - 1, sizeof(hash_t)); - memcpy(newtree->mt_nodes, tree->mt_nodes, (2 * tree->mt_leafcount - 1) * sizeof(hash_t)); - - return newtree; -} - -/* TODO: error checking */ -uint64_t read_u64(int (*read_fn)(void *userdata, void *buf, size_t len), void *userdata) -{ - uint64_t n; - if(read_fn(userdata, &n, sizeof(n)) != sizeof(n)) - { - printf("short read\n"); - return 0; - } - return n; -} - -void write_u64(void (*write_fn)(void *userdata, const void *data, size_t len), - void *userdata, uint64_t n) -{ - write_fn(userdata, &n, sizeof(n)); -} - -#define IOMT_EMPTY (uint64_t)0xFFFFFFFFFFFFFFFFUL - -void iomt_serialize(const struct iomt *tree, - void (*write_fn)(void *userdata, const void *data, size_t len), - void *userdata) -{ - /* leafcount isn't needed */ - if(tree) - { - write_u64(write_fn, userdata, tree->mt_logleaves); - - write_fn(userdata, tree->mt_nodes, sizeof(hash_t) * (2 * tree->mt_leafcount - 1)); - write_fn(userdata, tree->mt_leaves, sizeof(struct iomt_node) * tree->mt_leafcount); - } - else - write_u64(write_fn, userdata, IOMT_EMPTY); -} - -struct iomt *iomt_deserialize(int (*read_fn)(void *userdata, void *buf, size_t len), - void *userdata) -{ - uint64_t logleaves = read_u64(read_fn, userdata); - - if(logleaves == IOMT_EMPTY) - return NULL; - - struct iomt *tree = iomt_new(logleaves); - - read_fn(userdata, tree->mt_nodes, sizeof(hash_t) * (2 * tree->mt_leafcount - 1)); - read_fn(userdata, tree->mt_leaves, sizeof(struct iomt_node) * tree->mt_leafcount); - - return tree; -} - -void iomt_free(struct iomt *tree) -{ - if(tree) - { - free(tree->mt_nodes); - free(tree->mt_leaves); - free(tree); - } -} - -/* arbitrary */ -#define FILELINES_LOGLEAVES 10 - -struct iomt *iomt_from_lines(const char *filename) -{ - if(!filename) - return NULL; - - struct iomt *tree = iomt_new(FILELINES_LOGLEAVES); - - FILE *f = fopen(filename, "r"); - - SHA256_CTX ctx; - SHA256_Init(&ctx); - - int c; - uint64_t line = 0; - - do - { - c = fgetc(f); - - char ch = c; - - if(c != EOF) - SHA256_Update(&ctx, &ch, sizeof(ch)); - - if(ch == '\n' || c == EOF) - { - hash_t linehash; - SHA256_Final(linehash.hash, &ctx); - - /* set this leaf to loop around */ - iomt_update_leaf_full(tree, line, line + 1, 1, linehash); - - if(line > 0) - { - /* make previously inserted leaf point to this leaf */ - iomt_update_leaf_nextidx(tree, line - 1, line + 1); - } - - line++; - - /* re-initialize for next line */ - SHA256_Init(&ctx); - } - } while(c != EOF); - - fclose(f); - - return tree; -} - struct hashstring hash_format(hash_t h, int n) { struct hashstring ret; @@ -531,23 +195,6 @@ struct hashstring hash_format(hash_t h, int n) return ret; } -void iomt_dump(const struct iomt *tree) -{ - if(tree) - { - for(int i = 0; i < tree->mt_leafcount; ++i) - { - printf("(%lu, %s, %lu)%s", - tree->mt_leaves[i].idx, - hash_format(tree->mt_leaves[i].val, 4).str, - tree->mt_leaves[i].next_idx, - (i == tree->mt_leafcount - 1) ? "\n" : ", "); - } - } - else - printf("(empty IOMT)\n"); -} - /* convert the first 8 bytes (little endian) to a 64-bit int */ uint64_t hash_to_u64(hash_t h) { @@ -601,9 +248,9 @@ hash_t calc_lambda(hash_t gamma, const struct iomt *buildcode, const struct iomt { hash_t buildcode_root = hash_null, composefile_root = hash_null; if(buildcode) - buildcode_root = buildcode->mt_nodes[0]; + buildcode_root = iomt_getroot(buildcode); if(composefile) - composefile_root = composefile->mt_nodes[0]; + composefile_root = iomt_getroot(composefile); SHA256_CTX ctx; hash_t h; @@ -15,34 +15,6 @@ typedef struct hash_t { unsigned char hash[32]; } hash_t; -struct iomt_node { - uint64_t idx, next_idx; /* idx cannot be zero */ - hash_t val; /* all zero indicates placeholder */ -}; - -struct iomt { - int mt_leafcount, mt_logleaves; /* mt_logleaves must equal 2^mt_leafcount */ - - /* Each level of the IOMT is stored sequentially from left to - * right, top to bottom, as follows: - * - * [0]: root - * [1]: root left child - * [2]: root right child - * [3]: left child of [1] - * [4]: right child of [1] - * [5]: left child of [2] - * [6]: right child of [2], - * - * and so on. - */ - hash_t *mt_nodes; /* this has 2 * mt_leafcount - 1 elements. Note - * that the bottom level consists of hashes of - * the leaf nodes. */ - - struct iomt_node *mt_leaves; -}; - /* guaranteed to be zero */ static const struct hash_t hash_null = { { 0 } }; @@ -50,7 +22,6 @@ bool encloses(uint64_t b, uint64_t bprime, uint64_t a); bool hash_equals(hash_t a, hash_t b); bool is_zero(hash_t u); -hash_t hash_node(const struct iomt_node *node); hash_t hash_xor(hash_t a, hash_t b); hash_t sha256(const void *data, size_t datalen); @@ -77,55 +48,9 @@ int *bintree_complement_ordersonly(int leafidx, int logleaves); * given leaf node. Will be ordered from nearest relative to root. */ int *bintree_ancestors(int leafidx, int logleaves); -hash_t *merkle_complement(const struct iomt *tree, int leafidx, int **orders); - hash_t *lookup_nodes(const hash_t *nodes, const int *indices, int n); void restore_nodes(hash_t *nodes, const int *indices, const hash_t *values, int n); -/* This function is prefixed merkle_ because it does not know about - * any IOMT-specific properties (though it is still passed an iomt - * struct) */ -void merkle_update(struct iomt *tree, uint64_t leafidx, hash_t newval, hash_t **old_dep); - -struct iomt *iomt_new(int logleaves); -struct iomt *iomt_dup(const struct iomt *tree); -void iomt_free(struct iomt *tree); - -/* Find a leaf with IOMT index `idx' and change its value, propagating - * up the tree. */ -void iomt_update(struct iomt *tree, uint64_t idx, hash_t newval); - -/* Set all the fields of a leaf node (not an IOMT index!) */ -void iomt_update_leaf_full(struct iomt *tree, uint64_t leafidx, - uint64_t new_idx, uint64_t new_next_idx, hash_t new_val); -void iomt_update_leaf_idx(struct iomt *tree, uint64_t leafidx, - uint64_t new_idx); -void iomt_update_leaf_nextidx(struct iomt *tree, uint64_t leafidx, - uint64_t new_next_idx); -void iomt_update_leaf_hash(struct iomt *tree, uint64_t leafidx, - hash_t new_val); - -/* Create an IOMT where the leaves are the hash of file lines */ -struct iomt *iomt_from_lines(const char *filename); - -void iomt_serialize(const struct iomt *tree, - void (*write_fn)(void *userdata, const void *data, size_t len), - void *userdata); - -struct iomt *iomt_deserialize(int (*read_fn)(void *userdata, void *buf, size_t len), - void *userdata); - -void iomt_fill(struct iomt *tree); -void iomt_dump(const struct iomt *tree); - -hash_t iomt_getroot(const struct iomt *tree); -struct iomt_node *iomt_get_leaf_by_idx(const struct iomt *tree, uint64_t leafidx); - -/* All linear searches... slow! */ -struct iomt_node *iomt_find_leaf(const struct iomt *tree, uint64_t idx, uint64_t *leafidx); -struct iomt_node *iomt_find_encloser(const struct iomt *tree, uint64_t idx, uint64_t *leafidx); -struct iomt_node *iomt_find_leaf_or_encloser(const struct iomt *tree, uint64_t idx, uint64_t *leafidx); - int bintree_parent(int idx); int bintree_sibling(int idx); @@ -143,6 +68,8 @@ hash_t crypt_secret(hash_t encrypted_secret, uint64_t file_idx, uint64_t file_version, const void *key, size_t keylen); +struct iomt; + hash_t calc_lambda(hash_t gamma, const struct iomt *buildcode, const struct iomt *composefile, hash_t kf); /* Generate a signed acknowledgement for successful completion of a @@ -96,9 +96,9 @@ struct tm_cert cert_rv_by_idx(const struct trusted_module *tm, * given in file_node->idx with the user added with level 3 access in * the ACL. */ struct tm_request req_filecreate(const struct trusted_module *tm, - uint64_t user_id, - const struct iomt_node *file_node, - const hash_t *file_comp, const int *file_orders, size_t file_n) + uint64_t user_id, + const struct iomt_node *file_node, + const hash_t *file_comp, const int *file_orders, size_t file_n) { /* construct a request to create a file */ struct tm_request req = req_null; @@ -0,0 +1,384 @@ +#include "iomt.h" +#include "crypto.h" + +#include <string.h> + +#include <openssl/hmac.h> +#include <openssl/sha.h> + +hash_t hash_node(const struct iomt_node *node) +{ + return sha256(node, sizeof(*node)); +} + +/* internal nodes only */ +hash_t iomt_getnode(const struct iomt *tree, int idx) +{ + if(tree->in_memory) + return tree->mt_nodes[idx]; +} + +void iomt_setnode(const struct iomt *tree, int idx, hash_t val) +{ + if(tree->in_memory) + tree->mt_nodes[idx] = val; +} + +struct iomt_node iomt_getleaf(const struct iomt *tree, uint64_t leafidx) +{ + if(tree->in_memory) + return tree->mt_leaves[leafidx]; +} + +void iomt_setleaf(struct iomt *tree, uint64_t leafidx, struct iomt_node val) +{ + if(tree->in_memory) + tree->mt_leaves[leafidx] = val; +} + +hash_t *merkle_complement(const struct iomt *tree, int leafidx, int **orders) +{ + int *compidx = bintree_complement(leafidx, tree->mt_logleaves, orders); + hash_t *comp = lookup_nodes(tree->mt_nodes, compidx, tree->mt_logleaves); + free(compidx); + return comp; +} + +/* Index-Ordered Merkle Tree routines: */ +/* Calculate the value of all the nodes of the tree, given the IOMT + * leaves in mt_leaves. Leaf count *must* be an integer power of two, + * otherwise bad things will happen. This function should only need to + * be called once, namely when the service provider is created. */ +void iomt_fill(struct iomt *tree) +{ + for(int i = 0; i < tree->mt_leafcount; ++i) + { + uint64_t mt_idx = (1 << tree->mt_logleaves) - 1 + i; + iomt_setnode(tree, mt_idx, hash_node(tree->mt_leaves + i)); + } + /* now loop up from the bottom level, calculating the parent of + * each pair of nodes */ + for(int i = tree->mt_logleaves - 1; i >= 0; --i) + { + uint64_t baseidx = (1 << i) - 1; + for(int j = 0; j < (1 << i); ++j) + { + uint64_t mt_idx = baseidx + j; + iomt_setnode(tree, mt_idx, merkle_parent(iomt_getnode(tree, 2 * mt_idx + 1), + iomt_getnode(tree, 2 * mt_idx + 2), + 0)); + } + } +} + +/* A bit of a hack: our complement calculation returns the *indices* + * complementary nodes, which is good because the indices are much + * smaller than the actual nodes (which are 32 bytes each with + * SHA-256). However, the trusted module requires an array of the + * actual hash values of the complementary nodes. It would be optimal + * to modify each function to take the array of all nodes in the tree + * in addition to the complement indices, but this function will serve + * as a shim in the meantime. */ +hash_t *lookup_nodes(const hash_t *nodes, const int *indices, int n) +{ + hash_t *ret = calloc(n, sizeof(hash_t)); + for(int i = 0; i < n; ++i) + ret[i] = nodes[indices[i]]; + return ret; +} + +void restore_nodes(hash_t *nodes, const int *indices, const hash_t *values, int n) +{ + for(int i = 0; i < n; ++i) + nodes[indices[i]] = values[i]; +} + +/* Update mt_nodes to reflect a change to a leaf node's + * value. Optionally, if old_dep is not NULL, *old_dep will be made to + * point to an array of length mt_logleaves that contains the old node + * values (whose indices are returned by bintree_ancestors()). NOTE: + * this function will NOT set the corresponding IOMT leaf; use + * iomt_update_leaf_full for that. */ +void merkle_update(struct iomt *tree, uint64_t leafidx, hash_t newval, hash_t **old_dep) +{ + if(old_dep) + *old_dep = calloc(tree->mt_logleaves, sizeof(hash_t)); + + uint64_t idx = (1 << tree->mt_logleaves) - 1 + leafidx; + + iomt_setnode(tree, idx, newval); + for(int i = 0; i < tree->mt_logleaves; ++i) + { + /* find the merkle parent of the two children first */ + hash_t parent = merkle_parent(iomt_getnode(tree, idx), + iomt_getnode(tree, bintree_sibling(idx)), + (idx + 1) & 1); + + idx = bintree_parent(idx); + + /* save old value */ + if(old_dep) + (*old_dep)[i] = iomt_getnode(tree, mt_nodes[idx]); + + tree->mt_nodes[idx] = parent; + } +} + +hash_t iomt_getroot(const struct iomt *tree) +{ + return tree->mt_nodes[0]; +} + +/* find a node with given idx */ +struct iomt_node *iomt_find_leaf(const struct iomt *tree, uint64_t idx, uint64_t *leafidx) +{ + for(int i = 0; i < tree->mt_leafcount; ++i) + if(idx == tree->mt_leaves[i].idx) + { + if(leafidx) + *leafidx = i; + return tree->mt_leaves + i; + } + return NULL; +} + +struct iomt_node *iomt_find_encloser(const struct iomt *tree, uint64_t idx, uint64_t *leafidx) +{ + for(int i = 0; i < tree->mt_leafcount; ++i) + if(encloses(tree->mt_leaves[i].idx, tree->mt_leaves[i].next_idx, idx)) + { + if(leafidx) + *leafidx = i; + return tree->mt_leaves + i; + } + return NULL; +} + +struct iomt_node *iomt_find_leaf_or_encloser(const struct iomt *tree, uint64_t idx, uint64_t *leafidx) +{ + for(int i = 0; i < tree->mt_leafcount; ++i) + { + if(tree->mt_leaves[i].idx == idx || + encloses(tree->mt_leaves[i].idx, tree->mt_leaves[i].next_idx, idx)) + { + if(leafidx) + *leafidx = i; + return tree->mt_leaves + i; + } + } + return NULL; +} + +void iomt_update(struct iomt *tree, uint64_t idx, hash_t newval) +{ + /* update the leaf first, then use merkle_update */ + uint64_t leafidx; + struct iomt_node *leaf = iomt_find_leaf(tree, idx, &leafidx); + leaf->val = newval; + + merkle_update(tree, leafidx, hash_node(leaf), NULL); +} + +void iomt_update_leaf_full(struct iomt *tree, uint64_t leafidx, + uint64_t new_idx, uint64_t new_next_idx, hash_t new_val) +{ + struct iomt_node *leaf = tree->mt_leaves + leafidx; + leaf->idx = new_idx; + leaf->next_idx = new_next_idx; + leaf->val = new_val; + + merkle_update(tree, leafidx, hash_node(leaf), NULL); +} + +void iomt_update_leaf_idx(struct iomt *tree, uint64_t leafidx, + uint64_t new_idx) +{ + struct iomt_node *leaf = tree->mt_leaves + leafidx; + leaf->idx = new_idx; + + merkle_update(tree, leafidx, hash_node(leaf), NULL); +} + +void iomt_update_leaf_nextidx(struct iomt *tree, uint64_t leafidx, + uint64_t new_next_idx) +{ + struct iomt_node *leaf = tree->mt_leaves + leafidx; + leaf->next_idx = new_next_idx; + + merkle_update(tree, leafidx, hash_node(leaf), NULL); +} + +void iomt_update_leaf_hash(struct iomt *tree, uint64_t leafidx, + hash_t new_val) +{ + struct iomt_node *leaf = tree->mt_leaves + leafidx; + leaf->val = new_val; + + merkle_update(tree, leafidx, hash_node(leaf), NULL); +} + +/* Create a merkle tree with 2^logleaves leaves, each initialized to a + * zero leaf (not a placeholder!) */ +struct iomt *iomt_new(int logleaves) +{ + struct iomt *tree = calloc(1, sizeof(struct iomt)); + + tree->in_memory = true; + + tree->mt_leafcount = 1 << logleaves; + tree->mt_logleaves = logleaves; + tree->mt_leaves = calloc(tree->mt_leafcount, sizeof(struct iomt_node)); + + tree->mt_nodes = calloc(2 * tree->mt_leafcount - 1, sizeof(hash_t)); + + return tree; +} + +struct iomt *iomt_dup(const struct iomt *tree) +{ + if(!tree) + return NULL; + struct iomt *newtree = calloc(1, sizeof(struct iomt)); + newtree->mt_leafcount = tree->mt_leafcount; + newtree->mt_logleaves = tree->mt_logleaves; + + newtree->mt_leaves = calloc(tree->mt_leafcount, sizeof(struct iomt_node)); + memcpy(newtree->mt_leaves, tree->mt_leaves, tree->mt_leafcount * sizeof(struct iomt_node)); + + newtree->mt_nodes = calloc(2 * tree->mt_leafcount - 1, sizeof(hash_t)); + memcpy(newtree->mt_nodes, tree->mt_nodes, (2 * tree->mt_leafcount - 1) * sizeof(hash_t)); + + return newtree; +} + +/* TODO: error checking */ +uint64_t read_u64(int (*read_fn)(void *userdata, void *buf, size_t len), void *userdata) +{ + uint64_t n; + if(read_fn(userdata, &n, sizeof(n)) != sizeof(n)) + { + printf("short read\n"); + return 0; + } + return n; +} + +void write_u64(void (*write_fn)(void *userdata, const void *data, size_t len), + void *userdata, uint64_t n) +{ + write_fn(userdata, &n, sizeof(n)); +} + +#define IOMT_EMPTY (uint64_t)0xFFFFFFFFFFFFFFFFUL + +void iomt_serialize(const struct iomt *tree, + void (*write_fn)(void *userdata, const void *data, size_t len), + void *userdata) +{ + /* leafcount isn't needed */ + if(tree) + { + write_u64(write_fn, userdata, tree->mt_logleaves); + + write_fn(userdata, tree->mt_nodes, sizeof(hash_t) * (2 * tree->mt_leafcount - 1)); + write_fn(userdata, tree->mt_leaves, sizeof(struct iomt_node) * tree->mt_leafcount); + } + else + write_u64(write_fn, userdata, IOMT_EMPTY); +} + +struct iomt *iomt_deserialize(int (*read_fn)(void *userdata, void *buf, size_t len), + void *userdata) +{ + uint64_t logleaves = read_u64(read_fn, userdata); + + if(logleaves == IOMT_EMPTY) + return NULL; + + struct iomt *tree = iomt_new(logleaves); + + read_fn(userdata, tree->mt_nodes, sizeof(hash_t) * (2 * tree->mt_leafcount - 1)); + read_fn(userdata, tree->mt_leaves, sizeof(struct iomt_node) * tree->mt_leafcount); + + return tree; +} + +void iomt_free(struct iomt *tree) +{ + if(tree) + { + free(tree->mt_nodes); + free(tree->mt_leaves); + free(tree); + } +} + +/* arbitrary */ +#define FILELINES_LOGLEAVES 10 + +struct iomt *iomt_from_lines(const char *filename) +{ + if(!filename) + return NULL; + + struct iomt *tree = iomt_new(FILELINES_LOGLEAVES); + + FILE *f = fopen(filename, "r"); + + SHA256_CTX ctx; + SHA256_Init(&ctx); + + int c; + uint64_t line = 0; + + do + { + c = fgetc(f); + + char ch = c; + + if(c != EOF) + SHA256_Update(&ctx, &ch, sizeof(ch)); + + if(ch == '\n' || c == EOF) + { + hash_t linehash; + SHA256_Final(linehash.hash, &ctx); + + /* set this leaf to loop around */ + iomt_update_leaf_full(tree, line, line + 1, 1, linehash); + + if(line > 0) + { + /* make previously inserted leaf point to this leaf */ + iomt_update_leaf_nextidx(tree, line - 1, line + 1); + } + + line++; + + /* re-initialize for next line */ + SHA256_Init(&ctx); + } + } while(c != EOF); + + fclose(f); + + return tree; +} + +void iomt_dump(const struct iomt *tree) +{ + if(tree) + { + for(int i = 0; i < tree->mt_leafcount; ++i) + { + printf("(%lu, %s, %lu)%s", + tree->mt_leaves[i].idx, + hash_format(tree->mt_leaves[i].val, 4).str, + tree->mt_leaves[i].next_idx, + (i == tree->mt_leafcount - 1) ? "\n" : ", "); + } + } + else + printf("(empty IOMT)\n"); +} @@ -0,0 +1,102 @@ +#ifndef CSAA_IOMT_H +#define CSAA_IOMT_H +#include "crypto.h" + +struct iomt_node { + uint64_t idx, next_idx; /* idx cannot be zero */ + hash_t val; /* all zero indicates placeholder */ +}; + +struct iomt { + bool in_memory; + + void *db; + const char *nodes_table, leaves_table; + + /* the IOMT code will use nodes with key1_name = key1_val and (if + * not NULL) key2_name = key2_val */ + const char *key1_name, *key2_name; + int key1_val, key2_val; + + int mt_leafcount, mt_logleaves; /* mt_logleaves must equal 2^mt_leafcount */ + + /* The following members are valid only if in_memory == + * true... really should use a union here: */ + + /* Each level of the IOMT is stored sequentially from left to + * right, top to bottom, as follows: + * + * [0]: root + * [1]: root left child + * [2]: root right child + * [3]: left child of [1] + * [4]: right child of [1] + * [5]: left child of [2] + * [6]: right child of [2], + * + * and so on. + */ + hash_t *mt_nodes; /* this has 2 * mt_leafcount - 1 elements. Note + * that the bottom level consists of hashes of + * the leaf nodes. */ + + struct iomt_node *mt_leaves; +}; + +hash_t hash_node(const struct iomt_node *node); + +hash_t *merkle_complement(const struct iomt *tree, int leafidx, int **orders); + +/* This function is prefixed merkle_ because it does not know about + * any IOMT-specific properties (though it is still passed an iomt + * struct) */ +void merkle_update(struct iomt *tree, uint64_t leafidx, hash_t newval, hash_t **old_dep); + +struct iomt *iomt_new(int logleaves); +struct iomt *iomt_new_from_db(void *db, + const char *nodes_table, const char *leaves_table, + const char *key1_name, int key1_val, + const char *key2_name, int key2_val, + int logleaves); +struct iomt *iomt_dup(const struct iomt *tree); +void iomt_free(struct iomt *tree); + +/* Find a leaf with IOMT index `idx' and change its value, propagating + * up the tree. */ +void iomt_update(struct iomt *tree, uint64_t idx, hash_t newval); + +/* Set all the fields of a leaf node (not an IOMT index!) */ +void iomt_update_leaf_full(struct iomt *tree, uint64_t leafidx, + uint64_t new_idx, uint64_t new_next_idx, hash_t new_val); +void iomt_update_leaf_idx(struct iomt *tree, uint64_t leafidx, + uint64_t new_idx); +void iomt_update_leaf_nextidx(struct iomt *tree, uint64_t leafidx, + uint64_t new_next_idx); +void iomt_update_leaf_hash(struct iomt *tree, uint64_t leafidx, + hash_t new_val); + +/* Create an IOMT where the leaves are the hash of file lines */ +struct iomt *iomt_from_lines(const char *filename); + +void iomt_serialize(const struct iomt *tree, + void (*write_fn)(void *userdata, const void *data, size_t len), + void *userdata); + +struct iomt *iomt_deserialize(int (*read_fn)(void *userdata, void *buf, size_t len), + void *userdata); + +void iomt_fill(struct iomt *tree); +void iomt_dump(const struct iomt *tree); + +hash_t iomt_getroot(const struct iomt *tree); + +hash_t iomt_getnode(const struct iomt *tree, int idx); +void iomt_setnode(const struct iomt *tree, int idx, hash_t val); + +struct iomt_node iomt_getleaf(const struct iomt *tree, uint64_t leafidx); + +/* All linear searches... slow! */ +struct iomt_node iomt_find_leaf(const struct iomt *tree, uint64_t idx, uint64_t *leafidx); +struct iomt_node iomt_find_encloser(const struct iomt *tree, uint64_t idx, uint64_t *leafidx); +struct iomt_node iomt_find_leaf_or_encloser(const struct iomt *tree, uint64_t idx, uint64_t *leafidx); +#endif diff --git a/service_provider.c b/service_provider.c index f09badb..62efa09 100644 --- a/service_provider.c +++ b/service_provider.c @@ -11,6 +11,8 @@ #include <sys/types.h> #include <sys/socket.h> +#include <sqlite3.h> + #include "crypto.h" #include "helper.h" #include "service_provider.h" @@ -20,7 +22,10 @@ /* arbitrary */ #define ACL_LOGLEAVES 4 +/* free with free_version */ struct file_version { + uint64_t version; + hash_t kf; /* HMAC(key, file_idx) */ hash_t encrypted_secret; /* XOR'd with HMAC(kf, module secret) */ @@ -32,35 +37,25 @@ struct file_version { /* lines of docker-compose.yml */ struct iomt *composefile; - - /* image .tar file */ - void *contents; - size_t contents_len; }; +/* should be free'd with free_record */ struct file_record { uint64_t idx; uint64_t version; uint64_t counter; - struct iomt *acl; + struct iomt *acl; /* backed by database */ struct tm_cert fr_cert; /* issued by module */ hash_t fr_hmac; - - /* Version numbers start at 1 and are not stored - * explicitly. versions[0] refers to version 1. */ - struct file_version *versions; - int nversions; }; struct service_provider { struct trusted_module *tm; - struct file_record *records; - size_t nrecords; - - struct iomt *iomt; + void *db; /* sqlite3 handle */ + struct iomt *iomt; /* backed by database */ }; /* Generate an EQ certificate for inserting a placeholder with index @@ -133,16 +128,26 @@ struct tm_cert cert_eq(struct service_provider *sp, return tm_cert_equiv(sp->tm, &nu1, nu1_hmac, &nu2, nu2_hmac, encloser, placeholder_nodeidx, hmac_out); } -#if 0 +/* write to file CSAA_FILES/file_idx/version */ +void write_contents(int file_idx, int version, + const void *data, size_t len) +{ +} + +void *read_contents(int file_idx, int version, + size_t *len) +{ + +} + void *db_init(const char *filename) { sqlite3 *db; if(sqlite3_open(filename, &db) != SQLITE_OK) - return null; + return NULL; return db; } -#endif /* leaf count will be 2^logleaves */ struct service_provider *sp_new(const void *key, size_t keylen, int logleaves) @@ -150,7 +155,7 @@ struct service_provider *sp_new(const void *key, size_t keylen, int logleaves) assert(logleaves > 0); struct service_provider *sp = calloc(1, sizeof(*sp)); - //sp->db = db_init("csaa.db"); + sp->db = db_init("csaa.db"); sp->tm = tm_new(key, keylen); @@ -170,7 +175,7 @@ struct service_provider *sp_new(const void *key, size_t keylen, int logleaves) /* generate EQ certificate */ hash_t hmac; struct tm_cert eq = cert_eq(sp, - iomt_get_leaf_by_idx(sp->iomt, i - 1), + iomt_getleaf(sp->iomt, i - 1), i - 1, i, i + 1, &hmac); @@ -192,37 +197,48 @@ struct service_provider *sp_new(const void *key, size_t keylen, int logleaves) static void free_version(struct file_version *ver) { - free(ver->contents); - iomt_free(ver->buildcode); iomt_free(ver->composefile); } static void free_record(struct file_record *rec) { - for(int i = 0; i < rec->nversions; ++i) - free_version(rec->versions + i); - free(rec->versions); iomt_free(rec->acl); } void sp_free(struct service_provider *sp) { - for(int i = 0; i < sp->nrecords; ++i) - free_record(sp->records + i); - free(sp->records); - tm_free(sp->tm); iomt_free(sp->iomt); free(sp); } /* linear search for record given idx */ -static struct file_record *lookup_record(struct service_provider *sp, int idx) +static struct file_record *lookup_record(struct service_provider *sp, uint64_t idx) { - for(int i = 0; i < sp->nrecords; ++i) - if(idx == sp->records[i].idx) - return sp->records + i; + sqlite3 *handle = sp->db; + + const char *sql = "SELECT * FROM FileRecords WHERE Idx = ?1;"; + + sqlite3_stmt *st; + + sqlite3_prepare_v2(handle, sql, -1, &st, 0); + sqlite3_bind_int(st, 1, idx); + + int rc = sqlite3_step(st); + if(rc == SQLITE_ROW) + { + struct file_record *rec = calloc(1, sizeof(struct file_record)); + + rec->idx = sqlite3_column_int(st, 0); + rec->version = sqlite3_column_int(st, 1); + rec->counter = sqlite3_column_int(st, 2); + memcpy(&rec->fr_cert, sqlite3_column_blob(st, 3), sizeof(rec->fr_cert)); + memcpy(&rec->fr_hmac, sqlite3_column_blob(st, 4), sizeof(rec->fr_hmac)); + + int acl_logleaves = sqlite3_column_int(st, 5); + rec->acl = iomt_new_from_db(sp->db, "ACLNodes", "ACLLeaves", acl_logleaves); + } return NULL; } @@ -230,16 +246,124 @@ static struct file_record *lookup_record(struct service_provider *sp, int idx) * avoid copying (O(n) lookup, O(1) insertion)? Eventually this will * be replaced with a SQL backend. We do not check to ensure that * there are no duplicate file indices; that is up to the caller. */ -static void append_record(struct service_provider *sp, const struct file_record *rec) +static void insert_record(struct service_provider *sp, const struct file_record *rec) { - sp->records = realloc(sp->records, sizeof(struct file_record) * ++sp->nrecords); - sp->records[sp->nrecords - 1] = *rec; + sqlite3 *handle = sp->db; + + const char *sql = "INSERT INTO FileRecords VALUES ( ?1, ?2, ?3, ?4, ?5, ?6 )"; + sqlite3_stmt *st; + sqlite3_prepare_v2(handle, sql, -1, &st, 0); + sqlite3_bind_int(st, 1, rec->idx); + sqlite3_bind_int(st, 2, rec->version); + sqlite3_bind_int(st, 3, rec->counter); + sqlite3_bind_blob(st, 4, &rec->fr_cert, sizeof(rec->fr_cert), SQLITE_TRANSIENT); + sqlite3_bind_blob(st, 5, &rec->fr_hmac, sizeof(rec->fr_hmac), SQLITE_TRANSIENT); + sqlite3_bind_int(st, 6, rec->acl->mt_logleaves); + + assert(sqlite3_step(st) == SQLITE_DONE); + + sqlite3_finalize(st); } -static void append_version(struct file_record *rec, const struct file_version *ver) +/* Should we insert sorted (for O(logn) lookup), or just at the end to + * avoid copying (O(n) lookup, O(1) insertion)? Eventually this will + * be replaced with a SQL backend. We do not check to ensure that + * there are no duplicate file indices; that is up to the caller. */ +static void update_record(struct service_provider *sp, + const struct file_record *rec) { - rec->versions = realloc(rec->versions, sizeof(struct file_version) * ++rec->nversions); - rec->versions[rec->nversions - 1] = *ver; + sqlite3 *handle = sp->db; + + const char *sql = "UPDATE FileRecords SET Idx = ?1, Version = ?2, Counter = ?3, Cert = ?4, HMAC = ?5, ACL_logleaves = ?6 WHERE Idx = ?7"; + + sqlite3_stmt *st; + sqlite3_prepare_v2(handle, sql, -1, &st, 0); + sqlite3_bind_int(st, 1, rec->idx); + sqlite3_bind_int(st, 2, rec->version); + sqlite3_bind_int(st, 3, rec->counter); + sqlite3_bind_blob(st, 4, &rec->fr_cert, sizeof(rec->fr_cert), SQLITE_TRANSIENT); + sqlite3_bind_blob(st, 5, &rec->fr_hmac, sizeof(rec->fr_hmac), SQLITE_TRANSIENT); + sqlite3_bind_int(st, 6, rec->acl->mt_logleaves); + sqlite3_bind_int(st, 6, rec->idx); + + assert(sqlite3_step(st) == SQLITE_DONE); + + sqlite3_finalize(st); +} + +static void insert_version(struct service_provider *sp, + const struct file_record *rec, + const struct file_version *ver) +{ + sqlite3 *handle = sp->db; + + const char *sql = "INSERT INTO Versions VALUES ( ?1, ?2, ?3, ?4, ?5, ?6 ?7 ?8 )"; + sqlite3_stmt *st; + sqlite3_prepare_v2(handle, sql, -1, &st, 0); + sqlite3_bind_int(st, 1, rec->idx); + sqlite3_bind_int(st, 2, ver->version); + sqlite3_bind_blob(st, 3, &ver->kf, sizeof(ver->kf), SQLITE_TRANSIENT); + sqlite3_bind_blob(st, 4, &ver->encrypted_secret, sizeof(ver->encrypted_secret), SQLITE_TRANSIENT); + sqlite3_bind_blob(st, 5, &ver->vr_cert, sizeof(ver->vr_cert), SQLITE_TRANSIENT); + sqlite3_bind_blob(st, 6, &ver->vr_hmac, sizeof(ver->vr_hmac), SQLITE_TRANSIENT); + sqlite3_bind_int(st, 7, ver->buildcode->mt_logleaves); + sqlite3_bind_int(st, 8, ver->composefile->mt_logleaves); + + assert(sqlite3_step(st) == SQLITE_DONE); + + sqlite3_finalize(st); +} + +static int count_versions(struct service_provider *sp, + uint64_t file_idx) +{ + sqlite3 *handle = sp->db; + + const char *sql = "SELECT COUNT(*) FROM Versions WHERE FileIdx = ?1;"; + + sqlite3_stmt *st; + + sqlite3_prepare_v2(handle, sql, -1, &st, 0); + sqlite3_bind_int(st, 1, file_idx); + + /* praying it works */ + return sqlite3_column_int(st, 0); +} + +static struct file_version *lookup_version(struct service_provider *sp, + uint64_t file_idx, + uint64_t version) +{ + sqlite3 *handle = sp->db; + + if(!version) + version = count_versions(sp, file_idx); + + const char *sql = "SELECT * FROM Versions WHERE FileIdx = ?1 AND Version = ?2;"; + + sqlite3_stmt *st; + + sqlite3_prepare_v2(handle, sql, -1, &st, 0); + sqlite3_bind_int(st, 1, file_idx); + sqlite3_bind_int(st, 2, version); + + int rc = sqlite3_step(st); + if(rc == SQLITE_ROW) + { + struct file_version *ver = calloc(1, sizeof(struct file_version)); + + ver->version = sqlite3_column_int(st, 1); + memcpy(&ver->kf, sqlite3_column_blob(st, 2), sizeof(ver->kf)); + memcpy(&ver->encrypted_secret, sqlite3_column_blob(st, 3), sizeof(ver->encrypted_secret)); + memcpy(&ver->vr_cert, sqlite3_column_blob(st, 4), sizeof(ver->vr_cert)); + memcpy(&ver->vr_hmac, sqlite3_column_blob(st, 5), sizeof(ver->vr_hmac)); + + int bc_logleaves = sqlite3_column_int(st, 6); + int cf_logleaves = sqlite3_column_int(st, 7); + ver->buildcode = iomt_new_from_db(sp->db, "BCNodes", "BCLeaves", bc_logleaves); + ver->composefile = iomt_new_from_db(sp->db, "CFNodes", "CFLeaves", cf_logleaves); + } + return NULL; } /* This does the majority of the work that actually modifies or @@ -281,11 +405,12 @@ struct tm_cert sp_request(struct service_provider *sp, { /* update the corresponding file record */ struct file_record *rec = lookup_record(sp, fr.fr.idx); + bool need_insert = false; if(!rec) { - rec = calloc(1, sizeof(struct file_record)); need_insert = true; + rec = calloc(1, sizeof(struct file_record)); } rec->idx = fr.fr.idx; @@ -340,22 +465,20 @@ struct tm_cert sp_request(struct service_provider *sp, if(encrypted_contents) { - /* duplicate */ - ver.contents = malloc(contents_len); - memcpy(ver.contents, encrypted_contents, contents_len); - ver.contents_len = contents_len; + /* write to disk */ + write_contents(fr.fr.idx, fr.fr.version, + encrypted_contents, contents_len); } - append_version(rec, &ver); + insert_version(sp, rec, &ver); } if(need_insert) - { - append_record(sp, rec); + insert_record(sp, rec); + else + update_record(sp, rec); - /* append_record will make a copy */ - free(rec); - } + free_record(rec); /* update our tree */ iomt_update(sp->iomt, req->idx, u64_to_hash(fr.fr.counter)); @@ -385,7 +508,7 @@ struct tm_request sp_createfile(struct service_provider *sp, /* Find an empty leaf node */ for(i = 0; i < sp->iomt->mt_leafcount; ++i) { - if(is_zero(iomt_get_leaf_by_idx(sp->iomt, i)->val)) + if(is_zero(iomt_getleaf(sp->iomt, i).val)) break; } @@ -405,7 +528,7 @@ struct tm_request sp_createfile(struct service_provider *sp, struct tm_request req = req_filecreate(sp->tm, user_id, - iomt_get_leaf_by_idx(sp->iomt, i), + iomt_getleaf(sp->iomt, i), file_comp, file_orders, sp->iomt->mt_logleaves); hash_t req_hmac = sign_request(userdata, &req); @@ -597,7 +720,7 @@ struct version_info sp_fileinfo(struct service_provider *sp, /* Placeholder exists. */ rv1 = cert_rv(sp->tm, - iomt_get_leaf_by_idx(sp->iomt, file_idx - 1), + iomt_getleaf(sp->iomt, file_idx - 1), comp, orders, sp->iomt->mt_logleaves, &rv1_hmac, 0, NULL, NULL); @@ -611,7 +734,7 @@ struct version_info sp_fileinfo(struct service_provider *sp, hash_t *comp = merkle_complement(sp->iomt, sp->iomt->mt_leafcount - 1, &orders); cert_rv(sp->tm, - iomt_get_leaf_by_idx(sp->iomt, sp->iomt->mt_leafcount - 1), + iomt_getleaf(sp->iomt, sp->iomt->mt_leafcount - 1), comp, orders, sp->iomt->mt_logleaves, NULL, file_idx, &rv1, &rv1_hmac); @@ -643,22 +766,21 @@ struct version_info sp_fileinfo(struct service_provider *sp, user_id, &rv2_hmac); - struct file_version *ver; - if(rec->nversions > 0) - ver = &rec->versions[version ? version - 1 : rec->nversions - 1]; - else - ver = NULL; + struct file_version *ver = lookup_version(sp, rec->idx, version); if(acl_out) *acl_out = iomt_dup(rec->acl); - return tm_verify_fileinfo(sp->tm, - user_id, - &rv1, rv1_hmac, - &rv2, rv2_hmac, - &rec->fr_cert, rec->fr_hmac, - ver ? &ver->vr_cert : NULL, ver ? ver->vr_hmac : hash_null, - hmac); + struct version_info ret = tm_verify_fileinfo(sp->tm, + user_id, + &rv1, rv1_hmac, + &rv2, rv2_hmac, + &rec->fr_cert, rec->fr_hmac, + ver ? &ver->vr_cert : NULL, ver ? ver->vr_hmac : hash_null, + hmac); + free_version(ver); + + return ret; } /* This file retrieves the file given by file_idx for a given @@ -680,7 +802,7 @@ void *sp_retrieve_file(struct service_provider *sp, { struct file_record *rec = lookup_record(sp, file_idx); - if(!rec || !rec->nversions) + if(!rec || count_versions(sp, file_idx)) { /* Newly created file, no contents. We don't bother to set * *encrypted_secret or *len. Or, file does not exist. */ @@ -688,7 +810,10 @@ void *sp_retrieve_file(struct service_provider *sp, return NULL; } - struct file_version *ver = &rec->versions[version ? version - 1 : rec->nversions - 1]; + if(!version) + version = count_versions(sp, file_idx); + + struct file_version *ver = lookup_version(sp, file_idx, version); hash_t rv1_hmac, rv2_hmac; struct tm_cert rv1 = cert_rv_by_idx(sp->tm, sp->iomt, file_idx, &rv1_hmac); @@ -696,6 +821,7 @@ void *sp_retrieve_file(struct service_provider *sp, if(hash_to_u64(rv2.rv.val) < 1) { + free_version(ver); /* no permissions; don't return file contents */ return NULL; } @@ -714,12 +840,7 @@ void *sp_retrieve_file(struct service_provider *sp, if(kf) *kf = ver->kf; - if(len) - *len = ver->contents_len; - - /* duplicate */ - void *ret = malloc(ver->contents_len); - memcpy(ret, ver->contents, ver->contents_len); + void *ret = read_contents(file_idx, version, len); /* duplicate compose and build files */ if(buildcode) @@ -727,6 +848,8 @@ void *sp_retrieve_file(struct service_provider *sp, if(composefile) *composefile = iomt_dup(ver->composefile); + free_version(ver); + return ret; } diff --git a/testcreate.sh b/testcreate.sh index e95f04a..457d75d 100755 --- a/testcreate.sh +++ b/testcreate.sh @@ -1,5 +1,5 @@ #!/bin/bash for i in $(seq 1 1000) do - ./client -u 1 -k a create > /dev/null + ./client -u 1 -k a create done diff --git a/testmodify.sh b/testmodify.sh index 714f3a7..88ca9d7 100755 --- a/testmodify.sh +++ b/testmodify.sh @@ -1,6 +1,6 @@ #!/bin/bash -./client -u 1 -k a create > /dev/null +./client -u 1 -k a create for i in $(seq 1 1000) do - ./client -u 1 -k a modifyfile -f 1 -i container1/hello-world.tar > /dev/null + ./client -u 1 -k a modifyfile -f 1 -i container1/hello-world.tar done diff --git a/trusted_module.h b/trusted_module.h index 5333032..f764ad0 100644 --- a/trusted_module.h +++ b/trusted_module.h @@ -6,6 +6,7 @@ #include <stddef.h> #include "crypto.h" +#include "iomt.h" struct trusted_module; struct tm_request; |