aboutsummaryrefslogtreecommitdiff
path: root/service_provider.c
diff options
context:
space:
mode:
authorFranklin Wei <me@fwei.tk>2018-06-27 23:38:36 -0400
committerFranklin Wei <me@fwei.tk>2018-06-27 23:38:36 -0400
commitbe7238d18b06b726f1c688c39c21800ef22f72c1 (patch)
treedbffd58a595b53ed9dc80a21cd9888b5c0187128 /service_provider.c
parent3b232072565e54293466f8ba477547686be578bd (diff)
downloadcsaa-be7238d18b06b726f1c688c39c21800ef22f72c1.zip
csaa-be7238d18b06b726f1c688c39c21800ef22f72c1.tar.gz
csaa-be7238d18b06b726f1c688c39c21800ef22f72c1.tar.bz2
csaa-be7238d18b06b726f1c688c39c21800ef22f72c1.tar.xz
Optimize DB code
Diffstat (limited to 'service_provider.c')
-rw-r--r--service_provider.c182
1 files changed, 138 insertions, 44 deletions
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);
}