diff options
-rw-r--r-- | Makefile | 18 | ||||
-rw-r--r-- | client.c | 67 | ||||
-rw-r--r-- | crypto.c | 25 | ||||
-rw-r--r-- | crypto.h | 2 | ||||
-rw-r--r-- | dummy_client.c | 417 | ||||
-rw-r--r-- | dummy_service.c | 485 | ||||
-rw-r--r-- | iomt.c | 5 | ||||
-rw-r--r-- | main.c | 13 | ||||
-rw-r--r-- | service_provider.c | 184 | ||||
-rw-r--r-- | service_provider.h | 9 | ||||
-rw-r--r-- | sqlinit.c | 201 | ||||
-rw-r--r-- | sqlinit.txt | 33 | ||||
-rw-r--r-- | test.c | 1 | ||||
-rw-r--r-- | test.h | 2 | ||||
-rwxr-xr-x | testmodify.sh | 2 |
15 files changed, 1359 insertions, 105 deletions
@@ -1,9 +1,19 @@ -all: client server Makefile -CFLAGS = -g -Wall -O3 -lsqlite3 +all: client server dummy_client dummy_server +CFLAGS = -g -Wall -O0 -lsqlite3 +sqlinit.c: sqlinit.txt + xxd -i $^ | sed 's/\([0-9a-f]\)$$/\0, 0x00/' > $@ + +dummy_main.o: main.c + cc -c -o $@ $^ -DDUMMY $(CFLAGS) + +dummy_client: dummy_client.o crypto.o test.o iomt.o + cc -o $@ $^ -lcrypto $(CFLAGS) +dummy_server: dummy_service.o dummy_main.o sqlinit.o + cc -o $@ $^ -lcrypto $(CFLAGS) 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 iomt.o +server: service_provider.o crypto.o helper.o trusted_module.o main.o test.o iomt.o sqlinit.o cc -o $@ $^ -lcrypto $(CFLAGS) clean: - rm -f *.o a.out client server + rm -f *.o a.out client server dummy_client dummy_server @@ -85,10 +85,6 @@ void print_usage(const char *name) " retrieveinfo -f FILEIDX [-v VERSION]\n" "\n" " retrievefile -f FILEIDX [-v VERSION] -o IMAGE_OUT\n"); - for(int i = 0; i < 10; ++i) - { - printf("%d %d\n", i, ilog2(i)); - } } bool parse_args(int argc, char *argv[]) @@ -308,7 +304,8 @@ bool parse_args(int argc, char *argv[]) } } -static struct tm_request verify_and_sign(int fd, const struct user_request *req) +/* val is lambda for FILE_UPDATE, ignored for create, and the ACL root for ACL_MODIFY */ +static struct tm_request verify_and_sign(int fd, const struct user_request *req, hash_t val) { struct tm_request tmr = req_null; if(recv(fd, &tmr, sizeof(tmr), MSG_WAITALL) != sizeof(tmr)) @@ -338,12 +335,20 @@ static struct tm_request verify_and_sign(int fd, const struct user_request *req) } case MODIFY_FILE: { - /* TODO */ + if(tmr.type != FILE_UPDATE || + tmr.user_id != req->user_id || + tmr.idx != req->file_idx || + !hash_equals(tmr.val, val)) + return req_null; break; } case MODIFY_ACL: { - /* TODO */ + if(tmr.type != ACL_UPDATE || + tmr.user_id != req->user_id || + tmr.idx != req->file_idx || + !hash_equals(tmr.val, val)) + return req_null; break; } default: @@ -417,7 +422,19 @@ bool exec_request(int fd, const struct user_request *req, case MODIFY_FILE: { /* verify module ack */ - struct tm_request tmr = verify_and_sign(fd, req); + hash_t val = hash_null; + if(req->type == MODIFY_FILE) + { + hash_t gamma = sha256(new_file_contents, len); + val = calc_lambda(gamma, + new_buildcode, + new_composefile, + req->modify_file.kf); + } + else if(req->type == MODIFY_ACL) + val = iomt_getroot(new_acl); + + struct tm_request tmr = verify_and_sign(fd, req, val); if(tmreq_out) *tmreq_out = tmr; return verify_sp_ack(fd, &tmr); @@ -451,9 +468,14 @@ bool exec_request(int fd, const struct user_request *req, recv(fd, &encrypted_secret, sizeof(encrypted_secret), MSG_WAITALL); recv(fd, &kf, sizeof(kf), MSG_WAITALL); - hash_t pad = hmac_sha256(&kf, sizeof(kf), - user_key, keylen); - *secret_out = hash_xor(encrypted_secret, pad); + if(!is_zero(kf)) + { + hash_t pad = hmac_sha256(&kf, sizeof(kf), + user_key, keylen); + *secret_out = hash_xor(encrypted_secret, pad); + } + else + *secret_out = hash_null; *buildcode = iomt_deserialize(read_from_fd, &fd); *composefile = iomt_deserialize(read_from_fd, &fd); @@ -642,6 +664,8 @@ bool server_request(const char *sockpath, req.type == RETRIEVE_FILE ? &file_contents : NULL, req.type == RETRIEVE_FILE ? &file_len : NULL); + close(fd); + printf("Request %s\n", success ? "\033[32;1msucceeded\033[0m" : @@ -678,7 +702,26 @@ bool server_request(const char *sockpath, printf("Writing image file to %s.\n", image_path); write_file(image_path, file_contents, file_len); /* What about build code? We only have the IOMT, not the actual contents. */ - break; + + /* Verify contents */ + int fd = connect_to_service(sockpath); + struct version_info verinfo = request_verinfo(fd, user_id, + user_key, strlen(user_key), + req.file_idx, + 0); + close(fd); + + bool success = hash_equals(lambda, verinfo.lambda); + + if(!success) + { + printf("Could not verify integrity of response (lambda should be %s).\n", + hash_format(verinfo.lambda, 4).str); + } + else + printf("Successfully verifed integrity of file.\n"); + + return success; } default: break; @@ -1,3 +1,5 @@ +/* crypto and other generally useful stuff, shared by all code */ + #include "crypto.h" #include "iomt.h" #include "trusted_module.h" @@ -350,10 +352,14 @@ hash_t derive_key(const char *passphrase, hash_t nonce) hash_t calc_kf(hash_t encryption_key, uint64_t file_idx) { - if(is_zero(encryption_key)) - return hash_null; - return hmac_sha256(&encryption_key, sizeof(encryption_key), - &file_idx, sizeof(file_idx)); + hash_t kf = hash_null; + if(!is_zero(encryption_key)) + kf = hmac_sha256(&encryption_key, sizeof(encryption_key), + &file_idx, sizeof(file_idx)); + printf("calc_kf: encryption key = %s, file_idx = %lu, kf = %s\n", + hash_format(encryption_key, 4).str, file_idx, + hash_format(kf, 4).str); + return kf; } void memxor(unsigned char *dest, const unsigned char *b, size_t len) @@ -453,6 +459,17 @@ void dump_versioninfo(const struct version_info *verinfo) hash_format(verinfo->lambda, 4).str); } +void warn(const char *fmt, ...) +{ + va_list ap; + va_start(ap, fmt); + + char buf[256]; + vsnprintf(buf, sizeof(buf), fmt, ap); + + fprintf(stderr, "\033[31;1mWARNING\033[0m: %s\n", buf); +} + void crypto_test(void) { #if 1 @@ -87,6 +87,8 @@ hash_t generate_nonce(void); hash_t derive_key(const char *passphrase, hash_t nonce); hash_t calc_kf(hash_t encryption_key, uint64_t file_idx); +void warn(const char *fmt, ...) __attribute__((format(printf, 1, 2))); + /* self-test */ void crypto_test(void); #endif diff --git a/dummy_client.c b/dummy_client.c new file mode 100644 index 0000000..fe66b1b --- /dev/null +++ b/dummy_client.c @@ -0,0 +1,417 @@ +/* Based on: + * <https://github.com/troydhanson/network/blob/master/unixdomain/01.basic/cli.c> */ + +/* A dummy client for use with the dummy service provider, which + * provides no assurances. */ + +/* Usage: + * + * $ ./client [-s <SOCKET>] -u USERID COMMAND [PARAMS] + * + * Where COMMAND and PARAMS are one of the following: + * create (takes no parameters) + * + * modifyfile -f FILEIDX -i IMAGE_FILE + * + * retrievefile -f FILEIDX [-v VERSION] -o IMAGE_OUT + */ + +#define CLIENT +#include "crypto.h" +#include "service_provider.h" +#include "test.h" + +#include <sys/socket.h> +#include <sys/un.h> + +#include <signal.h> +#include <stdio.h> +#include <stdlib.h> +#include <unistd.h> +#include <assert.h> + +static const char *socket_path = "socket"; +static const char *parse_args_fail = NULL; +static uint64_t user_id = 0; +static struct user_request cl_request; +const char *image_path = NULL; + +void print_usage(const char *name) +{ + printf("Usage:\n" + "\n" + "$ ./client [-s <SOCKET>] -u USERID -k USER_KEY COMMAND [PARAMS]\n" + "\n" + "Where COMMAND and PARAMS are one of the following:\n" + " create (takes no parameters)\n" + "\n" + " modifyfile -f FILEIDX -i IMAGE_FILE [-ib buildcode_file]\n" + " [-ic compose_file] [--encrypt, -e]\n" + "\n" + " retrieveinfo -f FILEIDX [-v VERSION]\n" + "\n" + " retrievefile -f FILEIDX [-v VERSION] -o IMAGE_OUT\n"); +} + +bool parse_args(int argc, char *argv[]) +{ + for(int i = 1; i < argc; ++i) + { + char *arg = argv[i]; + if(!strcmp(arg, "-s") || !strcmp(arg, "--socket")) + { + if(++i < argc) + socket_path = argv[i]; + else + { + parse_args_fail = "Expected parameter after -s"; + return false; + } + } + else if(!strcmp(arg, "-u")) + { + if(++i < argc) + user_id = atol(argv[i]); + else + { + parse_args_fail = "Expected user id"; + return false; + } + } + else if(!strcmp(arg, "-f")) + { + if(++i < argc) + cl_request.file_idx = atol(argv[i]); + else + { + parse_args_fail = "Expected file index"; + return false; + } + } + else if(!strcmp(arg, "-v")) + { + if(++i < argc) + cl_request.retrieve.version = atol(argv[i]); + else + { + parse_args_fail = "Expected version number"; + return false; + } + } + /* -i and -o are handled identically */ + else if(!strcmp(arg, "-i") || !strcmp(arg, "-o")) + { + if(++i < argc) + image_path = argv[i]; + else + { + parse_args_fail = "Expected image path"; + return false; + } + } + else if(!strcmp(arg, "-h") || !strcmp(arg, "--help")) + { + print_usage(argv[0]); + exit(1); + } + else if(!strcmp(arg, "create")) + { + if(cl_request.type != USERREQ_NONE) + { + parse_args_fail = "Multiple commands"; + return false; + } + cl_request.type = CREATE_FILE; + } + else if(!strcmp(arg, "modifyfile")) + { + if(cl_request.type != USERREQ_NONE) + { + parse_args_fail = "Multiple commands"; + return false; + } + cl_request.type = MODIFY_FILE; + } + else if(!strcmp(arg, "retrieveinfo") || !strcmp(arg, "retrievefile")) + { + if(cl_request.type != USERREQ_NONE) + { + parse_args_fail = "Multiple commands"; + return false; + } + cl_request.type = RETRIEVE_INFO; + + if(!strcmp(arg, "retrievefile")) + { + cl_request.type = RETRIEVE_FILE; + } + } + else + { + parse_args_fail = "Unknown parameter"; + return false; + } + } + if(cl_request.type != USERREQ_NONE && user_id != 0) + { + if(cl_request.type > CREATE_FILE) + { + if(!cl_request.file_idx) + { + parse_args_fail = "No file index specified"; + return false; + } + } + else + { + if(cl_request.file_idx) + { + parse_args_fail = "Index specified for create"; + return false; + } + } + + if(cl_request.type == MODIFY_FILE || + cl_request.type == RETRIEVE_FILE) + { + if(!image_path) + { + parse_args_fail = "No image file specified"; + return false; + } + } + + return true; + } + else + { + parse_args_fail = "Missing required parameter (either command, user ID, or user key)"; + return false; + } +} + +/* In case of modifcation or file creation, returns true on successful + * completion of request, as acknowledged by module. In case of info + * retrieval, returns true if version info is verified by module. The + * verinfo_out, user_key, and keylen parameters must not be NULL in + * this case (in all other cases they are ignored). */ +bool exec_request(int fd, const struct user_request *req, + const void *new_file_contents, size_t len, /* MODIFY_FILE only */ + struct version_info *verinfo_out, /* RETRIEVE_INFO only */ + void **file_contents_out, /* RETRIEVE_FILE only */ + size_t *file_len, /* RETRIEVE_FILE only */ + uint64_t *new_idx) /* CREATE_FILE only */ +{ + write(fd, req, sizeof(*req)); + /* write additional data */ + switch(req->type) + { + case MODIFY_FILE: + /* prefix file with size */ + write(fd, &len, sizeof(len)); + write(fd, new_file_contents, len); + break; + case CREATE_FILE: + case RETRIEVE_INFO: + case RETRIEVE_FILE: + /* no additional data needed, fall through */ + default: + break; + } + + switch(req->type) + { + case CREATE_FILE: + { + if(new_idx) + recv(fd, new_idx, sizeof(*new_idx), MSG_WAITALL); + return true; + } + case MODIFY_ACL: + case MODIFY_FILE: + { + /* don't verify */ + return true; + } + case RETRIEVE_INFO: + { + hash_t hmac; + struct version_info verinfo; + recv(fd, &verinfo, sizeof(verinfo), MSG_WAITALL); + *verinfo_out = verinfo; + return true; + } + case RETRIEVE_FILE: + { + recv(fd, file_len, sizeof(*file_len), MSG_WAITALL); + + if(*file_len) + { + *file_contents_out = malloc(*file_len); + recv(fd, *file_contents_out, *file_len, MSG_WAITALL); + } + else + { + *file_contents_out = NULL; + return false; + } + return true; + } + default: + assert(false); + } +} + +/* set version = 0 to get latest version */ +struct version_info request_verinfo(int fd, uint64_t user_id, + uint64_t file_idx, uint64_t version) + +{ + struct user_request req; + req.type = RETRIEVE_INFO; + req.user_id = user_id; + req.retrieve.file_idx = file_idx; + req.retrieve.version = version; + + struct version_info verinfo; + + bool rc = exec_request(fd, &req, + NULL, 0, + &verinfo, + NULL, + NULL, + NULL); + + return verinfo; +} + +int connect_to_service(const char *sockpath) +{ + struct sockaddr_un addr; + int fd; + + if ( (fd = socket(AF_UNIX, SOCK_STREAM, 0)) == -1) { + perror("socket error"); + exit(-1); + } + + memset(&addr, 0, sizeof(addr)); + addr.sun_family = AF_UNIX; + if (*sockpath == '\0') { + *addr.sun_path = '\0'; + strncpy(addr.sun_path+1, sockpath+1, sizeof(addr.sun_path)-2); + } else { + strncpy(addr.sun_path, sockpath, sizeof(addr.sun_path)-1); + } + + if (connect(fd, (struct sockaddr*)&addr, sizeof(addr)) == -1) { + perror("connect error"); + exit(-1); + } + + return fd; +} + +void *load_file(const char *path, size_t *len) +{ + FILE *f = fopen(path, "r"); + fseek(f, 0, SEEK_END); + *len = ftell(f); + fseek(f, 0, SEEK_SET); + void *buf = malloc(*len); + fread(buf, 1, *len, f); + return buf; +} + +void write_file(const char *path, const void *contents, size_t len) +{ + if(contents) + { + FILE *f = fopen(path, "w"); + fwrite(contents, 1, len, f); + fclose(f); + } +} + +bool server_request(const char *sockpath, + uint64_t user_id, + struct user_request req, + const char *image_path) +{ + void *file_contents = NULL; + size_t file_len = 0; + + /* Fill in rest of request structure */ + req.user_id = user_id; + + if(req.type == MODIFY_FILE) + { + if(image_path) + { + file_contents = load_file(image_path, &file_len); + } + } + + struct version_info verinfo; + + int fd = connect_to_service(sockpath); + uint64_t new_idx; + + bool success = exec_request(fd, &req, + req.type == MODIFY_FILE ? file_contents : NULL, + req.type == MODIFY_FILE ? file_len : 0, + req.type == RETRIEVE_INFO ? &verinfo : NULL, + req.type == RETRIEVE_FILE ? &file_contents : NULL, + req.type == RETRIEVE_FILE ? &file_len : NULL, + req.type == CREATE_FILE ? &new_idx : NULL); + + printf("Request %s\n", + success ? + "\033[32;1msucceeded\033[0m" : + "\033[31;1mfailed\033[0m"); + + if(!success) + return false; + + switch(req.type) + { + case CREATE_FILE: + printf("Created file with index %lu.\n", new_idx); + break; + case RETRIEVE_INFO: + printf("File info: "); + dump_versioninfo(&verinfo); + break; + case RETRIEVE_FILE: + { + printf("Writing image file to %s.\n", image_path); + write_file(image_path, file_contents, file_len); + /* What about build code? We only have the IOMT, not the actual contents. */ + break; + } + default: + break; + } + + return true; +} + +int main(int argc, char *argv[]) { + char buf[100]; + int fd,rc; + + if(!parse_args(argc, argv)) + { + printf("%s\n", parse_args_fail); + print_usage(argv[0]); + return 1; + } + + signal(SIGPIPE, SIG_IGN); + + server_request(socket_path, user_id, + cl_request, + image_path); + + return 0; +} diff --git a/dummy_service.c b/dummy_service.c new file mode 100644 index 0000000..5a974d1 --- /dev/null +++ b/dummy_service.c @@ -0,0 +1,485 @@ +/* implementation of a basic service provider for use with the trusted + * module */ + +#include <assert.h> +#include <signal.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <time.h> +#include <unistd.h> + +#include <sys/socket.h> +#include <sys/stat.h> +#include <sys/types.h> + +#include <sqlite3.h> + +#include "crypto.h" +#include "helper.h" +#include "test.h" + +/* get type definitions only */ +#define CLIENT + +#include "trusted_module.h" +#include "service_provider.h" + +/* arbitrary */ +#define ACL_LOGLEAVES 4 + +#define MAX_PATH 260 + +/* should be free'd with free_record */ +struct file_record { + uint64_t idx; + uint64_t version; +}; + +struct service_provider { + const char *data_dir; + + void *db; /* sqlite3 handle */ +}; + +/* 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(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) +{ + sqlite3 *db; + 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, const char *data_dir, const char *dbpath) +{ + assert(logleaves > 0); + struct service_provider *sp = calloc(1, sizeof(*sp)); + + sp->db = db_init(dbpath); + + sp->data_dir = data_dir; + + return sp; +} + +static void free_record(struct file_record *rec) +{ + if(rec) + { + free(rec); + } +} + +void sp_free(struct service_provider *sp) +{ + if(sp) + { + free(sp); + } +} + +/* linear search for record given idx */ +static struct file_record *lookup_record(struct service_provider *sp, uint64_t idx) +{ + 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); + + return rec; + } + //printf("Failed to find file record with index %lu (%s), ret %d\n", idx, sqlite3_errmsg(handle), rc); + return NULL; +} + +/* 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 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 (Idx, Ver) VALUES ( ?1, ?2 );"; + 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); + + assert(sqlite3_step(st) == SQLITE_DONE); + + sqlite3_finalize(st); +} + +/* 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) +{ + sqlite3 *handle = sp->db; + + const char *sql = "UPDATE FileRecords SET Idx = ?1, Ver = ?2 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, 7, rec->idx); + + assert(sqlite3_step(st) == SQLITE_DONE); + + sqlite3_finalize(st); +} + +/* This does the majority of the work that actually modifies or + * creates a file. It expects a filled and signed tm_request + * structure, req, and will return the resulting FR certificate and + * its signature in *hmac_out. Additionally, the module's + * authenticated acknowledgement (equal to HMAC(req | 0), where | + * indicates concatenation) is output in *ack_hmac_out. + * + * If the request is to modify the file, the parameters + * encrypted_secret, kf, buildcode, composefile, encrypted_contents, + * and contents_len are used (otherwise they are + * ignored). `encrypted_secret' should be the file encryption key + * XOR'd with HMAC(file index | file counter, user_key). kf should be + * 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. This + * function will make a copy of new_acl, so it can safely be freed + * after calling this function. */ +void sp_request(struct service_provider *sp, + const struct tm_request *req, + const void *encrypted_contents, size_t contents_len) +{ + /* update the corresponding file record */ + struct file_record *rec = lookup_record(sp, req->idx); + + bool need_insert = false; + if(!rec) + { + rec = calloc(1, sizeof(struct file_record)); + need_insert = true; + } + + rec->idx = req->idx; + + if(req->type == FILE_UPDATE) + { + rec->version++; + + /* write to disk */ + write_contents(sp, req->idx, rec->version, + encrypted_contents, contents_len); + } + + if(need_insert) + insert_record(sp, rec); + else + update_record(sp, rec); + + free_record(rec); +} + +int next_slot(struct service_provider *sp) +{ + const char *sql = "SELECT MAX(Idx) from FileRecords;"; + + static sqlite3_stmt *st = NULL; + + sqlite3 *handle = sp->db; + + if(!st) + sqlite3_prepare_v2(handle, sql, -1, &st, 0); + + sqlite3_reset(st); + + int rc = sqlite3_step(st); + + if(rc == SQLITE_ROW) + { + return sqlite3_column_int(st, 0) + 1; + } + + return 1; +} + +int sp_createfile(struct service_provider *sp, + uint64_t user_id) +{ + int i = next_slot(sp); + + struct tm_request req; + req.idx = i; + req.user_id = user_id; + req.type = ACL_UPDATE; + req.counter = 0; + + sp_request(sp, + &req, + NULL, 0); + + return i; +} + +struct tm_request sp_modifyfile(struct service_provider *sp, + uint64_t user_id, + uint64_t file_idx, + const void *encrypted_file, size_t filelen) +{ + /* modification */ + struct file_record *rec = lookup_record(sp, file_idx); + if(!rec) + { + printf("Could not find file with index %lu\n", file_idx); + return req_null; + } + + struct tm_request req; + req.idx = file_idx; + req.user_id = user_id; + req.type = FILE_UPDATE; + + sp_request(sp, + &req, + encrypted_file, filelen); + + return req; +} + +/* Retrieve authenticated information (using the user's secret as the + * key) on a version of a file; if version is zero, default to the + * latest version. If the file does not exist, the function will still + * succeed, returning an authenticated structure indicating + * failure. */ +struct version_info sp_fileinfo(struct service_provider *sp, + uint64_t user_id, + uint64_t file_idx, + uint64_t version) +{ + struct file_record *rec = lookup_record(sp, file_idx); + + if(!rec) + { + return (struct version_info) { file_idx, 0, 0, 0, hash_null, hash_null }; + } + + if(!version) + version = rec->version; + + struct version_info ret = (struct version_info) { rec->idx, 0, version, rec->version, hash_null, hash_null }; + + return ret; +} + +/* This file retrieves the file given by file_idx for a given + * user. *encrypted_secret will be set to the encryption key XOR'd + * with HMAC(kf, K). kf will be returned via the *kf pointer. The + * returned value is dynamically allocated and must be freed by the + * caller. This function returns NULL upon failure. An authenticated + * proof that the request cannot be satisfied can be obtained by + * calling sp_fileinfo. */ +void *sp_retrieve_file(struct service_provider *sp, + uint64_t user_id, + uint64_t file_idx, + uint64_t version, + size_t *len) +{ + struct file_record *rec = lookup_record(sp, file_idx); + + if(!rec || rec->version == 0) + { + /* Newly created file, no contents. We don't bother to set + * *encrypted_secret or *len. Or, file does not exist. */ + *len = 0; + return NULL; + } + + if(!version) + version = rec->version; + + void *ret = read_contents(sp, file_idx, version, len); + + return ret; +} + +static void sp_handle_client(struct service_provider *sp, int cl) +{ + /* We should probably fork() here to avoid blocking */ + struct user_request user_req; + if(recv(cl, &user_req, sizeof(user_req), MSG_WAITALL) != sizeof(user_req)) + return; + + switch(user_req.type) + { + case CREATE_FILE: + { + printf("Client: create file\n"); + uint64_t slot = sp_createfile(sp, user_req.user_id); + write(cl, &slot, sizeof(slot)); + break; + } + case MODIFY_FILE: + { + printf("Client: modify file\n"); + size_t filelen; + recv(cl, &filelen, sizeof(filelen), MSG_WAITALL); + + printf("File is %lu bytes.\n", filelen); + void *filebuf = malloc(filelen); + recv(cl, filebuf, filelen, MSG_WAITALL); + + sp_modifyfile(sp, + user_req.user_id, + user_req.modify_file.file_idx, + filebuf, filelen); + break; + } + case RETRIEVE_INFO: + { + printf("Client: retrieve info\n"); + struct version_info verinfo = sp_fileinfo(sp, + user_req.user_id, + user_req.retrieve.file_idx, + user_req.retrieve.version); + write(cl, &verinfo, sizeof(verinfo)); + + break; + } + case RETRIEVE_FILE: + { + printf("Client: retrieve file\n"); + size_t len = 0; + void *contents = sp_retrieve_file(sp, + user_req.user_id, + user_req.retrieve.file_idx, + user_req.retrieve.version, + &len); + + write(cl, &len, sizeof(len)); + if(contents) + write(cl, contents, len); + + break; + } + case USERREQ_NONE: + { + printf("null request\n"); + exit(1); + } + } +} + +int sp_main(int sockfd, int logleaves, const char *dbpath, bool overwrite) +{ + (void) overwrite; +#define BACKLOG 10 + + if(listen(sockfd, BACKLOG) < 0) + { + perror("listen"); + return 1; + } + + signal(SIGPIPE, SIG_IGN); + + struct service_provider *sp = sp_new("a", 1, logleaves, "files", dbpath); + + while(1) + { + int cl; + + if((cl = accept(sockfd, NULL, NULL)) < 0) + { + perror("accept"); + return 1; + } + + sp_handle_client(sp, cl); + close(cl); + } +} @@ -306,7 +306,9 @@ void merkle_update(struct iomt *tree, uint64_t leafidx, hash_t newval, hash_t ** hash_t iomt_getroot(const struct iomt *tree) { - return iomt_getnode(tree, 0); + if(tree) + return iomt_getnode(tree, 0); + return hash_null; } /* find a node with given idx */ @@ -570,6 +572,7 @@ struct iomt *iomt_dup(const struct iomt *oldtree) newtree->mt_leafcount = oldtree->mt_leafcount; newtree->mt_logleaves = oldtree->mt_logleaves; + newtree->in_memory = true; newtree->mem.mt_leaves = calloc(oldtree->mt_leafcount, sizeof(struct iomt_node)); newtree->mem.mt_nodes = calloc(2 * oldtree->mt_leafcount - 1, sizeof(hash_t)); @@ -37,23 +37,33 @@ void signal_handler(int sig) exit(1); } +#ifndef DUMMY void run_tests(void) { crypto_test(); tm_test(); sp_test(); } +#endif int main(int argc, char *argv[]) { +#ifndef DUMMY //run_tests(); +#endif + bool overwrite = false; + + /* TODO: real parsing */ const char *dbpath = "csaa.db"; int logleaves = 10; if(argc >= 2) logleaves = atol(argv[1]); if(argc >= 3) dbpath = argv[2]; + if(argc >= 4) + if(!strcmp(argv[3], "--overwrite")) + overwrite = true; const char *socket_name = "socket"; int sockfd; @@ -71,6 +81,7 @@ int main(int argc, char *argv[]) signal(SIGINT, signal_handler); signal(SIGTERM, signal_handler); signal(SIGSEGV, signal_handler); + signal(SIGABRT, signal_handler); - sp_main(sockfd, logleaves, dbpath); + sp_main(sockfd, logleaves, dbpath, overwrite); } diff --git a/service_provider.c b/service_provider.c index 96f12d2..d17cd4e 100644 --- a/service_provider.c +++ b/service_provider.c @@ -184,7 +184,26 @@ void *read_contents(const struct service_provider *sp, return buf; } -void *db_init(const char *filename) +int count_rows(void *db, const char *table) +{ + char buf[1000]; + snprintf(buf, sizeof(buf), "SELECT COUNT(*) FROM %s;", table); + + sqlite3_stmt *st; + sqlite3_prepare_v2(db, buf, -1, &st, 0); + + /* no table */ + if(sqlite3_step(st) != SQLITE_ROW) + return 0; + + int rows = sqlite3_column_int(st, 0); + + sqlite3_finalize(st); + + return rows; +} + +void *db_init(const char *filename, bool overwrite, bool *need_init) { sqlite3 *db; if(sqlite3_open(filename, &db) != SQLITE_OK) @@ -193,6 +212,19 @@ void *db_init(const char *filename) sqlite3_exec(db, "PRAGMA synchronous = 0;", 0, 0, 0); sqlite3_exec(db, "PRAGMA journal_mode = memory;", 0, 0, 0); + if(overwrite || count_rows(db, "FileLeaves") == 0) + { + extern unsigned char sqlinit_txt[]; + + /* create tables */ + char *msg; + assert(sqlite3_exec(db, (const char*)sqlinit_txt, NULL, NULL, &msg) == SQLITE_OK); + + *need_init = true; + } + else + *need_init = false; + return db; } @@ -209,12 +241,18 @@ void commit_transaction(void *db) } /* leaf count will be 2^logleaves */ -struct service_provider *sp_new(const void *key, size_t keylen, int logleaves, const char *data_dir, const char *dbpath) +/* will use old DB contents unless overwrite_db is true */ +struct service_provider *sp_new(const void *key, size_t keylen, + int logleaves, + const char *data_dir, + const char *dbpath, + bool overwrite_db) { assert(logleaves > 0); struct service_provider *sp = calloc(1, sizeof(*sp)); - sp->db = db_init(dbpath); + bool iomt_init = true; + sp->db = db_init(dbpath, overwrite_db, &iomt_init); sp->tm = tm_new(key, keylen); @@ -223,75 +261,79 @@ struct service_provider *sp_new(const void *key, size_t keylen, int logleaves, c sp->data_dir = data_dir; - clock_t start = clock(); + if(iomt_init) + { + printf("Initializing IOMT with %llu nodes.\n", 1ULL << logleaves); - /* 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 - * update the internal IOMT root. Note that leaf indices are - * 1-indexed. */ - iomt_update_leaf_full(sp->iomt, - 0, - 1, 1, hash_null); + clock_t start = clock(); - for(int i = 1; i < sp->iomt->mt_leafcount; ++i) - { - /* generate EQ certificate */ - hash_t hmac; - struct tm_cert eq = cert_eq(sp, - iomt_getleaf(sp->iomt, i - 1), - i - 1, - i, i + 1, - &hmac); - assert(eq.type == EQ); - - /* update previous leaf's index */ - iomt_update_leaf_nextidx(sp->iomt, i - 1, i + 1); - - /* next_idx is set to 1 to keep everything circularly linked; - * in the next iteration it will be updated to point to the - * next node, if any */ - iomt_update_leaf_full(sp->iomt, i, i + 1, 1, hash_null); - -#if 0 - if(i % 10 == 0) + /* 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 + * update the internal IOMT root. Note that leaf indices are + * 1-indexed. */ + iomt_update_leaf_full(sp->iomt, + 0, + 1, 1, hash_null); + + for(int i = 1; i < sp->iomt->mt_leafcount; ++i) { - commit_transaction(sp->db); - begin_transaction(sp->db); + /* generate EQ certificate */ + hash_t hmac; + struct tm_cert eq = cert_eq(sp, + iomt_getleaf(sp->iomt, i - 1), + i - 1, + i, i + 1, + &hmac); + assert(eq.type == EQ); + + /* update previous leaf's index */ + iomt_update_leaf_nextidx(sp->iomt, i - 1, i + 1); + + /* next_idx is set to 1 to keep everything circularly linked; + * in the next iteration it will be updated to point to the + * next node, if any */ + iomt_update_leaf_full(sp->iomt, i, i + 1, 1, hash_null); + + assert(tm_set_equiv_root(sp->tm, &eq, hmac)); + //printf("%d\n", i); } -#endif - assert(tm_set_equiv_root(sp->tm, &eq, hmac)); - //printf("%d\n", i); - } + /* now transfer to database */ + printf("IOMT initialized in memory, transferring to DB...\n"); - /* now transfer to database */ - printf("IOMT initialized in memory, transferring to DB...\n"); + clock_t point1 = clock(); - clock_t point1 = clock(); + begin_transaction(sp->db); - begin_transaction(sp->db); + /* we must do it this way because cert_eq expects sp->iomt to be + * the working tree */ + struct iomt *old = sp->iomt; - /* we must do it this way because cert_eq expects sp->iomt to be - * the working tree */ - struct iomt *old = sp->iomt; + sp->iomt = iomt_dup_in_db(sp->db, + "FileNodes", "FileLeaves", + NULL, 0, + NULL, 0, + old); - sp->iomt = iomt_dup_in_db(sp->db, - "FileNodes", "FileLeaves", - NULL, 0, - NULL, 0, - old); + commit_transaction(sp->db); - commit_transaction(sp->db); + iomt_free(old); - iomt_free(old); + clock_t stop = clock(); - clock_t stop = clock(); - - printf("sp_init(): logleaves=%d, time=%.3fsec, overall_rate=%.3f/sec, db_time=%.3fsec\n", - logleaves, (double)(stop - start) / CLOCKS_PER_SEC, - (double)(1ULL << logleaves) * CLOCKS_PER_SEC / ( stop - start ), - (double)(stop - point1) / CLOCKS_PER_SEC); + printf("sp_init(): logleaves=%d, time=%.3fsec, overall_rate=%.3f/sec, db_time=%.3fsec\n", + logleaves, (double)(stop - start) / CLOCKS_PER_SEC, + (double)(1ULL << logleaves) * CLOCKS_PER_SEC / ( stop - start ), + (double)(stop - point1) / CLOCKS_PER_SEC); + } + else + { + int leaves = count_rows(sp->db, "FileLeaves"); + if(leaves != (1ULL << logleaves)) + warn("logleaves value is inconsistent with leaf count in IOMT! (have %d, expect %d)", + leaves, 1 << logleaves); + } return sp; } @@ -596,6 +638,7 @@ struct tm_cert sp_request(struct service_provider *sp, else { ver.encrypted_secret = hash_null; + ver.kf = hash_null; } ver.version = fr.fr.version; @@ -653,6 +696,7 @@ struct tm_request sp_createfile(struct service_provider *sp, { int i; + /* TODO: use database? */ /* Find an empty leaf node */ for(i = 0; i < sp->iomt->mt_leafcount; ++i) { @@ -816,6 +860,8 @@ struct tm_request sp_modifyfile(struct service_provider *sp, struct tm_cert vr; hash_t vr_hmac, fr_hmac; + printf("Modifying file with new kf=%s.\n", hash_format(kf, 4).str); + struct tm_cert new_fr = sp_request(sp, &req, req_hmac, &fr_hmac, @@ -920,6 +966,8 @@ struct version_info sp_fileinfo(struct service_provider *sp, struct file_version *ver = lookup_version(sp, rec->idx, version); + printf("Version kf=%s\n", hash_format(ver->kf, 4).str); + if(acl_out) *acl_out = iomt_dup(rec->acl); @@ -967,6 +1015,12 @@ void *sp_retrieve_file(struct service_provider *sp, struct file_version *ver = lookup_version(sp, file_idx, version); + if(!ver) + { + *len = 0; + return NULL; + } + hash_t rv1_hmac, rv2_hmac; struct tm_cert rv1 = cert_rv_by_idx(sp->tm, sp->iomt, file_idx, &rv1_hmac); struct tm_cert rv2 = cert_rv_by_idx(sp->tm, rec->acl, user_id, &rv2_hmac); @@ -1148,7 +1202,7 @@ static void sp_handle_client(struct service_provider *sp, int cl) } } -int sp_main(int sockfd, int logleaves, const char *dbpath) +int sp_main(int sockfd, int logleaves, const char *dbpath, bool overwrite) { #define BACKLOG 10 @@ -1160,12 +1214,7 @@ int sp_main(int sockfd, int logleaves, const char *dbpath) signal(SIGPIPE, SIG_IGN); - printf("Initializing IOMT with logleaves = %d...\n", logleaves); - - struct service_provider *sp = sp_new("a", 1, logleaves, "files", dbpath); - - /* test init only */ - return 0; + struct service_provider *sp = sp_new("a", 1, logleaves, "files", dbpath, overwrite); while(1) { @@ -1191,10 +1240,9 @@ static hash_t test_sign_request(void *userdata, const struct tm_request *req) void sp_test(void) { int logleaves = 1; - printf("Initializing IOMT with %llu nodes.\n", 1ULL << logleaves); clock_t start = clock(); - struct service_provider *sp = sp_new("a", 1, logleaves, "files", "csaa.db"); + struct service_provider *sp = sp_new("a", 1, logleaves, "files", "csaa.db", true); clock_t stop = clock(); check("Tree initialization", sp != NULL); diff --git a/service_provider.h b/service_provider.h index fe7a4cd..fdc7bc0 100644 --- a/service_provider.h +++ b/service_provider.h @@ -69,7 +69,8 @@ struct service_provider *sp_new(const void *key, size_t keylen, int logleaves, const char *data_dir, - const char *dbpath); + const char *dbpath, + bool overwrite); void sp_free(struct service_provider *sp); /* see .c file for documentation */ @@ -129,9 +130,11 @@ void *sp_retrieve_file(struct service_provider *sp, struct iomt **composefile, size_t *len); -int sp_main(int sockfd, int logleaves, const char *dbpath); - void sp_test(void); #endif +#if defined(DUMMY) || !defined(CLIENT) +int sp_main(int sockfd, int logleaves, const char *dbpath, bool overwrite); +#endif + #endif diff --git a/sqlinit.c b/sqlinit.c new file mode 100644 index 0000000..bfa2599 --- /dev/null +++ b/sqlinit.c @@ -0,0 +1,201 @@ +unsigned char sqlinit_txt[] = { + 0x50, 0x52, 0x41, 0x47, 0x4d, 0x41, 0x20, 0x66, 0x6f, 0x72, 0x65, 0x69, + 0x67, 0x6e, 0x5f, 0x6b, 0x65, 0x79, 0x73, 0x20, 0x3d, 0x20, 0x4f, 0x46, + 0x46, 0x3b, 0x0a, 0x0a, 0x44, 0x52, 0x4f, 0x50, 0x20, 0x54, 0x41, 0x42, + 0x4c, 0x45, 0x20, 0x49, 0x46, 0x20, 0x45, 0x58, 0x49, 0x53, 0x54, 0x53, + 0x20, 0x46, 0x69, 0x6c, 0x65, 0x52, 0x65, 0x63, 0x6f, 0x72, 0x64, 0x73, + 0x3b, 0x0a, 0x44, 0x52, 0x4f, 0x50, 0x20, 0x54, 0x41, 0x42, 0x4c, 0x45, + 0x20, 0x49, 0x46, 0x20, 0x45, 0x58, 0x49, 0x53, 0x54, 0x53, 0x20, 0x46, + 0x69, 0x6c, 0x65, 0x4c, 0x65, 0x61, 0x76, 0x65, 0x73, 0x3b, 0x0a, 0x44, + 0x52, 0x4f, 0x50, 0x20, 0x54, 0x41, 0x42, 0x4c, 0x45, 0x20, 0x49, 0x46, + 0x20, 0x45, 0x58, 0x49, 0x53, 0x54, 0x53, 0x20, 0x46, 0x69, 0x6c, 0x65, + 0x4e, 0x6f, 0x64, 0x65, 0x73, 0x3b, 0x0a, 0x44, 0x52, 0x4f, 0x50, 0x20, + 0x54, 0x41, 0x42, 0x4c, 0x45, 0x20, 0x49, 0x46, 0x20, 0x45, 0x58, 0x49, + 0x53, 0x54, 0x53, 0x20, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x73, + 0x3b, 0x0a, 0x44, 0x52, 0x4f, 0x50, 0x20, 0x54, 0x41, 0x42, 0x4c, 0x45, + 0x20, 0x49, 0x46, 0x20, 0x45, 0x58, 0x49, 0x53, 0x54, 0x53, 0x20, 0x41, + 0x43, 0x4c, 0x4c, 0x65, 0x61, 0x76, 0x65, 0x73, 0x3b, 0x0a, 0x44, 0x52, + 0x4f, 0x50, 0x20, 0x54, 0x41, 0x42, 0x4c, 0x45, 0x20, 0x49, 0x46, 0x20, + 0x45, 0x58, 0x49, 0x53, 0x54, 0x53, 0x20, 0x41, 0x43, 0x4c, 0x4e, 0x6f, + 0x64, 0x65, 0x73, 0x3b, 0x0a, 0x44, 0x52, 0x4f, 0x50, 0x20, 0x54, 0x41, + 0x42, 0x4c, 0x45, 0x20, 0x49, 0x46, 0x20, 0x45, 0x58, 0x49, 0x53, 0x54, + 0x53, 0x20, 0x42, 0x43, 0x4c, 0x65, 0x61, 0x76, 0x65, 0x73, 0x3b, 0x0a, + 0x44, 0x52, 0x4f, 0x50, 0x20, 0x54, 0x41, 0x42, 0x4c, 0x45, 0x20, 0x49, + 0x46, 0x20, 0x45, 0x58, 0x49, 0x53, 0x54, 0x53, 0x20, 0x42, 0x43, 0x4e, + 0x6f, 0x64, 0x65, 0x73, 0x3b, 0x0a, 0x44, 0x52, 0x4f, 0x50, 0x20, 0x54, + 0x41, 0x42, 0x4c, 0x45, 0x20, 0x49, 0x46, 0x20, 0x45, 0x58, 0x49, 0x53, + 0x54, 0x53, 0x20, 0x43, 0x46, 0x4c, 0x65, 0x61, 0x76, 0x65, 0x73, 0x3b, + 0x0a, 0x44, 0x52, 0x4f, 0x50, 0x20, 0x54, 0x41, 0x42, 0x4c, 0x45, 0x20, + 0x49, 0x46, 0x20, 0x45, 0x58, 0x49, 0x53, 0x54, 0x53, 0x20, 0x43, 0x46, + 0x4e, 0x6f, 0x64, 0x65, 0x73, 0x3b, 0x0a, 0x0a, 0x43, 0x52, 0x45, 0x41, + 0x54, 0x45, 0x20, 0x54, 0x41, 0x42, 0x4c, 0x45, 0x20, 0x49, 0x46, 0x20, + 0x4e, 0x4f, 0x54, 0x20, 0x45, 0x58, 0x49, 0x53, 0x54, 0x53, 0x20, 0x46, + 0x69, 0x6c, 0x65, 0x52, 0x65, 0x63, 0x6f, 0x72, 0x64, 0x73, 0x20, 0x28, + 0x0a, 0x49, 0x64, 0x78, 0x20, 0x49, 0x4e, 0x54, 0x45, 0x47, 0x45, 0x52, + 0x2c, 0x0a, 0x56, 0x65, 0x72, 0x20, 0x49, 0x4e, 0x54, 0x45, 0x47, 0x45, + 0x52, 0x2c, 0x0a, 0x43, 0x74, 0x72, 0x20, 0x49, 0x4e, 0x54, 0x45, 0x47, + 0x45, 0x52, 0x2c, 0x0a, 0x43, 0x65, 0x72, 0x74, 0x20, 0x42, 0x4c, 0x4f, + 0x42, 0x2c, 0x0a, 0x48, 0x4d, 0x41, 0x43, 0x20, 0x42, 0x4c, 0x4f, 0x42, + 0x2c, 0x0a, 0x41, 0x43, 0x4c, 0x5f, 0x6c, 0x6f, 0x67, 0x6c, 0x65, 0x61, + 0x76, 0x65, 0x73, 0x20, 0x49, 0x4e, 0x54, 0x45, 0x47, 0x45, 0x52, 0x0a, + 0x29, 0x3b, 0x0a, 0x0a, 0x43, 0x52, 0x45, 0x41, 0x54, 0x45, 0x20, 0x54, + 0x41, 0x42, 0x4c, 0x45, 0x20, 0x49, 0x46, 0x20, 0x4e, 0x4f, 0x54, 0x20, + 0x45, 0x58, 0x49, 0x53, 0x54, 0x53, 0x20, 0x46, 0x69, 0x6c, 0x65, 0x4c, + 0x65, 0x61, 0x76, 0x65, 0x73, 0x20, 0x28, 0x0a, 0x4c, 0x65, 0x61, 0x66, + 0x49, 0x64, 0x78, 0x20, 0x49, 0x4e, 0x54, 0x45, 0x47, 0x45, 0x52, 0x2c, + 0x0a, 0x49, 0x64, 0x78, 0x20, 0x49, 0x4e, 0x54, 0x45, 0x47, 0x45, 0x52, + 0x2c, 0x0a, 0x4e, 0x65, 0x78, 0x74, 0x49, 0x64, 0x78, 0x20, 0x49, 0x4e, + 0x54, 0x45, 0x47, 0x45, 0x52, 0x2c, 0x0a, 0x56, 0x61, 0x6c, 0x20, 0x42, + 0x4c, 0x4f, 0x42, 0x2c, 0x0a, 0x50, 0x52, 0x49, 0x4d, 0x41, 0x52, 0x59, + 0x20, 0x4b, 0x45, 0x59, 0x20, 0x28, 0x4c, 0x65, 0x61, 0x66, 0x49, 0x64, + 0x78, 0x29, 0x0a, 0x29, 0x3b, 0x0a, 0x0a, 0x43, 0x52, 0x45, 0x41, 0x54, + 0x45, 0x20, 0x54, 0x41, 0x42, 0x4c, 0x45, 0x20, 0x49, 0x46, 0x20, 0x4e, + 0x4f, 0x54, 0x20, 0x45, 0x58, 0x49, 0x53, 0x54, 0x53, 0x20, 0x46, 0x69, + 0x6c, 0x65, 0x4e, 0x6f, 0x64, 0x65, 0x73, 0x20, 0x28, 0x0a, 0x4e, 0x6f, + 0x64, 0x65, 0x49, 0x64, 0x78, 0x20, 0x49, 0x4e, 0x54, 0x45, 0x47, 0x45, + 0x52, 0x2c, 0x0a, 0x56, 0x61, 0x6c, 0x20, 0x42, 0x4c, 0x4f, 0x42, 0x2c, + 0x0a, 0x50, 0x52, 0x49, 0x4d, 0x41, 0x52, 0x59, 0x20, 0x4b, 0x45, 0x59, + 0x20, 0x28, 0x4e, 0x6f, 0x64, 0x65, 0x49, 0x64, 0x78, 0x29, 0x0a, 0x29, + 0x3b, 0x0a, 0x0a, 0x43, 0x52, 0x45, 0x41, 0x54, 0x45, 0x20, 0x54, 0x41, + 0x42, 0x4c, 0x45, 0x20, 0x49, 0x46, 0x20, 0x4e, 0x4f, 0x54, 0x20, 0x45, + 0x58, 0x49, 0x53, 0x54, 0x53, 0x20, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, + 0x6e, 0x73, 0x20, 0x28, 0x0a, 0x46, 0x69, 0x6c, 0x65, 0x49, 0x64, 0x78, + 0x20, 0x49, 0x4e, 0x54, 0x45, 0x47, 0x45, 0x52, 0x2c, 0x0a, 0x56, 0x65, + 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x20, 0x49, 0x4e, 0x54, 0x45, 0x47, 0x45, + 0x52, 0x2c, 0x0a, 0x4b, 0x46, 0x20, 0x42, 0x4c, 0x4f, 0x42, 0x2c, 0x0a, + 0x65, 0x6e, 0x63, 0x72, 0x79, 0x70, 0x74, 0x65, 0x64, 0x5f, 0x73, 0x65, + 0x63, 0x72, 0x65, 0x74, 0x20, 0x42, 0x4c, 0x4f, 0x42, 0x2c, 0x0a, 0x43, + 0x65, 0x72, 0x74, 0x20, 0x42, 0x4c, 0x4f, 0x42, 0x2c, 0x0a, 0x48, 0x4d, + 0x41, 0x43, 0x20, 0x42, 0x4c, 0x4f, 0x42, 0x2c, 0x0a, 0x42, 0x75, 0x69, + 0x6c, 0x64, 0x63, 0x6f, 0x64, 0x65, 0x5f, 0x6c, 0x6f, 0x67, 0x6c, 0x65, + 0x61, 0x76, 0x65, 0x73, 0x20, 0x49, 0x4e, 0x54, 0x45, 0x47, 0x45, 0x52, + 0x2c, 0x0a, 0x43, 0x6f, 0x6d, 0x70, 0x6f, 0x73, 0x65, 0x66, 0x69, 0x6c, + 0x65, 0x5f, 0x6c, 0x6f, 0x67, 0x6c, 0x65, 0x61, 0x76, 0x65, 0x73, 0x20, + 0x49, 0x4e, 0x54, 0x45, 0x47, 0x45, 0x52, 0x2c, 0x0a, 0x50, 0x52, 0x49, + 0x4d, 0x41, 0x52, 0x59, 0x20, 0x4b, 0x45, 0x59, 0x20, 0x28, 0x46, 0x69, + 0x6c, 0x65, 0x49, 0x64, 0x78, 0x2c, 0x20, 0x56, 0x65, 0x72, 0x73, 0x69, + 0x6f, 0x6e, 0x29, 0x2c, 0x0a, 0x46, 0x4f, 0x52, 0x45, 0x49, 0x47, 0x4e, + 0x20, 0x4b, 0x45, 0x59, 0x20, 0x28, 0x46, 0x69, 0x6c, 0x65, 0x49, 0x64, + 0x78, 0x29, 0x20, 0x52, 0x45, 0x46, 0x45, 0x52, 0x45, 0x4e, 0x43, 0x45, + 0x53, 0x20, 0x46, 0x69, 0x6c, 0x65, 0x52, 0x65, 0x63, 0x6f, 0x72, 0x64, + 0x73, 0x28, 0x49, 0x64, 0x78, 0x29, 0x0a, 0x29, 0x3b, 0x0a, 0x0a, 0x43, + 0x52, 0x45, 0x41, 0x54, 0x45, 0x20, 0x54, 0x41, 0x42, 0x4c, 0x45, 0x20, + 0x49, 0x46, 0x20, 0x4e, 0x4f, 0x54, 0x20, 0x45, 0x58, 0x49, 0x53, 0x54, + 0x53, 0x20, 0x41, 0x43, 0x4c, 0x4c, 0x65, 0x61, 0x76, 0x65, 0x73, 0x20, + 0x28, 0x0a, 0x46, 0x69, 0x6c, 0x65, 0x49, 0x64, 0x78, 0x20, 0x49, 0x4e, + 0x54, 0x45, 0x47, 0x45, 0x52, 0x2c, 0x0a, 0x4c, 0x65, 0x61, 0x66, 0x49, + 0x64, 0x78, 0x20, 0x49, 0x4e, 0x54, 0x45, 0x47, 0x45, 0x52, 0x2c, 0x0a, + 0x49, 0x64, 0x78, 0x20, 0x49, 0x4e, 0x54, 0x45, 0x47, 0x45, 0x52, 0x2c, + 0x0a, 0x4e, 0x65, 0x78, 0x74, 0x49, 0x64, 0x78, 0x20, 0x49, 0x4e, 0x54, + 0x45, 0x47, 0x45, 0x52, 0x2c, 0x0a, 0x56, 0x61, 0x6c, 0x20, 0x42, 0x4c, + 0x4f, 0x42, 0x2c, 0x0a, 0x50, 0x52, 0x49, 0x4d, 0x41, 0x52, 0x59, 0x20, + 0x4b, 0x45, 0x59, 0x20, 0x28, 0x46, 0x69, 0x6c, 0x65, 0x49, 0x64, 0x78, + 0x2c, 0x20, 0x4c, 0x65, 0x61, 0x66, 0x49, 0x64, 0x78, 0x29, 0x2c, 0x0a, + 0x46, 0x4f, 0x52, 0x45, 0x49, 0x47, 0x4e, 0x20, 0x4b, 0x45, 0x59, 0x20, + 0x28, 0x46, 0x69, 0x6c, 0x65, 0x49, 0x64, 0x78, 0x29, 0x20, 0x52, 0x45, + 0x46, 0x45, 0x52, 0x45, 0x4e, 0x43, 0x45, 0x53, 0x20, 0x46, 0x69, 0x6c, + 0x65, 0x52, 0x65, 0x63, 0x6f, 0x72, 0x64, 0x73, 0x28, 0x49, 0x64, 0x78, + 0x29, 0x0a, 0x29, 0x3b, 0x0a, 0x0a, 0x43, 0x52, 0x45, 0x41, 0x54, 0x45, + 0x20, 0x54, 0x41, 0x42, 0x4c, 0x45, 0x20, 0x49, 0x46, 0x20, 0x4e, 0x4f, + 0x54, 0x20, 0x45, 0x58, 0x49, 0x53, 0x54, 0x53, 0x20, 0x41, 0x43, 0x4c, + 0x4e, 0x6f, 0x64, 0x65, 0x73, 0x20, 0x28, 0x0a, 0x46, 0x69, 0x6c, 0x65, + 0x49, 0x64, 0x78, 0x20, 0x49, 0x4e, 0x54, 0x45, 0x47, 0x45, 0x52, 0x2c, + 0x0a, 0x4e, 0x6f, 0x64, 0x65, 0x49, 0x64, 0x78, 0x20, 0x49, 0x4e, 0x54, + 0x45, 0x47, 0x45, 0x52, 0x2c, 0x0a, 0x56, 0x61, 0x6c, 0x20, 0x42, 0x4c, + 0x4f, 0x42, 0x2c, 0x0a, 0x50, 0x52, 0x49, 0x4d, 0x41, 0x52, 0x59, 0x20, + 0x4b, 0x45, 0x59, 0x20, 0x28, 0x46, 0x69, 0x6c, 0x65, 0x49, 0x64, 0x78, + 0x2c, 0x20, 0x4e, 0x6f, 0x64, 0x65, 0x49, 0x64, 0x78, 0x29, 0x2c, 0x0a, + 0x46, 0x4f, 0x52, 0x45, 0x49, 0x47, 0x4e, 0x20, 0x4b, 0x45, 0x59, 0x20, + 0x28, 0x46, 0x69, 0x6c, 0x65, 0x49, 0x64, 0x78, 0x29, 0x20, 0x52, 0x45, + 0x46, 0x45, 0x52, 0x45, 0x4e, 0x43, 0x45, 0x53, 0x20, 0x46, 0x69, 0x6c, + 0x65, 0x52, 0x65, 0x63, 0x6f, 0x72, 0x64, 0x73, 0x28, 0x49, 0x64, 0x78, + 0x29, 0x0a, 0x29, 0x3b, 0x0a, 0x0a, 0x43, 0x52, 0x45, 0x41, 0x54, 0x45, + 0x20, 0x54, 0x41, 0x42, 0x4c, 0x45, 0x20, 0x49, 0x46, 0x20, 0x4e, 0x4f, + 0x54, 0x20, 0x45, 0x58, 0x49, 0x53, 0x54, 0x53, 0x20, 0x42, 0x43, 0x4c, + 0x65, 0x61, 0x76, 0x65, 0x73, 0x20, 0x28, 0x0a, 0x46, 0x69, 0x6c, 0x65, + 0x49, 0x64, 0x78, 0x20, 0x49, 0x4e, 0x54, 0x45, 0x47, 0x45, 0x52, 0x2c, + 0x0a, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x20, 0x49, 0x4e, 0x54, + 0x45, 0x47, 0x45, 0x52, 0x2c, 0x0a, 0x4c, 0x65, 0x61, 0x66, 0x49, 0x64, + 0x78, 0x20, 0x49, 0x4e, 0x54, 0x45, 0x47, 0x45, 0x52, 0x2c, 0x0a, 0x49, + 0x64, 0x78, 0x20, 0x49, 0x4e, 0x54, 0x45, 0x47, 0x45, 0x52, 0x2c, 0x0a, + 0x4e, 0x65, 0x78, 0x74, 0x49, 0x64, 0x78, 0x20, 0x49, 0x4e, 0x54, 0x45, + 0x47, 0x45, 0x52, 0x2c, 0x0a, 0x56, 0x61, 0x6c, 0x20, 0x42, 0x4c, 0x4f, + 0x42, 0x2c, 0x0a, 0x50, 0x52, 0x49, 0x4d, 0x41, 0x52, 0x59, 0x20, 0x4b, + 0x45, 0x59, 0x20, 0x28, 0x46, 0x69, 0x6c, 0x65, 0x49, 0x64, 0x78, 0x2c, + 0x20, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x2c, 0x20, 0x4c, 0x65, + 0x61, 0x66, 0x49, 0x64, 0x78, 0x29, 0x2c, 0x0a, 0x46, 0x4f, 0x52, 0x45, + 0x49, 0x47, 0x4e, 0x20, 0x4b, 0x45, 0x59, 0x20, 0x28, 0x46, 0x69, 0x6c, + 0x65, 0x49, 0x64, 0x78, 0x29, 0x20, 0x52, 0x45, 0x46, 0x45, 0x52, 0x45, + 0x4e, 0x43, 0x45, 0x53, 0x20, 0x46, 0x69, 0x6c, 0x65, 0x52, 0x65, 0x63, + 0x6f, 0x72, 0x64, 0x73, 0x28, 0x49, 0x64, 0x78, 0x29, 0x2c, 0x0a, 0x46, + 0x4f, 0x52, 0x45, 0x49, 0x47, 0x4e, 0x20, 0x4b, 0x45, 0x59, 0x20, 0x28, + 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x29, 0x20, 0x52, 0x45, 0x46, + 0x45, 0x52, 0x45, 0x4e, 0x43, 0x45, 0x53, 0x20, 0x56, 0x65, 0x72, 0x73, + 0x69, 0x6f, 0x6e, 0x73, 0x28, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, + 0x29, 0x0a, 0x29, 0x3b, 0x0a, 0x0a, 0x43, 0x52, 0x45, 0x41, 0x54, 0x45, + 0x20, 0x54, 0x41, 0x42, 0x4c, 0x45, 0x20, 0x49, 0x46, 0x20, 0x4e, 0x4f, + 0x54, 0x20, 0x45, 0x58, 0x49, 0x53, 0x54, 0x53, 0x20, 0x42, 0x43, 0x4e, + 0x6f, 0x64, 0x65, 0x73, 0x20, 0x28, 0x0a, 0x46, 0x69, 0x6c, 0x65, 0x49, + 0x64, 0x78, 0x20, 0x49, 0x4e, 0x54, 0x45, 0x47, 0x45, 0x52, 0x2c, 0x0a, + 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x20, 0x49, 0x4e, 0x54, 0x45, + 0x47, 0x45, 0x52, 0x2c, 0x0a, 0x56, 0x61, 0x6c, 0x20, 0x42, 0x4c, 0x4f, + 0x42, 0x2c, 0x0a, 0x4e, 0x6f, 0x64, 0x65, 0x49, 0x64, 0x78, 0x20, 0x49, + 0x4e, 0x54, 0x45, 0x47, 0x45, 0x52, 0x2c, 0x0a, 0x50, 0x52, 0x49, 0x4d, + 0x41, 0x52, 0x59, 0x20, 0x4b, 0x45, 0x59, 0x20, 0x28, 0x46, 0x69, 0x6c, + 0x65, 0x49, 0x64, 0x78, 0x2c, 0x20, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, + 0x6e, 0x2c, 0x20, 0x4e, 0x6f, 0x64, 0x65, 0x49, 0x64, 0x78, 0x29, 0x2c, + 0x0a, 0x46, 0x4f, 0x52, 0x45, 0x49, 0x47, 0x4e, 0x20, 0x4b, 0x45, 0x59, + 0x20, 0x28, 0x46, 0x69, 0x6c, 0x65, 0x49, 0x64, 0x78, 0x29, 0x20, 0x52, + 0x45, 0x46, 0x45, 0x52, 0x45, 0x4e, 0x43, 0x45, 0x53, 0x20, 0x46, 0x69, + 0x6c, 0x65, 0x52, 0x65, 0x63, 0x6f, 0x72, 0x64, 0x73, 0x28, 0x49, 0x64, + 0x78, 0x29, 0x2c, 0x0a, 0x46, 0x4f, 0x52, 0x45, 0x49, 0x47, 0x4e, 0x20, + 0x4b, 0x45, 0x59, 0x20, 0x28, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, + 0x29, 0x20, 0x52, 0x45, 0x46, 0x45, 0x52, 0x45, 0x4e, 0x43, 0x45, 0x53, + 0x20, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x73, 0x28, 0x56, 0x65, + 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x29, 0x0a, 0x29, 0x3b, 0x0a, 0x0a, 0x43, + 0x52, 0x45, 0x41, 0x54, 0x45, 0x20, 0x54, 0x41, 0x42, 0x4c, 0x45, 0x20, + 0x49, 0x46, 0x20, 0x4e, 0x4f, 0x54, 0x20, 0x45, 0x58, 0x49, 0x53, 0x54, + 0x53, 0x20, 0x43, 0x46, 0x4c, 0x65, 0x61, 0x76, 0x65, 0x73, 0x20, 0x28, + 0x0a, 0x46, 0x69, 0x6c, 0x65, 0x49, 0x64, 0x78, 0x20, 0x49, 0x4e, 0x54, + 0x45, 0x47, 0x45, 0x52, 0x2c, 0x0a, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, + 0x6e, 0x20, 0x49, 0x4e, 0x54, 0x45, 0x47, 0x45, 0x52, 0x2c, 0x0a, 0x4c, + 0x65, 0x61, 0x66, 0x49, 0x64, 0x78, 0x20, 0x49, 0x4e, 0x54, 0x45, 0x47, + 0x45, 0x52, 0x2c, 0x0a, 0x49, 0x64, 0x78, 0x20, 0x49, 0x4e, 0x54, 0x45, + 0x47, 0x45, 0x52, 0x2c, 0x0a, 0x4e, 0x65, 0x78, 0x74, 0x49, 0x64, 0x78, + 0x20, 0x49, 0x4e, 0x54, 0x45, 0x47, 0x45, 0x52, 0x2c, 0x0a, 0x56, 0x61, + 0x6c, 0x20, 0x42, 0x4c, 0x4f, 0x42, 0x2c, 0x0a, 0x50, 0x52, 0x49, 0x4d, + 0x41, 0x52, 0x59, 0x20, 0x4b, 0x45, 0x59, 0x20, 0x28, 0x46, 0x69, 0x6c, + 0x65, 0x49, 0x64, 0x78, 0x2c, 0x20, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, + 0x6e, 0x2c, 0x20, 0x4c, 0x65, 0x61, 0x66, 0x49, 0x64, 0x78, 0x29, 0x2c, + 0x0a, 0x46, 0x4f, 0x52, 0x45, 0x49, 0x47, 0x4e, 0x20, 0x4b, 0x45, 0x59, + 0x20, 0x28, 0x46, 0x69, 0x6c, 0x65, 0x49, 0x64, 0x78, 0x29, 0x20, 0x52, + 0x45, 0x46, 0x45, 0x52, 0x45, 0x4e, 0x43, 0x45, 0x53, 0x20, 0x46, 0x69, + 0x6c, 0x65, 0x52, 0x65, 0x63, 0x6f, 0x72, 0x64, 0x73, 0x28, 0x49, 0x64, + 0x78, 0x29, 0x2c, 0x0a, 0x46, 0x4f, 0x52, 0x45, 0x49, 0x47, 0x4e, 0x20, + 0x4b, 0x45, 0x59, 0x20, 0x28, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, + 0x29, 0x20, 0x52, 0x45, 0x46, 0x45, 0x52, 0x45, 0x4e, 0x43, 0x45, 0x53, + 0x20, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x73, 0x28, 0x56, 0x65, + 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x29, 0x0a, 0x29, 0x3b, 0x0a, 0x0a, 0x43, + 0x52, 0x45, 0x41, 0x54, 0x45, 0x20, 0x54, 0x41, 0x42, 0x4c, 0x45, 0x20, + 0x49, 0x46, 0x20, 0x4e, 0x4f, 0x54, 0x20, 0x45, 0x58, 0x49, 0x53, 0x54, + 0x53, 0x20, 0x43, 0x46, 0x4e, 0x6f, 0x64, 0x65, 0x73, 0x20, 0x28, 0x0a, + 0x46, 0x69, 0x6c, 0x65, 0x49, 0x64, 0x78, 0x20, 0x49, 0x4e, 0x54, 0x45, + 0x47, 0x45, 0x52, 0x2c, 0x0a, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, + 0x20, 0x49, 0x4e, 0x54, 0x45, 0x47, 0x45, 0x52, 0x2c, 0x0a, 0x56, 0x61, + 0x6c, 0x20, 0x42, 0x4c, 0x4f, 0x42, 0x2c, 0x0a, 0x4e, 0x6f, 0x64, 0x65, + 0x49, 0x64, 0x78, 0x20, 0x49, 0x4e, 0x54, 0x45, 0x47, 0x45, 0x52, 0x2c, + 0x0a, 0x50, 0x52, 0x49, 0x4d, 0x41, 0x52, 0x59, 0x20, 0x4b, 0x45, 0x59, + 0x20, 0x28, 0x46, 0x69, 0x6c, 0x65, 0x49, 0x64, 0x78, 0x2c, 0x20, 0x56, + 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x2c, 0x20, 0x4e, 0x6f, 0x64, 0x65, + 0x49, 0x64, 0x78, 0x29, 0x2c, 0x0a, 0x46, 0x4f, 0x52, 0x45, 0x49, 0x47, + 0x4e, 0x20, 0x4b, 0x45, 0x59, 0x20, 0x28, 0x46, 0x69, 0x6c, 0x65, 0x49, + 0x64, 0x78, 0x29, 0x20, 0x52, 0x45, 0x46, 0x45, 0x52, 0x45, 0x4e, 0x43, + 0x45, 0x53, 0x20, 0x46, 0x69, 0x6c, 0x65, 0x52, 0x65, 0x63, 0x6f, 0x72, + 0x64, 0x73, 0x28, 0x49, 0x64, 0x78, 0x29, 0x2c, 0x0a, 0x46, 0x4f, 0x52, + 0x45, 0x49, 0x47, 0x4e, 0x20, 0x4b, 0x45, 0x59, 0x20, 0x28, 0x56, 0x65, + 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x29, 0x20, 0x52, 0x45, 0x46, 0x45, 0x52, + 0x45, 0x4e, 0x43, 0x45, 0x53, 0x20, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, + 0x6e, 0x73, 0x28, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x29, 0x0a, + 0x29, 0x3b, 0x0a, 0x00 +}; +unsigned int sqlinit_txt_len = 2367; diff --git a/sqlinit.txt b/sqlinit.txt index 8f17229..06cd076 100644 --- a/sqlinit.txt +++ b/sqlinit.txt @@ -1,4 +1,17 @@ -CREATE TABLE FileRecords ( +PRAGMA foreign_keys = OFF; + +DROP TABLE IF EXISTS FileRecords; +DROP TABLE IF EXISTS FileLeaves; +DROP TABLE IF EXISTS FileNodes; +DROP TABLE IF EXISTS Versions; +DROP TABLE IF EXISTS ACLLeaves; +DROP TABLE IF EXISTS ACLNodes; +DROP TABLE IF EXISTS BCLeaves; +DROP TABLE IF EXISTS BCNodes; +DROP TABLE IF EXISTS CFLeaves; +DROP TABLE IF EXISTS CFNodes; + +CREATE TABLE IF NOT EXISTS FileRecords ( Idx INTEGER, Ver INTEGER, Ctr INTEGER, @@ -7,7 +20,7 @@ HMAC BLOB, ACL_logleaves INTEGER ); -CREATE TABLE FileLeaves ( +CREATE TABLE IF NOT EXISTS FileLeaves ( LeafIdx INTEGER, Idx INTEGER, NextIdx INTEGER, @@ -15,13 +28,13 @@ Val BLOB, PRIMARY KEY (LeafIdx) ); -CREATE TABLE FileNodes ( +CREATE TABLE IF NOT EXISTS FileNodes ( NodeIdx INTEGER, Val BLOB, PRIMARY KEY (NodeIdx) ); -CREATE TABLE Versions ( +CREATE TABLE IF NOT EXISTS Versions ( FileIdx INTEGER, Version INTEGER, KF BLOB, @@ -34,7 +47,7 @@ PRIMARY KEY (FileIdx, Version), FOREIGN KEY (FileIdx) REFERENCES FileRecords(Idx) ); -CREATE TABLE ACLLeaves ( +CREATE TABLE IF NOT EXISTS ACLLeaves ( FileIdx INTEGER, LeafIdx INTEGER, Idx INTEGER, @@ -44,7 +57,7 @@ PRIMARY KEY (FileIdx, LeafIdx), FOREIGN KEY (FileIdx) REFERENCES FileRecords(Idx) ); -CREATE TABLE ACLNodes ( +CREATE TABLE IF NOT EXISTS ACLNodes ( FileIdx INTEGER, NodeIdx INTEGER, Val BLOB, @@ -52,7 +65,7 @@ PRIMARY KEY (FileIdx, NodeIdx), FOREIGN KEY (FileIdx) REFERENCES FileRecords(Idx) ); -CREATE TABLE BCLeaves ( +CREATE TABLE IF NOT EXISTS BCLeaves ( FileIdx INTEGER, Version INTEGER, LeafIdx INTEGER, @@ -64,7 +77,7 @@ FOREIGN KEY (FileIdx) REFERENCES FileRecords(Idx), FOREIGN KEY (Version) REFERENCES Versions(Version) ); -CREATE TABLE BCNodes ( +CREATE TABLE IF NOT EXISTS BCNodes ( FileIdx INTEGER, Version INTEGER, Val BLOB, @@ -74,7 +87,7 @@ FOREIGN KEY (FileIdx) REFERENCES FileRecords(Idx), FOREIGN KEY (Version) REFERENCES Versions(Version) ); -CREATE TABLE CFLeaves ( +CREATE TABLE IF NOT EXISTS CFLeaves ( FileIdx INTEGER, Version INTEGER, LeafIdx INTEGER, @@ -86,7 +99,7 @@ FOREIGN KEY (FileIdx) REFERENCES FileRecords(Idx), FOREIGN KEY (Version) REFERENCES Versions(Version) ); -CREATE TABLE CFNodes ( +CREATE TABLE IF NOT EXISTS CFNodes ( FileIdx INTEGER, Version INTEGER, Val BLOB, @@ -1,5 +1,6 @@ #include <stdio.h> +#include "crypto.h" #include "service_provider.h" #include "trusted_module.h" @@ -1,5 +1,5 @@ /* testing */ void check(const char *name, int condition); -/* in main.c */ +/* in test.c or dummy_service.c */ void run_tests(void); diff --git a/testmodify.sh b/testmodify.sh index 1e03f29..c836ad4 100755 --- a/testmodify.sh +++ b/testmodify.sh @@ -1,5 +1,5 @@ #!/bin/bash -./client -u 1 -k a create +./client -u 1 -k a create > /dev/null for i in $(seq 1 100) do ./client -u 1 -k a modifyfile -f 1 -i container1/hello-world.tar > /dev/null |