diff options
author | Franklin Wei <me@fwei.tk> | 2018-06-22 22:57:25 -0400 |
---|---|---|
committer | Franklin Wei <me@fwei.tk> | 2018-06-22 22:57:25 -0400 |
commit | 77094976e17f3c1151dc7210815f0d47029ea54b (patch) | |
tree | 0c10179dacb7d6a696132c1cd63aba1559c8c437 | |
parent | 898454639359d49ddb8cb098634473e9207c6e49 (diff) | |
download | csaa-77094976e17f3c1151dc7210815f0d47029ea54b.zip csaa-77094976e17f3c1151dc7210815f0d47029ea54b.tar.gz csaa-77094976e17f3c1151dc7210815f0d47029ea54b.tar.bz2 csaa-77094976e17f3c1151dc7210815f0d47029ea54b.tar.xz |
Finish implementing client and server
Also makes a minor change to F_rs() IVP; the encryption pad ought to depend
on the file version, not the counter.
-rw-r--r-- | .gitignore | 5 | ||||
-rw-r--r-- | client.c | 101 | ||||
-rw-r--r-- | crypto.c | 17 | ||||
-rw-r--r-- | crypto.h | 5 | ||||
-rw-r--r-- | service_provider.c | 80 | ||||
-rw-r--r-- | service_provider.h | 4 | ||||
-rw-r--r-- | trusted_module.c | 30 | ||||
-rw-r--r-- | trusted_module.h | 18 |
8 files changed, 183 insertions, 77 deletions
diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..fc2c59c --- /dev/null +++ b/.gitignore @@ -0,0 +1,5 @@ +*.o +*~ +a.out +server +client @@ -17,11 +17,6 @@ char *socket_path = "socket"; -static bool need_sign(int reqtype) -{ - return reqtype == CREATE_FILE || reqtype == MODIFY_FILE || reqtype == MODIFY_ACL; -} - static struct tm_request verify_and_sign(int fd, const struct user_request *req) { struct tm_request tmr = req_null; @@ -57,6 +52,8 @@ static struct tm_request verify_and_sign(int fd, const struct user_request *req) /* TODO */ break; } + default: + break; } hash_t hmac = hmac_sha256(&tmr, sizeof(tmr), "a", 1); @@ -77,17 +74,23 @@ static bool verify_sp_ack(int fd, const struct tm_request *tmr) return ack_verify(tmr, "a", 1, hmac); } -void write_fd(void *userdata, const void *data, size_t len) -{ - int *fdptr = userdata; - write(*fdptr, data, len); -} - +/* 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 struct iomt *new_acl, - const struct iomt *new_buildcode, - const struct iomt *new_composefile, - const void *file_contents, size_t len) + const struct iomt *new_acl, /* MODIFY_ACL only */ + const struct iomt *new_buildcode, /* MODIFY_FILE only */ + const struct iomt *new_composefile, /* MODIFY_FILE only */ + const void *new_file_contents, size_t len, /* MODIFY_FILE only */ + struct version_info *verinfo_out, /* RETRIEVE_INFO only */ + const void *user_key, size_t keylen, /* RETRIEVE_INFO and RETRIEVE_FILE only */ + struct iomt **buildcode, /* RETRIEVE_FILE only */ + struct iomt **composefile, /* RETRIEVE_FILE only */ + hash_t *secret_out, /* RETRIEVE_FILE only */ + void **file_contents_out, /* RETRIEVE_FILE only */ + size_t *file_len) /* RETRIEVE_FILE only */ { write(fd, req, sizeof(*req)); /* write additional data */ @@ -95,16 +98,16 @@ bool exec_request(int fd, const struct user_request *req, { case MODIFY_ACL: /* send ACL */ - iomt_serialize(new_acl, write_fd, &fd); + iomt_serialize(new_acl, write_to_fd, &fd); break; case MODIFY_FILE: /* send build code, compose file, and file contents */ - iomt_serialize(new_buildcode, write_fd, &fd); - iomt_serialize(new_composefile, write_fd, &fd); + iomt_serialize(new_buildcode, write_to_fd, &fd); + iomt_serialize(new_composefile, write_to_fd, &fd); /* prefix file with size */ write(fd, &len, sizeof(len)); - write(fd, file_contents, len); + write(fd, new_file_contents, len); break; case CREATE_FILE: case RETRIEVE_INFO: @@ -114,18 +117,52 @@ bool exec_request(int fd, const struct user_request *req, break; } - struct tm_request tmr; - - /* sign request */ - if(need_sign(req->type)) + switch(req->type) { - /* read a tm_request from the file descriptor, and verify that - * it carries out the requested action, and then sign */ - tmr = verify_and_sign(fd, req); + case CREATE_FILE: + case MODIFY_ACL: + case MODIFY_FILE: + { + /* verify module ack */ + struct tm_request tmr = verify_and_sign(fd, req); + return verify_sp_ack(fd, &tmr); + } + case RETRIEVE_INFO: + { + hash_t hmac; + struct version_info verinfo; + read(fd, &verinfo, sizeof(verinfo)); + read(fd, &hmac, sizeof(hmac)); + + if(hash_equals(hmac, hmac_sha256(&verinfo, sizeof(verinfo), user_key, keylen))) + { + *verinfo_out = verinfo; + return true; + } + return false; } + case RETRIEVE_FILE: + { + hash_t encrypted_secret; + read(fd, &encrypted_secret, sizeof(encrypted_secret)); - /* verify acknowledgement */ - return verify_sp_ack(fd, &tmr); + *secret_out = crypt_secret(encrypted_secret, + req->retrieve.file_idx, + req->retrieve.version, + user_key, keylen); + + *buildcode = iomt_deserialize(read_from_fd, &fd); + *composefile = iomt_deserialize(read_from_fd, &fd); + + read(fd, file_len, sizeof(*file_len)); + + *file_contents_out = malloc(*file_len); + read(fd, file_contents_out, *file_len); + return true; + } + default: + assert(false); + } } int connect_to_service(const char *sockpath) @@ -167,7 +204,9 @@ int main(int argc, char *argv[]) { req.type = CREATE_FILE; req.create.user_id = 1; - check("Client file creation", exec_request(fd, &req, NULL, NULL, NULL, NULL, 0)); + check("Client file creation", exec_request(fd, &req, NULL, NULL, NULL, NULL, 0, + NULL, NULL, 0, + NULL, NULL, NULL, NULL, NULL)); close(fd); fd = connect_to_service(socket_path); @@ -177,7 +216,9 @@ int main(int argc, char *argv[]) { req.modify_file.encrypted_secret = hash_null; req.modify_file.kf = hash_null; - check("Client file modification", exec_request(fd, &req, NULL, NULL, NULL, "contents", 8)); + check("Client file modification", exec_request(fd, &req, NULL, NULL, NULL, "contents", 8, + NULL, NULL, 0, + NULL, NULL, NULL, NULL, NULL)); close(fd); return 0; @@ -524,7 +524,7 @@ hash_t u64_to_hash(uint64_t n) /* simple XOR cipher, so encryption and decryption are symmetric */ hash_t crypt_secret(hash_t encrypted_secret, - uint64_t file_idx, uint64_t file_counter, + uint64_t file_idx, uint64_t file_version, const void *key, size_t keylen) { hash_t pad; /* key = encrypted_secret ^ pad */ @@ -535,7 +535,7 @@ hash_t crypt_secret(hash_t encrypted_secret, /* potential endianness issue */ HMAC_Update(ctx, (const unsigned char*)&file_idx, sizeof(file_idx)); - HMAC_Update(ctx, (const unsigned char*)&file_counter, sizeof(file_counter)); + HMAC_Update(ctx, (const unsigned char*)&file_version, sizeof(file_version)); HMAC_Final(ctx, pad.hash, NULL); HMAC_CTX_free(ctx); @@ -599,6 +599,19 @@ bool ack_verify(const struct tm_request *req, return hash_equals(hmac, correct); } +void write_to_fd(void *userdata, const void *data, size_t len) +{ + int *fdptr = userdata; + write(*fdptr, data, len); +} + + +int read_from_fd(void *userdata, void *buf, size_t len) +{ + int *fdptr = userdata; + return read(*fdptr, buf, len); +} + void crypto_test(void) { #if 1 @@ -136,7 +136,7 @@ struct hashstring { struct hashstring hash_format(hash_t h, int n); hash_t crypt_secret(hash_t encrypted_secret, - uint64_t file_idx, uint64_t file_counter, + uint64_t file_idx, uint64_t file_version, const void *key, size_t keylen); hash_t calc_lambda(hash_t gamma, const struct iomt *buildcode, const struct iomt *composefile, hash_t kf); @@ -149,6 +149,9 @@ bool ack_verify(const struct tm_request *req, const void *secret, size_t secret_len, hash_t hmac); +void write_to_fd(void *userdata, const void *data, size_t len); +int read_from_fd(void *userdata, void *buf, size_t len); + /* self-test */ void crypto_test(void); #endif diff --git a/service_provider.c b/service_provider.c index 5dc033b..cf1535d 100644 --- a/service_provider.c +++ b/service_provider.c @@ -312,7 +312,7 @@ struct tm_cert sp_request(struct service_provider *sp, { /* File is encrypted */ ver.encrypted_secret = tm_verify_and_encrypt_secret(sp->tm, - rec->idx, rec->counter, + rec->idx, rec->version, req->user_id, encrypted_secret, kf); assert(!is_zero(ver.encrypted_secret)); @@ -614,13 +614,13 @@ struct version_info sp_fileinfo(struct service_provider *sp, free(orders); } - return tm_verify_file(sp->tm, - user_id, - &rv1, rv1_hmac, - NULL, hash_null, - NULL, hash_null, - NULL, hash_null, - hmac); + return tm_verify_fileinfo(sp->tm, + user_id, + &rv1, rv1_hmac, + NULL, hash_null, + NULL, hash_null, + NULL, hash_null, + hmac); } /* RV1 indicates counter */ @@ -639,7 +639,7 @@ struct version_info sp_fileinfo(struct service_provider *sp, struct file_version *ver = &rec->versions[version ? version - 1 : rec->nversions - 1]; - return tm_verify_file(sp->tm, + return tm_verify_fileinfo(sp->tm, user_id, &rv1, rv1_hmac, &rv2, rv2_hmac, @@ -659,6 +659,8 @@ void *sp_retrieve_file(struct service_provider *sp, uint64_t file_idx, uint64_t version, hash_t *encrypted_secret, + struct iomt **buildcode, + struct iomt **composefile, size_t *len) { struct file_record *rec = lookup_record(sp, file_idx); @@ -700,6 +702,12 @@ void *sp_retrieve_file(struct service_provider *sp, void *ret = malloc(ver->contents_len); memcpy(ret, ver->contents, ver->contents_len); + /* duplicate compose and build files */ + if(buildcode) + *buildcode = iomt_dup(ver->buildcode); + if(composefile) + *composefile = iomt_dup(ver->composefile); + return ret; } @@ -713,12 +721,6 @@ static hash_t get_client_signature(void *userdata, const struct tm_request *req) return hmac; } -int read_fd(void *userdata, void *buf, size_t len) -{ - int *fdptr = userdata; - return read(*fdptr, buf, len); -} - static void sp_handle_client(struct service_provider *sp, int cl) { /* We should probably fork() here to avoid blocking */ @@ -732,10 +734,11 @@ static void sp_handle_client(struct service_provider *sp, int cl) { case CREATE_FILE: sp_createfile(sp, user_req.create.user_id, get_client_signature, &cl, &ack_hmac); + write(cl, &ack_hmac, sizeof(ack_hmac)); break; case MODIFY_ACL: { - struct iomt *acl = iomt_deserialize(read_fd, &cl); + struct iomt *acl = iomt_deserialize(read_from_fd, &cl); sp_modifyacl(sp, user_req.modify_acl.user_id, get_client_signature, @@ -744,14 +747,16 @@ static void sp_handle_client(struct service_provider *sp, int cl) acl, &ack_hmac); iomt_free(acl); + write(cl, &ack_hmac, sizeof(ack_hmac)); break; } case MODIFY_FILE: { - struct iomt *buildcode = iomt_deserialize(read_fd, &cl); - struct iomt *composefile = iomt_deserialize(read_fd, &cl); + struct iomt *buildcode = iomt_deserialize(read_from_fd, &cl); + struct iomt *composefile = iomt_deserialize(read_from_fd, &cl); size_t filelen; read(cl, &filelen, sizeof(filelen)); + void *filebuf = malloc(filelen); read(cl, filebuf, filelen); @@ -768,10 +773,45 @@ static void sp_handle_client(struct service_provider *sp, int cl) &ack_hmac); iomt_free(buildcode); iomt_free(composefile); + write(cl, &ack_hmac, sizeof(ack_hmac)); + break; } + case RETRIEVE_INFO: + { + struct version_info verinfo = sp_fileinfo(sp, + user_req.retrieve.user_id, + user_req.retrieve.file_idx, + user_req.retrieve.version, + &ack_hmac); + write(cl, &verinfo, sizeof(verinfo)); + write(cl, &ack_hmac, sizeof(ack_hmac)); + break; } + case RETRIEVE_FILE: + { + hash_t encrypted_secret; + size_t len; + struct iomt *buildcode = NULL, *composefile = NULL; + void *contents = sp_retrieve_file(sp, + user_req.retrieve.user_id, + user_req.retrieve.file_idx, + user_req.retrieve.version, + &encrypted_secret, + &buildcode, + &composefile, + &len); + /* write everything (no HMAC; the client should do a + * RETRIEVE_INFO request separately) */ + write(cl, &encrypted_secret, sizeof(encrypted_secret)); + iomt_serialize(buildcode, write_to_fd, &cl); + iomt_serialize(composefile, write_to_fd, &cl); - write(cl, &ack_hmac, sizeof(ack_hmac)); + write(cl, &len, sizeof(len)); + write(cl, contents, len); + + break; + } + } } int sp_main(int sockfd) @@ -882,6 +922,8 @@ void sp_test(void) 1, 1, &key, + NULL, + NULL, &len); check("File retrieval 1", !memcmp(contents, "contents", 8) && len == 8); free(contents); diff --git a/service_provider.h b/service_provider.h index b55285c..be931a2 100644 --- a/service_provider.h +++ b/service_provider.h @@ -105,7 +105,7 @@ struct tm_request sp_modifyfile(struct service_provider *sp, /* Retrieve authenticated information on a version of a file; if * version is zero, default to the latest version. */ struct version_info sp_fileinfo(struct service_provider *sp, - uint64_t user_id, uint64_t file_id, + uint64_t user_id, uint64_t file_idx, uint64_t version, hash_t *hmac); @@ -115,6 +115,8 @@ void *sp_retrieve_file(struct service_provider *sp, uint64_t file_idx, uint64_t version, hash_t *encrypted_secret, + struct iomt **buildcode, + struct iomt **composefile, size_t *len); int sp_main(int sockfd); diff --git a/trusted_module.c b/trusted_module.c index 2c021e3..9e310b3 100644 --- a/trusted_module.c +++ b/trusted_module.c @@ -682,12 +682,12 @@ struct tm_cert tm_request(struct trusted_module *tm, /* Untested. */ hash_t tm_verify_and_encrypt_secret(const struct trusted_module *tm, uint64_t file_idx, - uint64_t file_counter, + uint64_t file_version, uint64_t user_id, hash_t encrypted_secret, hash_t kf) { hash_t key = crypt_secret(encrypted_secret, - file_idx, file_counter, + file_idx, file_version, tm->user_keys[user_id - 1].key, tm->user_keys[user_id - 1].len); @@ -790,9 +790,9 @@ hash_t tm_retrieve_secret(const struct trusted_module *tm, return hash_xor(secret, pad); } -static hash_t sign_response(const struct trusted_module *tm, - const struct version_info *ver, - uint64_t user_id) +static hash_t sign_verinfo(const struct trusted_module *tm, + const struct version_info *ver, + uint64_t user_id) { return hmac_sha256(ver, sizeof(*ver), tm->user_keys[user_id - 1].key, @@ -810,13 +810,13 @@ static hash_t sign_response(const struct trusted_module *tm, * one). Finally, FR should be the latest file record certificate * issued by the module, reflecting the latest counter value and * ACL. */ -struct version_info tm_verify_file(const struct trusted_module *tm, - uint64_t user_id, - const struct tm_cert *rv1, hash_t rv1_hmac, - const struct tm_cert *rv2, hash_t rv2_hmac, - const struct tm_cert *fr, hash_t fr_hmac, - const struct tm_cert *vr, hash_t vr_hmac, - hash_t *response_hmac) +struct version_info tm_verify_fileinfo(const struct trusted_module *tm, + uint64_t user_id, + const struct tm_cert *rv1, hash_t rv1_hmac, + const struct tm_cert *rv2, hash_t rv2_hmac, + const struct tm_cert *fr, hash_t fr_hmac, + const struct tm_cert *vr, hash_t vr_hmac, + hash_t *response_hmac) { struct version_info verinfo = verinfo_null; @@ -853,7 +853,7 @@ struct version_info tm_verify_file(const struct trusted_module *tm, if(is_zero(rv1->rv.val)) { verinfo.idx = rv1->rv.idx; - *response_hmac = sign_response(tm, &verinfo, user_id); + *response_hmac = sign_verinfo(tm, &verinfo, user_id); return verinfo; } @@ -911,7 +911,7 @@ struct version_info tm_verify_file(const struct trusted_module *tm, /* Prepare the denial response now so we can fail if needed. */ verinfo.idx = fr->fr.idx; - *response_hmac = sign_response(tm, &verinfo, rv2->rv.idx); + *response_hmac = sign_verinfo(tm, &verinfo, user_id); if(hash_to_u64(rv2->rv.val) < 1) { @@ -926,7 +926,7 @@ struct version_info tm_verify_file(const struct trusted_module *tm, verinfo.version = vr->vr.version; verinfo.lambda = vr->vr.hash; - *response_hmac = sign_response(tm, &verinfo, user_id); + *response_hmac = sign_verinfo(tm, &verinfo, user_id); return verinfo; } diff --git a/trusted_module.h b/trusted_module.h index 7e1cd4b..18dbd12 100644 --- a/trusted_module.h +++ b/trusted_module.h @@ -172,7 +172,7 @@ struct tm_cert tm_request(struct trusted_module *tm, hash_t *ack_hmac); /* enc_secret is encrypted by the user by XOR'ing the file encryption - * key with h(f + c_f + K), where + denotes concatenation. The purpose + * key with h(f + q + K), where + denotes concatenation. The purpose * of this function is to decrypt the secret passed by the user, * verify its integrity against kf=HMAC(secret, key=f_idx), and then * re-encrypt the secret with the module's secret key. This is the @@ -180,7 +180,7 @@ struct tm_cert tm_request(struct trusted_module *tm, /* Untested. */ hash_t tm_verify_and_encrypt_secret(const struct trusted_module *tm, uint64_t file_idx, - uint64_t file_counter, + uint64_t file_version, uint64_t user_id, hash_t encrypted_secret, hash_t kf); @@ -197,13 +197,13 @@ hash_t tm_retrieve_secret(const struct trusted_module *tm, const struct tm_cert *fr, hash_t fr_hmac, hash_t encrypted_secret, hash_t kf); -struct version_info tm_verify_file(const struct trusted_module *tm, - uint64_t user_id, - const struct tm_cert *rv1, hash_t rv1_hmac, - const struct tm_cert *rv2, hash_t rv2_hmac, - const struct tm_cert *fr, hash_t fr_hmac, - const struct tm_cert *vr, hash_t vr_hmac, - hash_t *response_hmac); +struct version_info tm_verify_fileinfo(const struct trusted_module *tm, + uint64_t user_id, + const struct tm_cert *rv1, hash_t rv1_hmac, + const struct tm_cert *rv2, hash_t rv2_hmac, + const struct tm_cert *fr, hash_t fr_hmac, + const struct tm_cert *vr, hash_t vr_hmac, + hash_t *response_hmac); const char *tm_geterror(void); |