aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Makefile6
-rw-r--r--client.c1
-rw-r--r--crypto.c359
-rw-r--r--crypto.h77
-rw-r--r--helper.c6
-rw-r--r--iomt.c384
-rw-r--r--iomt.h102
-rw-r--r--service_provider.c269
-rwxr-xr-xtestcreate.sh2
-rwxr-xr-xtestmodify.sh4
-rw-r--r--trusted_module.h1
11 files changed, 698 insertions, 513 deletions
diff --git a/Makefile b/Makefile
index f439450..91e294a 100644
--- a/Makefile
+++ b/Makefile
@@ -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
diff --git a/client.c b/client.c
index 278c8d1..bc947cd 100644
--- a/client.c
+++ b/client.c
@@ -22,6 +22,7 @@
#define CLIENT
#include "crypto.h"
+#include "iomt.h"
#include "service_provider.h"
#include "trusted_module.h"
#include "test.h"
diff --git a/crypto.c b/crypto.c
index ae744ae..7fb667f 100644
--- a/crypto.c
+++ b/crypto.c
@@ -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;
diff --git a/crypto.h b/crypto.h
index 65ead1f..b14dd45 100644
--- a/crypto.h
+++ b/crypto.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
diff --git a/helper.c b/helper.c
index 15ae695..3310e94 100644
--- a/helper.c
+++ b/helper.c
@@ -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;
diff --git a/iomt.c b/iomt.c
new file mode 100644
index 0000000..c6fff04
--- /dev/null
+++ b/iomt.c
@@ -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");
+}
diff --git a/iomt.h b/iomt.h
new file mode 100644
index 0000000..8ccd0dc
--- /dev/null
+++ b/iomt.h
@@ -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;