aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Makefile2
-rw-r--r--client.c43
-rw-r--r--crypto.c11
-rw-r--r--crypto.h3
-rw-r--r--service_provider.c21
-rw-r--r--trusted_module.c73
-rw-r--r--trusted_module.h1
7 files changed, 119 insertions, 35 deletions
diff --git a/Makefile b/Makefile
index 9016ba1..f439450 100644
--- a/Makefile
+++ b/Makefile
@@ -1,5 +1,5 @@
all: client server Makefile
-CFLAGS = -g -Wall
+CFLAGS = -g -Wall -O0
client: client.o crypto.o test.o
cc -o $@ $^ -lcrypto $(CFLAGS)
diff --git a/client.c b/client.c
index 4ee9d99..d7a9b9e 100644
--- a/client.c
+++ b/client.c
@@ -64,7 +64,7 @@ void print_usage(const char *name)
"\n"
"Where COMMAND and PARAMS are one of the following:\n"
" create (takes no parameters)\n"
- " modifyacl fileidx USER1 ACCESS1 ... USERn ACCESSn\n"
+ " modifyacl fileidx USER_1 ACCESS_1 ... USER_n ACCESS_n\n"
" modifyfile fileidx buildcode_file compose_file image_file [FILE_KEY]\n"
" retrieveinfo fileidx version\n"
" retrievefile fileidx version buildcode_out compose_out image_out [FILE_KEY]\n", name);
@@ -220,6 +220,8 @@ bool parse_args(int argc, char *argv[])
if(!strcmp(arg, "retrievefile"))
{
+ cl_request.type = RETRIEVE_FILE;
+
buildcode_path = argv[++i];
compose_path = argv[++i];
image_path = argv[++i];
@@ -246,10 +248,7 @@ static struct tm_request verify_and_sign(int fd, const struct user_request *req)
{
struct tm_request tmr = req_null;
if(recv(fd, &tmr, sizeof(tmr), MSG_WAITALL) != sizeof(tmr))
- {
- perror("short read");
- exit(1);
- }
+ return req_null;
assert(tmr.type != REQ_NONE);
@@ -298,10 +297,7 @@ static bool verify_sp_ack(int fd, const struct tm_request *tmr)
{
hash_t hmac = hash_null;
if(recv(fd, &hmac, sizeof(hmac), MSG_WAITALL) != sizeof(hmac))
- {
- perror("read 2");
- exit(2);
- }
+ return false;
return ack_verify(tmr, userkey, strlen(userkey), hmac);
}
@@ -392,7 +388,7 @@ bool exec_request(int fd, const struct user_request *req,
recv(fd, file_len, sizeof(*file_len), MSG_WAITALL);
*file_contents_out = malloc(*file_len);
- recv(fd, file_contents_out, *file_len, MSG_WAITALL);
+ recv(fd, *file_contents_out, *file_len, MSG_WAITALL);
return true;
}
default:
@@ -430,13 +426,21 @@ int connect_to_service(const char *sockpath)
void *load_file(const char *path, size_t *len)
{
FILE *f = fopen(path, "r");
- *len = fseek(f, 0, SEEK_END);
+ 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)
+{
+ FILE *f = fopen(path, "w");
+ fwrite(contents, 1, len, f);
+ fclose(f);
+}
+
bool server_request(const char *sockpath,
const char *userkey, uint64_t user_id,
struct user_request req,
@@ -498,6 +502,23 @@ bool server_request(const char *sockpath,
case CREATE_FILE:
printf("Created file with index %lu.\n", tmreq.idx);
break;
+ case RETRIEVE_INFO:
+ printf("File info: ");
+ dump_versioninfo(&verinfo);
+ break;
+ case RETRIEVE_FILE:
+ {
+ hash_t gamma = sha256(file_contents, file_len);
+ hash_t lambda = calc_lambda(gamma, buildcode, composefile, req.modify_file.kf);
+
+ printf("File lambda = %s\n", hash_format(lambda, 4).str);
+
+ /* TODO: decrypt 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;
}
diff --git a/crypto.c b/crypto.c
index a7bf68c..4eb1cfa 100644
--- a/crypto.c
+++ b/crypto.c
@@ -555,6 +555,9 @@ hash_t crypt_secret(hash_t encrypted_secret,
* forgo any HMAC. */
hash_t calc_lambda(hash_t gamma, const struct iomt *buildcode, const struct iomt *composefile, hash_t kf)
{
+ printf("calc_lambda: gamma = %s, buildcode = %s, compose = %s, kf = %s\n",
+ hash_format(gamma, 4).str, hash_format(buildcode->mt_nodes[0], 4).str,
+ hash_format(composefile->mt_nodes[0], 4).str, hash_format(kf, 4).str);
hash_t buildcode_root = hash_null, composefile_root = hash_null;
if(buildcode)
buildcode_root = buildcode->mt_nodes[0];
@@ -625,6 +628,14 @@ int read_from_fd(void *userdata, void *buf, size_t len)
return rc;
}
+void dump_versioninfo(const struct version_info *verinfo)
+{
+ printf("idx = %lu, ctr = %lu, ver = %lu, max_ver = %lu, acl = %s, lambda = %s\n",
+ verinfo->idx, verinfo->counter, verinfo->version, verinfo->max_version,
+ hash_format(verinfo->current_acl, 4).str,
+ hash_format(verinfo->lambda, 4).str);
+}
+
void crypto_test(void)
{
#if 1
diff --git a/crypto.h b/crypto.h
index fe251d9..0cc0710 100644
--- a/crypto.h
+++ b/crypto.h
@@ -5,6 +5,7 @@
#include <stdint.h>
struct tm_request;
+struct version_info;
/* Various useful cryptographic functions; shared between TM and SP. */
@@ -152,6 +153,8 @@ bool ack_verify(const struct tm_request *req,
void write_to_fd(void *userdata, const void *data, size_t len);
int read_from_fd(void *userdata, void *buf, size_t len);
+void dump_versioninfo(const struct version_info *verinfo);
+
/* self-test */
void crypto_test(void);
#endif
diff --git a/service_provider.c b/service_provider.c
index eb47ab3..2ee4a12 100644
--- a/service_provider.c
+++ b/service_provider.c
@@ -641,15 +641,19 @@ struct version_info sp_fileinfo(struct service_provider *sp,
user_id,
&rv2_hmac);
- struct file_version *ver = &rec->versions[version ? version - 1 : rec->nversions - 1];
+ struct file_version *ver;
+ if(rec->nversions > 0)
+ ver = &rec->versions[version ? version - 1 : rec->nversions - 1];
+ else
+ ver = NULL;
return tm_verify_fileinfo(sp->tm,
- user_id,
- &rv1, rv1_hmac,
- &rv2, rv2_hmac,
- &rec->fr_cert, rec->fr_hmac,
- &ver->vr_cert, ver->vr_hmac,
- hmac);
+ user_id,
+ &rv1, rv1_hmac,
+ &rv2, rv2_hmac,
+ &rec->fr_cert, rec->fr_hmac,
+ ver ? &ver->vr_cert : NULL, ver ? ver->vr_hmac : hash_null,
+ hmac);
}
/* This file retrieves the file given by file_idx for a given
@@ -771,6 +775,7 @@ static void sp_handle_client(struct service_provider *sp, int cl)
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);
@@ -850,7 +855,7 @@ int sp_main(int sockfd)
signal(SIGPIPE, SIG_IGN);
- int logleaves = 8;
+ int logleaves = 10;
struct service_provider *sp = sp_new("a", 1, logleaves);
while(1)
diff --git a/trusted_module.c b/trusted_module.c
index 712e7a8..59cc503 100644
--- a/trusted_module.c
+++ b/trusted_module.c
@@ -863,32 +863,34 @@ struct version_info tm_verify_fileinfo(const struct trusted_module *tm,
return verinfo;
}
- /* We must have the other 3 certificates to continue. */
- if(!rv2 || !fr || !vr)
+ /* We must have these 2 certificates to continue (VR can be null
+ * for the next part). */
+ if(!rv2 || !fr)
{
tm_seterror("null parameter");
return verinfo_null;
}
+ /* It's possible to have a null VR certificate and a perfectly
+ * valid RV2 and FR certificate when the file has just been
+ * created, but not modifed yet, so we do not check VR just
+ * yet. */
if(!cert_verify(tm, rv2, rv2_hmac) ||
- !cert_verify(tm, fr, fr_hmac) ||
- !cert_verify(tm, vr, vr_hmac))
+ !cert_verify(tm, fr, fr_hmac))
{
tm_seterror("certificate signature invalid");
return verinfo_null;
}
if(rv2->type != RV ||
- fr->type != FR ||
- vr->type != VR)
+ fr->type != FR)
{
tm_seterror("wrong certificate type");
return verinfo_null;
}
/* Ensure that all file indices match */
- if(rv1->rv.idx != fr->fr.idx ||
- rv1->rv.idx != vr->vr.idx)
+ if(rv1->rv.idx != fr->fr.idx)
{
tm_seterror("certificate indices do not match");
return verinfo_null;
@@ -915,21 +917,62 @@ struct version_info tm_verify_fileinfo(const struct trusted_module *tm,
return verinfo_null;
}
- /* Prepare the denial response now so we can fail if needed. */
- verinfo.idx = fr->fr.idx;
- *response_hmac = sign_verinfo(tm, &verinfo, user_id);
-
if(hash_to_u64(rv2->rv.val) < 1)
{
- /* insufficient access level */
+ /* insufficient access level; produce an authenticated denial
+ * (which is indistinguishable from the response when a file
+ * does not exist) */
+ verinfo.idx = fr->fr.idx;
+ *response_hmac = sign_verinfo(tm, &verinfo, user_id);
+
return verinfo;
}
- /* We have verified that the file exists and can convey this to
- * the user */
+ if(!vr)
+ {
+ if(!fr->fr.version)
+ {
+ /* File has been created, but has no contents (and hence
+ * no versions). We issue a response to this effect. */
+ verinfo.idx = fr->fr.idx;
+ verinfo.counter = fr->fr.counter;
+ verinfo.max_version = fr->fr.version;
+ verinfo.version = 0;
+ verinfo.current_acl = fr->fr.acl;
+ verinfo.lambda = hash_null;
+
+ *response_hmac = sign_verinfo(tm, &verinfo, user_id);
+ return verinfo;
+ }
+ tm_seterror("null VR even though maxversion > 0");
+ return verinfo_null;
+ }
+
+ if(!cert_verify(tm, vr, vr_hmac))
+ {
+ tm_seterror("certificate signature invalid");
+ return verinfo_null;
+ }
+
+ if(vr->type != VR)
+ {
+ tm_seterror("wrong certificate type");
+ return verinfo_null;
+ }
+
+ if(rv1->rv.idx != vr->vr.idx)
+ {
+ tm_seterror("certificate indices do not match");
+ return verinfo_null;
+ }
+
+ /* We have verified that this file version exists and can
+ * authenticate its record. */
+ verinfo.idx = fr->fr.idx;
verinfo.counter = fr->fr.counter;
verinfo.max_version = fr->fr.version;
verinfo.version = vr->vr.version;
+ verinfo.current_acl = fr->fr.acl;
verinfo.lambda = vr->vr.hash;
*response_hmac = sign_verinfo(tm, &verinfo, user_id);
diff --git a/trusted_module.h b/trusted_module.h
index 18dbd12..5333032 100644
--- a/trusted_module.h
+++ b/trusted_module.h
@@ -91,6 +91,7 @@ struct version_info {
uint64_t idx;
uint64_t counter;
uint64_t version, max_version;
+ hash_t current_acl; /* not version ACL */
hash_t lambda; /* equal to HMAC(h(encrypted_contents), key=HMAC(key, file_idx)) */
};