diff options
-rw-r--r-- | Makefile | 2 | ||||
-rw-r--r-- | client.c | 43 | ||||
-rw-r--r-- | crypto.c | 11 | ||||
-rw-r--r-- | crypto.h | 3 | ||||
-rw-r--r-- | service_provider.c | 21 | ||||
-rw-r--r-- | trusted_module.c | 73 | ||||
-rw-r--r-- | trusted_module.h | 1 |
7 files changed, 119 insertions, 35 deletions
@@ -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) @@ -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; } @@ -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 @@ -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)) */ }; |