diff options
-rw-r--r-- | helper.c | 44 | ||||
-rw-r--r-- | helper.h | 17 | ||||
-rw-r--r-- | service_provider.c | 88 | ||||
-rw-r--r-- | service_provider.h | 9 | ||||
-rw-r--r-- | trusted_module.c | 6 | ||||
-rw-r--r-- | trusted_module.h | 30 |
6 files changed, 174 insertions, 20 deletions
@@ -47,6 +47,9 @@ struct tm_cert cert_rv(const struct trusted_module *tm, b, nonexist, hmac_nonexist); } +/* Fill out a user_request struct to create a file with the index + * given in file_node->idx with the user added with level 3 access in + * the ACL. */ struct user_request req_filecreate(const struct trusted_module *tm, uint64_t user_id, const struct iomt_node *file_node, @@ -81,6 +84,9 @@ struct user_request req_filecreate(const struct trusted_module *tm, return req; } +/* Fill out a user_request struct to modify an existing file's + * contents, given the previously generated FR certificate, and the + * ACL node giving the user's access rights. */ struct user_request req_filemodify(const struct trusted_module *tm, const struct tm_cert *fr_cert, hash_t fr_hmac, const struct iomt_node *file_node, @@ -116,3 +122,41 @@ struct user_request req_filemodify(const struct trusted_module *tm, return req; } + +/* Fill out a user_request struct to modify a file's ACL. Same + * parameters as req_filemodify(), except the hash is the root of the + * new ACL. */ +struct user_request req_aclmodify(const struct trusted_module *tm, + const struct tm_cert *fr_cert, hash_t fr_hmac, + const struct iomt_node *file_node, + const hash_t *file_comp, const int *file_orders, size_t file_n, + const struct iomt_node *oldacl_node, + const hash_t *oldacl_comp, const int *oldacl_orders, size_t oldacl_n, + hash_t newacl_root) +{ + struct user_request req; + req.type = ACL_UPDATE; + + req.idx = file_node->idx; + req.counter = hash_to_u64(file_node->val); + + req.user_id = oldacl_node->idx; + + req.modify.fr_cert = *fr_cert; + req.modify.fr_hmac = fr_hmac; + + req.modify.rv_cert = cert_rv(tm, + oldacl_node, + oldacl_comp, oldacl_orders, oldacl_n, + &req.modify.rv_hmac, + 0, NULL, NULL); + + hash_t next_counter = u64_to_hash(req.counter + 1); + + req.modify.ru_cert = cert_ru(tm, file_node, next_counter, + file_comp, file_orders, file_n, + &req.modify.ru_hmac); + req.val = newacl_root; + + return req; +} @@ -13,11 +13,17 @@ struct tm_cert cert_rv(const struct trusted_module *tm, uint64_t b, struct tm_cert *nonexist, hash_t *hmac_nonexist); +/* Fill out a user_request struct to create a file with the index + * given in file_node->idx with the user added with level 3 access in + * the ACL. */ struct user_request req_filecreate(const struct trusted_module *tm, uint64_t user_id, const struct iomt_node *file_node, const hash_t *file_comp, const int *file_orders, size_t file_n); +/* Fill out a user_request struct to modify an existing file's + * contents, given the previously generated FR certificate, and the + * ACL node giving the user's access rights. */ struct user_request req_filemodify(const struct trusted_module *tm, const struct tm_cert *fr_cert, hash_t fr_hmac, const struct iomt_node *file_node, @@ -25,3 +31,14 @@ struct user_request req_filemodify(const struct trusted_module *tm, const struct iomt_node *acl_node, const hash_t *acl_comp, const int *acl_orders, size_t acl_n, hash_t fileval); + +/* Fill out a user_request struct to modify a file's ACL. Same + * parameters as req_filemodify(), except the hash is the root of the + * new ACL. */ +struct user_request req_aclmodify(const struct trusted_module *tm, + const struct tm_cert *fr_cert, hash_t fr_hmac, + const struct iomt_node *file_node, + const hash_t *file_comp, const int *file_orders, size_t file_n, + const struct iomt_node *oldacl_node, + const hash_t *oldacl_comp, const int *oldacl_orders, size_t oldacl_n, + hash_t newacl_root); diff --git a/service_provider.c b/service_provider.c index 8469d1a..7f87b72 100644 --- a/service_provider.c +++ b/service_provider.c @@ -12,12 +12,12 @@ #include "trusted_module.h" struct file_version { - hash_t kf; /* h(key, file_idx) */ - hash_t l; /* h(h(file contents), kf) */ - hash_t enc_key; /* XOR'd with h(kf, module secret) */ + hash_t kf; /* HMAC(key, file_idx) */ + hash_t l; /* HMAC(h(encrypted contents), kf) */ + hash_t encrypted_secret; /* XOR'd with HMAC(kf, module secret) */ - struct tm_cert cert; /* VR certificate */ - hash_t cert_hmac; + struct tm_cert vr_cert; /* VR certificate */ + hash_t vr_hmac; void *contents; size_t len; @@ -35,7 +35,7 @@ struct file_record { hash_t fr_hmac; struct file_version *versions; - int n_versions; + int nversions; }; struct service_provider { @@ -292,19 +292,39 @@ static struct file_record *lookup_record(struct service_provider *sp, int idx) /* We do not check to ensure that there are no duplicate file indices; * this is up to the caller */ -static void insert_record(struct service_provider *sp, struct file_record *rec) +static void append_record(struct service_provider *sp, const struct file_record *rec) { sp->records = realloc(sp->records, sizeof(struct file_record) * ++sp->nrecords); sp->records[sp->nrecords - 1] = *rec; } -/* this does the majority of the work that actually modifies or - * creates a file */ +static void append_version(struct file_record *rec, const struct file_version *ver) +{ + rec->versions = realloc(rec->versions, sizeof(struct file_version) * ++rec->nversions); + rec->versions[rec->nversions - 1] = *ver; +} + +/* This does the majority of the work that actually modifies or + * creates a file. It expects a filled and signed user_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, 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). + */ struct tm_cert sp_request(struct service_provider *sp, const struct user_request *req, hash_t req_hmac, hash_t *hmac_out, struct tm_cert *vr_out, hash_t *vr_hmac_out, - hash_t *ack_hmac_out) + hash_t *ack_hmac_out, + hash_t encrypted_secret, hash_t kf, + const void *encrypted_contents, + size_t contents_len) { struct tm_cert vr = cert_null; hash_t vr_hmac, ack_hmac, fr_hmac; @@ -325,13 +345,51 @@ struct tm_cert sp_request(struct service_provider *sp, need_insert = true; } - rec->version = fr.fr.version; rec->counter = fr.fr.counter; rec->fr_cert = fr; rec->fr_hmac = fr_hmac; + if(rec->version != fr.fr.version) + { + rec->version = fr.fr.version; + + struct file_version ver; + hash_t gamma = sha256(encrypted_contents, contents_len); + ver.l = hmac_sha256(&gamma, sizeof(gamma), + &kf, sizeof(kf)); + + if(!is_zero(encrypted_secret) && !is_zero(kf)) + { + /* File is encrypted */ + ver.encrypted_secret = tm_verify_and_encrypt_secret(sp->tm, + rec->idx, rec->counter, + req->user_id, + encrypted_secret, kf); + assert(!is_zero(ver.encrypted_secret)); + + /* We have no way of verifying that kf=HMAC(encryption + * secret, file index) ourselves; instead we rely on the + * module to do so for us. */ + ver.kf = kf; + } + else + { + ver.encrypted_secret = hash_null; + } + + ver.vr_cert = vr; + ver.vr_hmac = vr_hmac; + + append_version(rec, &ver); + } + if(need_insert) - insert_record(sp, rec); + { + append_record(sp, rec); + + /* append_record will make a copy */ + free(rec); + } /* update our tree */ sp->mt_leaves[req->idx - 1].val = u64_to_hash(fr.fr.counter); @@ -371,7 +429,8 @@ void sp_test(void) hash_t fr_hmac; hash_t ack_hmac; - struct tm_cert fr_cert = sp_request(sp, &req, req_hmac, &fr_hmac, NULL, NULL, &ack_hmac); + struct tm_cert fr_cert = sp_request(sp, &req, req_hmac, &fr_hmac, NULL, NULL, &ack_hmac, + hash_null, hash_null, NULL, 0); check(fr_cert.type == FR && fr_cert.fr.counter == 1 && @@ -394,7 +453,8 @@ void sp_test(void) struct tm_cert vr; hash_t vr_hmac; - struct tm_cert new_fr = sp_request(sp, &mod, req_hmac, &fr_hmac, &vr, &vr_hmac, &ack_hmac); + struct tm_cert new_fr = sp_request(sp, &mod, req_hmac, &fr_hmac, &vr, &vr_hmac, &ack_hmac, + hash_null, hash_null, "contents", 8); printf("File modification: "); check(new_fr.type == FR); diff --git a/service_provider.h b/service_provider.h index 883c9ea..6deb814 100644 --- a/service_provider.h +++ b/service_provider.h @@ -10,11 +10,16 @@ struct service_provider; struct service_provider *sp_new(const void *key, size_t keylen, int logleaves); + +/* see .c file for documentation */ struct tm_cert sp_request(struct service_provider *sp, const struct user_request *req, hash_t req_hmac, hash_t *hmac_out, - struct tm_cert *vr_out, hash_t *vr_hmac, - hash_t *ack_hmac); + struct tm_cert *vr_out, hash_t *vr_hmac_out, + hash_t *ack_hmac_out, + hash_t encrypted_secret, hash_t kf, + const void *encrypted_contents, + size_t contents_len); void sp_test(void); diff --git a/trusted_module.c b/trusted_module.c index 47bcfa2..b3db5b2 100644 --- a/trusted_module.c +++ b/trusted_module.c @@ -674,9 +674,9 @@ hash_t tm_verify_and_encrypt_secret(const struct trusted_module *tm, uint64_t file_idx, uint64_t file_counter, uint64_t user_id, - hash_t enc_secret, hash_t kf) + hash_t encrypted_secret, hash_t kf) { - hash_t pad; /* key = enc_secret ^ pad */ + hash_t pad; /* key = encrypted_secret ^ pad */ HMAC_CTX *ctx = HMAC_CTX_new(); HMAC_Init_ex(ctx, tm->user_keys[user_id - 1].key, tm->user_keys[user_id - 1].len, EVP_sha256(), NULL); @@ -687,7 +687,7 @@ hash_t tm_verify_and_encrypt_secret(const struct trusted_module *tm, HMAC_Final(ctx, pad.hash, NULL); HMAC_CTX_free(ctx); - hash_t key = hash_xor(enc_secret, pad); + hash_t key = hash_xor(encrypted_secret, pad); if(hash_equals(kf, hmac_sha256(key.hash, sizeof(key.hash), diff --git a/trusted_module.h b/trusted_module.h index 71d086e..8cdf65a 100644 --- a/trusted_module.h +++ b/trusted_module.h @@ -55,7 +55,10 @@ struct user_request { uint64_t counter; /* current counter value, 0 for creation */ hash_t val; /* for ACL update, val=[root of ACL IOMT], for file * update, val is a commitment to the contents, key, - * and index of the file */ + * and index of the file (specifically this is the + * value represented by lambda in Mohanty et al., + * equal to HMAC(h(encrypted contents), kf). Note that + * kf=HMAC(key, file_idx) */ union { /* if counter = 0 and type = ACL_UPDATE, create a new file with given ACL */ struct { @@ -155,4 +158,29 @@ struct tm_cert tm_request(struct trusted_module *tm, struct tm_cert *vr_out, hash_t *vr_hmac, 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 + * 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 + * F_rs() function described by Mohanty et al. */ +/* Untested. */ +hash_t tm_verify_and_encrypt_secret(const struct trusted_module *tm, + uint64_t file_idx, + uint64_t file_counter, + uint64_t user_id, + hash_t encrypted_secret, hash_t kf); + +/* Decrypt a previously encrypted secret, and then encrypt for receipt + * by a user. rv1 should bind the file index and counter to the + * current root. rv2 should verify the user's access level in the + * ACL. The index (which is a user id) given in rv2 will select the + * key used to encrypt the secret. As with + * tm_verify_and_encrypt_secret(), kf=HMAC(secret, key=f_idx). */ +/* Untested. */ +hash_t tm_retrieve_secret(const struct trusted_module *tm, + 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, + hash_t secret, hash_t kf); #endif |