diff options
-rw-r--r-- | Makefile | 2 | ||||
-rw-r--r-- | iomt.c | 320 | ||||
-rw-r--r-- | iomt.h | 11 | ||||
-rw-r--r-- | main.c | 2 | ||||
-rw-r--r-- | service_provider.c | 182 | ||||
-rw-r--r-- | service_provider.h | 2 | ||||
-rwxr-xr-x | testcreate.sh | 4 | ||||
-rwxr-xr-x | testmodify.sh | 4 |
8 files changed, 316 insertions, 211 deletions
@@ -1,5 +1,5 @@ all: client server Makefile -CFLAGS = -g -Wall -O0 -lsqlite3 +CFLAGS = -g -Wall -O3 -lsqlite3 client: client.o crypto.o test.o iomt.o cc -o $@ $^ -lcrypto $(CFLAGS) @@ -21,30 +21,8 @@ hash_t iomt_getnode(const struct iomt *tree, int idx) return tree->mem.mt_nodes[idx]; else { - sqlite3 *handle = tree->db.db; - - char sql[1000]; - if(tree->db.key1_name) - { - if(tree->db.key2_name) - { - snprintf(sql, sizeof(sql), "SELECT Val FROM %s WHERE %s = ?3 AND %s = ?5 AND NodeIdx = ?6;", - tree->db.nodes_table, - tree->db.key1_name, - tree->db.key2_name); - } - else - snprintf(sql, sizeof(sql), "SELECT Val FROM %s WHERE %s = ?3 AND NodeIdx = ?6;", - tree->db.nodes_table, - tree->db.key1_name); - } - else - snprintf(sql, sizeof(sql), "SELECT Val FROM %s WHERE NodeIdx = ?6;", - tree->db.nodes_table); - - sqlite3_stmt *st; - - sqlite3_prepare_v2(handle, sql, -1, &st, 0); + sqlite3_stmt *st = tree->db.getnode; + sqlite3_reset(st); if(tree->db.key1_name) { @@ -80,32 +58,13 @@ void iomt_setnode(const struct iomt *tree, int idx, hash_t val) tree->mem.mt_nodes[idx] = val; else { - printf("Setting node idx = %d in %s\n", idx, tree->db.nodes_table); + //printf("Setting node idx = %d in %s\n", idx, tree->db.nodes_table); sqlite3 *handle = tree->db.db; - char sql[1000]; - if(tree->db.key1_name) - { - if(tree->db.key2_name) - { - snprintf(sql, sizeof(sql), "UPDATE %s SET Val = ?2 WHERE %s = ?4 AND %s = ?6 AND NodeIdx = ?7;", - tree->db.nodes_table, - tree->db.key1_name, - tree->db.key2_name); - } - else - snprintf(sql, sizeof(sql), "UPDATE %s SET Val = ?2 WHERE %s = ?4 AND NodeIdx = ?7;", - tree->db.nodes_table, - tree->db.key1_name); - } - else - snprintf(sql, sizeof(sql), "UPDATE %s SET Val = ?2 WHERE NodeIdx = ?7;", - tree->db.nodes_table); + sqlite3_stmt *st = tree->db.updatenode; + sqlite3_reset(st); - sqlite3_stmt *st; - - sqlite3_prepare_v2(handle, sql, -1, &st, 0); sqlite3_bind_blob(st, 2, &val, sizeof(val), SQLITE_TRANSIENT); if(tree->db.key1_name) @@ -124,29 +83,11 @@ void iomt_setnode(const struct iomt *tree, int idx, hash_t val) int changes = sqlite3_changes(handle); - sqlite3_finalize(st); - /* Failure, likely because node doesn't exist */ if(rc != SQLITE_DONE || !changes) { - printf("Update failed, (%s) inserting...\n", sqlite3_errmsg(handle)); - if(tree->db.key1_name) - { - if(tree->db.key2_name) - snprintf(sql, sizeof(sql), "INSERT INTO %s ( NodeIdx, Val, %s, %s ) VALUES ( ?4, ?5, ?6, ?7 );", - tree->db.nodes_table, - tree->db.key1_name, - tree->db.key2_name); - else - snprintf(sql, sizeof(sql), "INSERT INTO %s ( NodeIdx, Val, %s ) VALUES ( ?4, ?5, ?6 );", - tree->db.nodes_table, - tree->db.key1_name); - } - else - snprintf(sql, sizeof(sql), "INSERT INTO %s ( NodeIdx, Val ) VALUES ( ?4, ?5 );", - tree->db.nodes_table); - - sqlite3_prepare_v2(handle, sql, -1, &st, 0); + st = tree->db.insertnode; + sqlite3_reset(st); sqlite3_bind_int(st, 4, idx); sqlite3_bind_blob(st, 5, &val, sizeof(val), SQLITE_TRANSIENT); @@ -160,10 +101,12 @@ void iomt_setnode(const struct iomt *tree, int idx, hash_t val) if(sqlite3_step(st) != SQLITE_DONE) { - printf("Failed 1: %s\n", sqlite3_errmsg(tree->db.db)); + //printf("Failed 1: %s\n", sqlite3_errmsg(tree->db.db)); } - - sqlite3_finalize(st); + } + else + { + //printf("Successfully updated node %d\n", idx); } } } @@ -174,32 +117,8 @@ struct iomt_node iomt_getleaf(const struct iomt *tree, uint64_t leafidx) return tree->mem.mt_leaves[leafidx]; else { - sqlite3 *handle = tree->db.db; - - char sql[1000]; - if(tree->db.key1_name) - { - if(tree->db.key2_name) - { - snprintf(sql, sizeof(sql), "SELECT Idx, NextIdx, Val FROM %s WHERE %s = ?3 AND %s = ?5 AND LeafIdx = ?6;", - tree->db.leaves_table, - tree->db.key1_name, - tree->db.key2_name); - } - else - { - snprintf(sql, sizeof(sql), "SELECT Idx, NextIdx, Val FROM %s WHERE %s = ?3 AND LeafIdx = ?6;", - tree->db.leaves_table, - tree->db.key1_name); - } - } - else - snprintf(sql, sizeof(sql), "SELECT Idx, NextIdx, Val FROM %s WHERE LeafIdx = ?6;", - tree->db.leaves_table); - - sqlite3_stmt *st; - - sqlite3_prepare_v2(handle, sql, -1, &st, 0); + sqlite3_stmt *st = tree->db.getleaf; + sqlite3_reset(st); if(tree->db.key1_name) { @@ -226,8 +145,8 @@ struct iomt_node iomt_getleaf(const struct iomt *tree, uint64_t leafidx) } else { - printf("Failed 2: %s\n", sqlite3_errmsg(tree->db.db)); - printf("Failed to look up leaf %d in %s\n", leafidx, tree->db.leaves_table); + //printf("Failed 2: %s\n", sqlite3_errmsg(tree->db.db)); + //printf("Failed to look up leaf %lu in %s\n", leafidx, tree->db.leaves_table); return node_null; } } @@ -239,36 +158,13 @@ void iomt_setleaf(struct iomt *tree, uint64_t leafidx, struct iomt_node val) tree->mem.mt_leaves[leafidx] = val; else { - printf("Setting leaf idx = %d in %s\n", leafidx, tree->db.leaves_table); + //printf("Setting leaf idx = %lu in %s\n", leafidx, tree->db.leaves_table); sqlite3 *handle = tree->db.db; - char sql[1000]; - if(tree->db.key1_name) - { - if(tree->db.key2_name) - { - snprintf(sql, sizeof(sql), "UPDATE %s SET Idx = ?2, NextIdx = ?3, Val = ?4 WHERE %s = ?6 AND %s = ?8 AND LeafIdx = ?9;", - tree->db.leaves_table, - tree->db.key1_name, - tree->db.key2_name); - } - else - { - snprintf(sql, sizeof(sql), "UPDATE %s SET Idx = ?2, NextIdx = ?3, Val = ?4 WHERE %s = ?6 AND LeafIdx = ?9;", - tree->db.leaves_table, - tree->db.key1_name); - } - } - else - snprintf(sql, sizeof(sql), "UPDATE %s SET Idx = ?2, NextIdx = ?3, Val = ?4 WHERE LeafIdx = ?9;", - tree->db.leaves_table); - - printf("Statement is %s\n", sql); - - sqlite3_stmt *st; + sqlite3_stmt *st = tree->db.updateleaf; + sqlite3_reset(st); - sqlite3_prepare_v2(handle, sql, -1, &st, 0); sqlite3_bind_int(st, 2, val.idx); sqlite3_bind_int(st, 3, val.next_idx); sqlite3_bind_blob(st, 4, &val.val, sizeof(val.val), SQLITE_TRANSIENT); @@ -289,31 +185,11 @@ void iomt_setleaf(struct iomt *tree, uint64_t leafidx, struct iomt_node val) int changes = sqlite3_changes(handle); - sqlite3_finalize(st); - /* Failure, likely because node doesn't exist */ if(rc != SQLITE_DONE || !changes) { - printf("Update failed (%s), inserting...\n", sqlite3_errmsg(handle)); - - if(tree->db.key1_name) - { - if(tree->db.key2_name) - snprintf(sql, sizeof(sql), "INSERT INTO %s ( LeafIdx, Idx, NextIdx, Val, %s, %s ) VALUES ( ?5, ?6, ?7, ?8, ?9, ?10 );", - tree->db.leaves_table, - tree->db.key1_name, - tree->db.key2_name); - else - snprintf(sql, sizeof(sql), "INSERT INTO %s ( LeafIdx, Idx, NextIdx, Val, %s ) VALUES ( ?5, ?6, ?7, ?8, ?9 );", - tree->db.leaves_table, - tree->db.key1_name); - } - else - snprintf(sql, sizeof(sql), "INSERT INTO %s ( LeafIdx, Idx, NextIdx, Val ) VALUES ( ?5, ?6, ?7, ?8 );", - tree->db.leaves_table); - - - sqlite3_prepare_v2(handle, sql, -1, &st, 0); + st = tree->db.insertleaf; + sqlite3_reset(st); if(tree->db.key1_name) { @@ -335,9 +211,7 @@ void iomt_setleaf(struct iomt *tree, uint64_t leafidx, struct iomt_node val) printf("Failed 3: %s\n", sqlite3_errmsg(handle)); } - printf("Successfully inserted (%s)\n", sqlite3_errmsg(handle)); - - sqlite3_finalize(st); + //printf("Successfully inserted (%s)\n", sqlite3_errmsg(handle)); } } } @@ -436,6 +310,7 @@ hash_t iomt_getroot(const struct iomt *tree) } /* find a node with given idx */ +/* TODO: replace with database update */ 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) @@ -443,7 +318,7 @@ struct iomt_node iomt_find_leaf(const struct iomt *tree, uint64_t idx, uint64_t { if(leafidx) *leafidx = i; - return tree->mem.mt_leaves[i]; + return iomt_getleaf(tree, i); } return node_null; } @@ -455,7 +330,7 @@ struct iomt_node iomt_find_encloser(const struct iomt *tree, uint64_t idx, uint6 { if(leafidx) *leafidx = i; - return tree->mem.mt_leaves[i]; + return iomt_getleaf(tree, i); } return node_null; } @@ -469,7 +344,7 @@ struct iomt_node iomt_find_leaf_or_encloser(const struct iomt *tree, uint64_t id { if(leafidx) *leafidx = i; - return tree->mem.mt_leaves[i]; + return iomt_getleaf(tree, i); } } return node_null; @@ -478,7 +353,7 @@ struct iomt_node iomt_find_leaf_or_encloser(const struct iomt *tree, uint64_t id void iomt_update(struct iomt *tree, uint64_t idx, hash_t newval) { /* update the leaf first, then use merkle_update */ - uint64_t leafidx; + uint64_t leafidx = 0; struct iomt_node leaf = iomt_find_leaf(tree, idx, &leafidx); leaf.val = newval; iomt_setleaf(tree, leafidx, leaf); @@ -566,13 +441,134 @@ struct iomt *iomt_new_from_db(void *db, tree->db.key2_name = key2_name; tree->db.key2_val = key2_val; + /* compile statements now to save time */ + char sql[1000]; + + /* TODO: refactor! */ + + if(tree->db.key1_name) + { + if(tree->db.key2_name) + { + snprintf(sql, sizeof(sql), "SELECT Val FROM %s WHERE %s = ?3 AND %s = ?5 AND NodeIdx = ?6;", + tree->db.nodes_table, + tree->db.key1_name, + tree->db.key2_name); + sqlite3_prepare_v2(db, sql, -1, &tree->db.getnode, 0); + + snprintf(sql, sizeof(sql), "UPDATE %s SET Val = ?2 WHERE %s = ?4 AND %s = ?6 AND NodeIdx = ?7;", + tree->db.nodes_table, + tree->db.key1_name, + tree->db.key2_name); + sqlite3_prepare_v2(db, sql, -1, &tree->db.updatenode, 0); + snprintf(sql, sizeof(sql), "INSERT INTO %s ( NodeIdx, Val, %s, %s ) VALUES ( ?4, ?5, ?6, ?7 );", + tree->db.nodes_table, + tree->db.key1_name, + tree->db.key2_name); + sqlite3_prepare_v2(db, sql, -1, &tree->db.insertnode, 0); + snprintf(sql, sizeof(sql), "SELECT Idx, NextIdx, Val FROM %s WHERE %s = ?3 AND %s = ?5 AND LeafIdx = ?6;", + tree->db.leaves_table, + tree->db.key1_name, + tree->db.key2_name); + sqlite3_prepare_v2(db, sql, -1, &tree->db.getleaf, 0); + snprintf(sql, sizeof(sql), "UPDATE %s SET Idx = ?2, NextIdx = ?3, Val = ?4 WHERE %s = ?6 AND %s = ?8 AND LeafIdx = ?9;", + tree->db.leaves_table, + tree->db.key1_name, + tree->db.key2_name); + sqlite3_prepare_v2(db, sql, -1, &tree->db.updateleaf, 0); + snprintf(sql, sizeof(sql), "INSERT INTO %s ( LeafIdx, Idx, NextIdx, Val, %s, %s ) VALUES ( ?5, ?6, ?7, ?8, ?9, ?10 );", + tree->db.leaves_table, + tree->db.key1_name, + tree->db.key2_name); + sqlite3_prepare_v2(db, sql, -1, &tree->db.insertleaf, 0); + } + else + { + snprintf(sql, sizeof(sql), "SELECT Val FROM %s WHERE %s = ?3 AND NodeIdx = ?6;", + tree->db.nodes_table, + tree->db.key1_name); + sqlite3_prepare_v2(db, sql, -1, &tree->db.getnode, 0); + snprintf(sql, sizeof(sql), "UPDATE %s SET Val = ?2 WHERE %s = ?4 AND NodeIdx = ?7;", + tree->db.nodes_table, + tree->db.key1_name); + sqlite3_prepare_v2(db, sql, -1, &tree->db.updatenode, 0); + snprintf(sql, sizeof(sql), "INSERT INTO %s ( NodeIdx, Val, %s ) VALUES ( ?4, ?5, ?6 );", + tree->db.nodes_table, + tree->db.key1_name); + sqlite3_prepare_v2(db, sql, -1, &tree->db.insertnode, 0); + snprintf(sql, sizeof(sql), "SELECT Idx, NextIdx, Val FROM %s WHERE %s = ?3 AND LeafIdx = ?6;", + tree->db.leaves_table, + tree->db.key1_name); + sqlite3_prepare_v2(db, sql, -1, &tree->db.getleaf, 0); + snprintf(sql, sizeof(sql), "UPDATE %s SET Idx = ?2, NextIdx = ?3, Val = ?4 WHERE %s = ?6 AND LeafIdx = ?9;", + tree->db.leaves_table, + tree->db.key1_name); + sqlite3_prepare_v2(db, sql, -1, &tree->db.updateleaf, 0); + snprintf(sql, sizeof(sql), "INSERT INTO %s ( LeafIdx, Idx, NextIdx, Val, %s ) VALUES ( ?5, ?6, ?7, ?8, ?9 );", + tree->db.leaves_table, + tree->db.key1_name); + sqlite3_prepare_v2(db, sql, -1, &tree->db.insertleaf, 0); + } + } + else + { + snprintf(sql, sizeof(sql), "SELECT Val FROM %s WHERE NodeIdx = ?6;", + tree->db.nodes_table); + sqlite3_prepare_v2(db, sql, -1, &tree->db.getnode, 0); + snprintf(sql, sizeof(sql), "UPDATE %s SET Val = ?2 WHERE NodeIdx = ?7;", + tree->db.nodes_table); + sqlite3_prepare_v2(db, sql, -1, &tree->db.updatenode, 0); + snprintf(sql, sizeof(sql), "INSERT INTO %s ( NodeIdx, Val ) VALUES ( ?4, ?5 );", + tree->db.nodes_table); + sqlite3_prepare_v2(db, sql, -1, &tree->db.insertnode, 0); + snprintf(sql, sizeof(sql), "SELECT Idx, NextIdx, Val FROM %s WHERE LeafIdx = ?6;", + tree->db.leaves_table); + sqlite3_prepare_v2(db, sql, -1, &tree->db.getleaf, 0); + snprintf(sql, sizeof(sql), "UPDATE %s SET Idx = ?2, NextIdx = ?3, Val = ?4 WHERE LeafIdx = ?9;", + tree->db.leaves_table); + sqlite3_prepare_v2(db, sql, -1, &tree->db.updateleaf, 0); + snprintf(sql, sizeof(sql), "INSERT INTO %s ( LeafIdx, Idx, NextIdx, Val ) VALUES ( ?5, ?6, ?7, ?8 );", + tree->db.leaves_table); + sqlite3_prepare_v2(db, sql, -1, &tree->db.insertleaf, 0); + } + return tree; } +/* make a copy of the IOMT with database backing (there will be no + * pointer semantics between the two trees when this function + * returns) */ +struct iomt *iomt_dup_in_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, + const struct iomt *oldtree) +{ + struct iomt *newtree = iomt_new_from_db(db, nodes_table, leaves_table, + key1_name, key1_val, + key2_name, key2_val, + oldtree->mt_logleaves); + + /* copy nodes, leaves (we do not recalculate the tree) */ + for(int i = 0; i < newtree->mt_leafcount; ++i) + iomt_setleaf(newtree, i, iomt_getleaf(oldtree, i)); + + for(int i = 0; i < 2 * newtree->mt_leafcount - 1; ++i) + iomt_setnode(newtree, i, iomt_getnode(oldtree, i)); + + return newtree; +} + +/* produces a new IOMT with no relation with the old one (no pointer + * semantics) */ struct iomt *iomt_dup(const struct iomt *tree) { if(!tree) return NULL; + + if(!tree->in_memory) + assert(false); + struct iomt *newtree = calloc(1, sizeof(struct iomt)); newtree->mt_leafcount = tree->mt_leafcount; newtree->mt_logleaves = tree->mt_logleaves; @@ -649,10 +645,13 @@ struct iomt *iomt_deserialize(int (*read_fn)(void *userdata, void *buf, size_t l void iomt_free(struct iomt *tree) { - if(tree && tree->in_memory) + if(tree) { - free(tree->mem.mt_nodes); - free(tree->mem.mt_leaves); + if(tree->in_memory) + { + free(tree->mem.mt_nodes); + free(tree->mem.mt_leaves); + } free(tree); } } @@ -712,17 +711,18 @@ struct iomt *iomt_from_lines(const char *filename) void iomt_dump(const struct iomt *tree) { - if(tree && tree->in_memory) + if(tree) { for(int i = 0; i < tree->mt_leafcount; ++i) { + struct iomt_node node = iomt_getleaf(tree, i); printf("(%lu, %s, %lu)%s", - tree->mem.mt_leaves[i].idx, - hash_format(tree->mem.mt_leaves[i].val, 4).str, - tree->mem.mt_leaves[i].next_idx, + node.idx, + hash_format(node.val, 4).str, + node.next_idx, (i == tree->mt_leafcount - 1) ? "\n" : ", "); } } else - printf("(empty IOMT)\n"); + printf("(null IOMT)\n"); } @@ -1,6 +1,7 @@ #ifndef CSAA_IOMT_H #define CSAA_IOMT_H #include "crypto.h" +#include <sqlite3.h> struct iomt_node { uint64_t idx, next_idx; /* idx cannot be zero */ @@ -37,6 +38,9 @@ struct iomt { * not NULL) key2_name = key2_val */ const char *key1_name, *key2_name; int key1_val, key2_val; + + sqlite3_stmt *getnode, *updatenode, *insertnode; + sqlite3_stmt *getleaf, *updateleaf, *insertleaf; } db; struct { hash_t *mt_nodes; /* this has 2 * mt_leafcount - 1 elements. Note @@ -66,7 +70,14 @@ struct iomt *iomt_new_from_db(void *db, const char *key1_name, int key1_val, const char *key2_name, int key2_val, int logleaves); + struct iomt *iomt_dup(const struct iomt *tree); +struct iomt *iomt_dup_in_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, + const struct iomt *oldtree); + void iomt_free(struct iomt *tree); /* Find a leaf with IOMT index `idx' and change its value, propagating @@ -46,7 +46,7 @@ void run_tests(void) int main() { - run_tests(); + //run_tests(); const char *socket_name = "socket"; int sockfd; diff --git a/service_provider.c b/service_provider.c index 2e119b6..074ab3d 100644 --- a/service_provider.c +++ b/service_provider.c @@ -8,8 +8,9 @@ #include <stdio.h> #include <unistd.h> -#include <sys/types.h> #include <sys/socket.h> +#include <sys/stat.h> +#include <sys/types.h> #include <sqlite3.h> @@ -22,6 +23,8 @@ /* arbitrary */ #define ACL_LOGLEAVES 4 +#define MAX_PATH 260 + /* free with free_version */ struct file_version { uint64_t version; @@ -54,6 +57,8 @@ struct file_record { struct service_provider { struct trusted_module *tm; + const char *data_dir; + void *db; /* sqlite3 handle */ struct iomt *iomt; /* backed by database */ }; @@ -128,16 +133,54 @@ 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); } -/* write to file CSAA_FILES/file_idx/version */ -void write_contents(int file_idx, int version, +/* write to file data_dir/file_idx/version */ +void write_contents(const struct service_provider *sp, + int file_idx, int version, const void *data, size_t len) { + mkdir(sp->data_dir, 0755); + + char dirname[MAX_PATH]; + snprintf(dirname, sizeof(dirname), "%s/%d", sp->data_dir, file_idx); + + mkdir(dirname, 0755); + + char filename[MAX_PATH]; + snprintf(filename, sizeof(filename), "%s/%d/%d", sp->data_dir, file_idx, version); + + FILE *f = fopen(filename, "w"); + + fwrite(data, 1, len, f); + + fclose(f); +} + +size_t file_len(FILE *f) +{ + off_t orig = ftell(f); + fseek(f, 0, SEEK_END); + off_t len = ftell(f); + fseek(f, orig, SEEK_SET); + + return (size_t)len; } -void *read_contents(int file_idx, int version, +void *read_contents(const struct service_provider *sp, + int file_idx, int version, size_t *len) { + char filename[MAX_PATH]; + snprintf(filename, sizeof(filename), "%s/%d/%d", sp->data_dir, file_idx, version); + FILE *f = fopen(filename, "r"); + + *len = file_len(f); + + void *buf = malloc(*len); + fread(buf, 1, *len, f); + + fclose(f); + return buf; } void *db_init(const char *filename) @@ -146,11 +189,26 @@ void *db_init(const char *filename) if(sqlite3_open(filename, &db) != SQLITE_OK) return NULL; + sqlite3_exec(db, "PRAGMA synchronous = 0;", 0, 0, 0); + sqlite3_exec(db, "PRAGMA journal_mode = memory;", 0, 0, 0); + return db; } +void begin_transaction(void *db) +{ + sqlite3 *handle = db; + sqlite3_exec(handle, "BEGIN;", 0, 0, 0); +} + +void commit_transaction(void *db) +{ + sqlite3 *handle = db; + sqlite3_exec(handle, "COMMIT;", 0, 0, 0); +} + /* leaf count will be 2^logleaves */ -struct service_provider *sp_new(const void *key, size_t keylen, int logleaves) +struct service_provider *sp_new(const void *key, size_t keylen, int logleaves, const char *data_dir) { assert(logleaves > 0); struct service_provider *sp = calloc(1, sizeof(*sp)); @@ -165,6 +223,10 @@ struct service_provider *sp_new(const void *key, size_t keylen, int logleaves) NULL, 0, logleaves); + begin_transaction(sp->db); + + sp->data_dir = data_dir; + /* The trusted module initializes itself with a single placeholder * node (1,0,1). We first update our list of IOMT leaves. Then we * insert our desired number of nodes by using EQ certificates to @@ -193,28 +255,50 @@ struct service_provider *sp_new(const void *key, size_t keylen, int logleaves) * next node, if any */ iomt_update_leaf_full(sp->iomt, i, i + 1, 1, hash_null); +#if 0 + if(i % 10 == 0) + { + commit_transaction(sp->db); + begin_transaction(sp->db); + } +#endif + assert(tm_set_equiv_root(sp->tm, &eq, hmac)); + printf("%d\n", i); } + commit_transaction(sp->db); + return sp; } static void free_version(struct file_version *ver) { - iomt_free(ver->buildcode); - iomt_free(ver->composefile); + if(ver) + { + iomt_free(ver->buildcode); + iomt_free(ver->composefile); + free(ver); + } } static void free_record(struct file_record *rec) { - iomt_free(rec->acl); + if(rec) + { + iomt_free(rec->acl); + free(rec); + } } void sp_free(struct service_provider *sp) { - tm_free(sp->tm); - iomt_free(sp->iomt); - free(sp); + if(sp) + { + tm_free(sp->tm); + iomt_free(sp->iomt); + free(sp); + } } /* linear search for record given idx */ @@ -246,7 +330,10 @@ static struct file_record *lookup_record(struct service_provider *sp, uint64_t i "FileIdx", idx, NULL, 0, acl_logleaves); + + return rec; } + //printf("Failed to find file record with index %lu (%s), ret %d\n", idx, sqlite3_errmsg(handle), rc); return NULL; } @@ -256,9 +343,11 @@ static struct file_record *lookup_record(struct service_provider *sp, uint64_t i * there are no duplicate file indices; that is up to the caller. */ static void insert_record(struct service_provider *sp, const struct file_record *rec) { + //printf("Inserting record %lu\n", rec->idx); + sqlite3 *handle = sp->db; - const char *sql = "INSERT INTO FileRecords VALUES ( ?1, ?2, ?3, ?4, ?5, ?6 )"; + 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); @@ -282,7 +371,7 @@ static void update_record(struct service_provider *sp, { 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"; + const char *sql = "UPDATE FileRecords SET Idx = ?1, Ver = ?2, Ctr = ?3, Cert = ?4, HMAC = ?5, ACL_logleaves = ?6 WHERE Idx = ?7;"; sqlite3_stmt *st; sqlite3_prepare_v2(handle, sql, -1, &st, 0); @@ -305,7 +394,7 @@ static void insert_version(struct service_provider *sp, { sqlite3 *handle = sp->db; - const char *sql = "INSERT INTO Versions VALUES ( ?1, ?2, ?3, ?4, ?5, ?6 ?7 ?8 )"; + 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); @@ -314,10 +403,16 @@ static void insert_version(struct service_provider *sp, 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_bind_int(st, 7, ver->buildcode ? ver->buildcode->mt_logleaves : -1); + + sqlite3_bind_int(st, 8, ver->composefile ? ver->composefile->mt_logleaves : -1); + + int rc = sqlite3_step(st); + if(rc != SQLITE_DONE) + { + printf("Failed (%s)\n", sqlite3_errmsg(handle)); + } sqlite3_finalize(st); } @@ -380,6 +475,7 @@ static struct file_version *lookup_version(struct service_provider *sp, "FileIdx", file_idx, "Version", version, cf_logleaves); + return ver; } return NULL; } @@ -399,8 +495,9 @@ static struct file_version *lookup_version(struct service_provider *sp, * HMAC(encryption secret, file index). * * If the request is to either modify the ACL or create a file (which - * is essentially an ACL update), the ACL will be set to - * new_acl. `new_acl' must be in persistent storage. */ + * is essentially an ACL update), the ACL will be set to new_acl. This + * function will make a copy of new_acl, so it can safely be freed + * after calling this function. */ struct tm_cert sp_request(struct service_provider *sp, const struct tm_request *req, hash_t req_hmac, hash_t *hmac_out, @@ -427,8 +524,8 @@ struct tm_cert sp_request(struct service_provider *sp, bool need_insert = false; if(!rec) { - need_insert = true; rec = calloc(1, sizeof(struct file_record)); + need_insert = true; } rec->idx = fr.fr.idx; @@ -441,9 +538,14 @@ struct tm_cert sp_request(struct service_provider *sp, /* check that the passed value matches the calculated root */ assert(hash_equals(req->val, iomt_getroot(new_acl))); - /* update our ACL */ iomt_free(rec->acl); - rec->acl = iomt_dup(new_acl); + + /* copy the ACL into our database tables */ + rec->acl = iomt_dup_in_db(sp->db, + "ACLNodes", "ACLLeaves", + "FileIdx", fr.fr.idx, + NULL, 0, + new_acl); } if(rec->version != fr.fr.version) @@ -472,6 +574,7 @@ struct tm_cert sp_request(struct service_provider *sp, ver.encrypted_secret = hash_null; } + ver.version = fr.fr.version; ver.vr_cert = vr; ver.vr_hmac = vr_hmac; @@ -484,7 +587,7 @@ struct tm_cert sp_request(struct service_provider *sp, if(encrypted_contents) { /* write to disk */ - write_contents(fr.fr.idx, fr.fr.version, + write_contents(sp, fr.fr.idx, fr.fr.version, encrypted_contents, contents_len); } @@ -512,6 +615,9 @@ struct tm_cert sp_request(struct service_provider *sp, if(ack_hmac_out) *ack_hmac_out = ack_hmac; + if(is_zero(*ack_hmac_out)) + printf("Failed: %s\n", tm_geterror()); + return fr; } @@ -541,7 +647,7 @@ struct tm_request sp_createfile(struct service_provider *sp, struct iomt *acl = iomt_new_from_db(sp->db, "ACLNodes", "ACLLeaves", - "FileIdx", i, + "FileIdx", iomt_getleaf(sp->iomt, i).idx, NULL, 0, ACL_LOGLEAVES); @@ -567,13 +673,12 @@ struct tm_request sp_createfile(struct service_provider *sp, NULL, 0, acl); - iomt_free(acl); - free(file_comp); free(file_orders); if(fr_cert.type == FR) return req; + return req_null; } @@ -825,7 +930,7 @@ void *sp_retrieve_file(struct service_provider *sp, { struct file_record *rec = lookup_record(sp, file_idx); - if(!rec || count_versions(sp, file_idx)) + 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. */ @@ -863,7 +968,7 @@ void *sp_retrieve_file(struct service_provider *sp, if(kf) *kf = ver->kf; - void *ret = read_contents(file_idx, version, len); + void *ret = read_contents(sp, file_idx, version, len); /* duplicate compose and build files */ if(buildcode) @@ -923,7 +1028,6 @@ static void sp_handle_client(struct service_provider *sp, int cl) user_req.modify_acl.file_idx, acl, &ack_hmac); - iomt_free(acl); if(write(cl, &ack_hmac, sizeof(ack_hmac)) != sizeof(ack_hmac)) return; break; @@ -1033,7 +1137,7 @@ int sp_main(int sockfd) signal(SIGPIPE, SIG_IGN); int logleaves = 10; - struct service_provider *sp = sp_new("a", 1, logleaves); + struct service_provider *sp = sp_new("a", 1, logleaves, "files"); while(1) { @@ -1064,7 +1168,7 @@ void sp_test(void) printf("Initializing IOMT with %llu nodes.\n", 1ULL << logleaves); clock_t start = clock(); - struct service_provider *sp = sp_new("a", 1, logleaves); + struct service_provider *sp = sp_new("a", 1, logleaves, "files"); clock_t stop = clock(); printf("%.1f placeholder insertions per second\n", (double)(1ULL << logleaves) * CLOCKS_PER_SEC / (stop - start)); @@ -1086,7 +1190,7 @@ void sp_test(void) hash_t correct_root = merkle_parent(hash_node(node1), hash_node(node2), 0); check("IOMT generation from file 2", hash_equals(iomt_getroot(buildcode), correct_root)); -#define N_MODIFY 1 +#define N_MODIFY 10 start = clock(); for(int i = 0; i < N_MODIFY; ++i) req = sp_modifyfile(sp, 1, test_sign_request, "a", 1, hash_null, hash_null, buildcode, NULL, "contents", 8, &ack_hmac); @@ -1150,8 +1254,8 @@ void sp_test(void) hash_t ack; bool success = true; -#define N_ACLMODIFY 100 - for(int i = 0; i < 100; ++i) +#define N_ACLMODIFY 10 + for(int i = 0; i < N_ACLMODIFY; ++i) { struct tm_request req = sp_modifyacl(sp, 1, @@ -1163,8 +1267,6 @@ void sp_test(void) success &= ack_verify(&req, "a", 1, ack); } - iomt_free(newacl); - check("ACL modification 1", success); } @@ -1174,13 +1276,5 @@ void sp_test(void) iomt_dump(sp->iomt); } - /* test tree initialization (only simple case) */ - if(logleaves == 1) - { - struct iomt_node a = { 1, 2, u64_to_hash(2) }; - struct iomt_node b = { 2, 1, hash_null }; - check("Merkle tree initialization", hash_equals(iomt_getroot(sp->iomt), merkle_parent(hash_node(a), hash_node(b), 0))); - } - sp_free(sp); } diff --git a/service_provider.h b/service_provider.h index 1150dad..2f2434a 100644 --- a/service_provider.h +++ b/service_provider.h @@ -65,7 +65,7 @@ struct user_request { } __attribute__((packed)); #ifndef CLIENT -struct service_provider *sp_new(const void *key, size_t keylen, int logleaves); +struct service_provider *sp_new(const void *key, size_t keylen, int logleaves, const char *data_dir); void sp_free(struct service_provider *sp); /* see .c file for documentation */ diff --git a/testcreate.sh b/testcreate.sh index 457d75d..5f3e47f 100755 --- a/testcreate.sh +++ b/testcreate.sh @@ -1,5 +1,5 @@ #!/bin/bash -for i in $(seq 1 1000) +for i in $(seq 1 100) do - ./client -u 1 -k a create + ./client -u 1 -k a create > /dev/null done diff --git a/testmodify.sh b/testmodify.sh index 88ca9d7..1e03f29 100755 --- a/testmodify.sh +++ b/testmodify.sh @@ -1,6 +1,6 @@ #!/bin/bash ./client -u 1 -k a create -for i in $(seq 1 1000) +for i in $(seq 1 100) do - ./client -u 1 -k a modifyfile -f 1 -i container1/hello-world.tar + ./client -u 1 -k a modifyfile -f 1 -i container1/hello-world.tar > /dev/null done |