aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--service_provider.c39
-rw-r--r--service_provider.h2
-rw-r--r--trusted_module.c104
-rw-r--r--trusted_module.h18
4 files changed, 151 insertions, 12 deletions
diff --git a/service_provider.c b/service_provider.c
index 6d69010..e136917 100644
--- a/service_provider.c
+++ b/service_provider.c
@@ -396,7 +396,7 @@ struct user_request sp_createfile(struct service_provider *sp,
struct user_request sp_modifyfile(struct service_provider *sp,
uint64_t user_id, const void *key, size_t keylen,
uint64_t file_idx,
- hash_t encrypted_secret,
+ hash_t encrypted_secret, hash_t kf,
const void *encrypted_file, size_t filelen,
hash_t *ack_hmac)
{
@@ -442,8 +442,17 @@ struct user_request sp_modifyfile(struct service_provider *sp,
struct tm_cert vr;
hash_t vr_hmac, fr_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, NULL);
+ struct tm_cert new_fr = sp_request(sp,
+ &mod, req_hmac,
+ &fr_hmac,
+ &vr, &vr_hmac,
+ ack_hmac,
+ encrypted_secret, kf,
+ encrypted_file, filelen,
+ NULL);
+
+ /* We return the request because that is how the module's
+ * authentication is done. */
if(new_fr.type == FR)
return mod;
return req_null;
@@ -457,11 +466,17 @@ static bool ack_verify(const struct user_request *req,
return hash_equals(hmac, correct);
}
+#include <time.h>
+
void sp_test(void)
{
- /* 2^10 = 1024 leaves ought to be enough for anybody */
- int logleaves = 10;
+ int logleaves = 4;
+ printf("Initializing IOMT with %llu nodes.\n", 1ULL << logleaves);
+
+ clock_t start = clock();
struct service_provider *sp = sp_new("a", 1, logleaves);
+ clock_t stop = clock();
+ printf("%.1f placeholder insertions per second\n", (double)(1ULL << logleaves) * CLOCKS_PER_SEC / (stop - start));
check("Tree initialization", sp != NULL);
@@ -470,12 +485,20 @@ void sp_test(void)
check("File creation", ack_verify(&req, "a", 1, ack_hmac));
- req = sp_modifyfile(sp, 1, "a", 1, 1, hash_null, NULL, 0, &ack_hmac);
+#define N_MODIFY 1000
+ start = clock();
+ for(int i = 0; i < N_MODIFY; ++i)
+ req = sp_modifyfile(sp, 1, "a", 1, 1, hash_null, hash_null, NULL, 0, &ack_hmac);
+ stop = clock();
+ printf("%.1f modifications per second\n", (double)N_MODIFY * CLOCKS_PER_SEC / (stop - start));
check("File modification", ack_verify(&req, "a", 1, ack_hmac));
- printf("CDI-IOMT contents: ");
- iomt_dump(sp->iomt);
+ if(logleaves < 5)
+ {
+ printf("CDI-IOMT contents: ");
+ iomt_dump(sp->iomt);
+ }
/* test tree initilization (only simple case) */
if(logleaves == 1)
diff --git a/service_provider.h b/service_provider.h
index e6180b1..2529af9 100644
--- a/service_provider.h
+++ b/service_provider.h
@@ -32,7 +32,7 @@ struct user_request sp_createfile(struct service_provider *sp,
struct user_request sp_modifyfile(struct service_provider *sp,
uint64_t user_id, const void *key, size_t keylen,
uint64_t file_idx,
- hash_t encrypted_secret,
+ hash_t encrypted_secret, hash_t kf,
const void *encrypted_file, size_t filelen,
hash_t *ack_hmac);
diff --git a/trusted_module.c b/trusted_module.c
index f9f0472..e55cf3e 100644
--- a/trusted_module.c
+++ b/trusted_module.c
@@ -37,7 +37,7 @@ struct trusted_module {
static void tm_setroot(struct trusted_module *tm, hash_t newroot)
{
- printf("TM: %s -> %s\n", hash_format(tm->root, 4).str, hash_format(newroot, 4).str);
+ //printf("TM: %s -> %s\n", hash_format(tm->root, 4).str, hash_format(newroot, 4).str);
tm->root = newroot;
}
@@ -246,7 +246,7 @@ struct tm_cert tm_cert_equiv(const struct trusted_module *tm,
/* nu must be of the form [x,y,x,y] to indicate that x is a child of y */
/* also, if b > 0 and nonexist != NULL, this function will generate a
* certificate indicating that no node with index b exists with root
- * y*/
+ * y */
struct tm_cert tm_cert_record_verify(const struct trusted_module *tm,
const struct tm_cert *nu, hash_t hmac,
const struct iomt_node *node,
@@ -806,6 +806,106 @@ 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)
+{
+ return hmac_sha256(ver, sizeof(*ver),
+ tm->user_keys[user_id - 1].key,
+ tm->user_keys[user_id - 1].len);
+}
+
+/* Verify the integrity of file information passed in the four
+ * certificates by checking it against the current root; response is
+ * authenticated with HMAC(response, user_key). RV1 should verify the
+ * current file counter value against the current root. RV2 should
+ * prove that the user has the proper access level in the ACL. VR
+ * should be signed and can be any version (not just the latest
+ * 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,
+ 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;
+
+ /* No authenticated response if the parameters are incorrect or
+ * improperly signed; it is the service provider's responsibility
+ * to make sure these are correct, because if they are not, the
+ * user will not receive the expected authentication. */
+ if(!rv1 || !rv2 || !fr || !vr)
+ {
+ tm_seterror("null paramter");
+ return verinfo_null;
+ }
+
+ if(!cert_verify(tm, rv1, rv1_hmac) ||
+ !cert_verify(tm, rv2, rv2_hmac) ||
+ !cert_verify(tm, fr, fr_hmac) ||
+ !cert_verify(tm, vr, vr_hmac))
+
+ {
+ tm_seterror("certificate signature invalid");
+ return verinfo_null;
+ }
+
+ /* 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);
+
+ /* Check RV1 against root */
+ if(!hash_equals(rv1->rv.root, tm->root))
+ {
+ tm_seterror("RV1 does not reflect current root");
+ return verinfo;
+ }
+
+ /* Ensure that all file indices match */
+ if(rv1->rv.idx != fr->fr.idx ||
+ rv1->rv.idx != vr->vr.idx)
+ {
+ tm_seterror("certificate indices do not match");
+ return verinfo;
+ }
+
+ /* Ensure that the FR certificate is fresh by checking the counter
+ * against the value of RV1 (which is guaranteed to be fresh) */
+ if(hash_to_u64(rv1->rv.val) != fr->fr.counter)
+ {
+ tm_seterror("FR counter is not fresh");
+ return verinfo;
+ }
+
+ /* Make sure that RV2's root is the file ACL */
+ if(!hash_equals(rv2->rv.root, fr->fr.acl))
+ {
+ tm_seterror("RV2 does not have file ACL as root");
+ return verinfo;
+ }
+
+ /* Check whether file exists and that the access level is sufficient */
+ if(is_zero(rv1->rv.val) ||
+ hash_to_u64(rv2->rv.val) < 1)
+ {
+ tm_seterror("insufficient permissions or file does not exist");
+ return verinfo;
+ }
+
+ /* We have verified that the file exists and can convey this to
+ * the user */
+ verinfo.counter = fr->fr.counter;
+ verinfo.max_version = fr->fr.version;
+ verinfo.version = vr->vr.version;
+ verinfo.lambda = vr->vr.hash;
+
+ *response_hmac = sign_response(tm, &verinfo, rv2->rv.idx);
+ return verinfo;
+}
+
/* self-test */
void tm_test(void)
{
diff --git a/trusted_module.h b/trusted_module.h
index 27dc8ec..1aab731 100644
--- a/trusted_module.h
+++ b/trusted_module.h
@@ -43,7 +43,8 @@ struct tm_cert {
struct {
uint64_t idx;
uint64_t version;
- hash_t hash; /* commitment to contents, key, and index */
+ hash_t hash; /* lambda value: the commitment to contents,
+ * key, and index */
} vr; /* version record (of a file) */
};
};
@@ -85,8 +86,16 @@ struct user_request {
};
};
+struct version_info {
+ uint64_t idx;
+ uint64_t counter;
+ uint64_t version, max_version;
+ hash_t lambda; /* equal to HMAC(h(encrypted_contents), key=HMAC(key, file_idx)) */
+};
+
static const struct user_request req_null = { REQ_NONE };
static const struct tm_cert cert_null = { CERT_NONE };
+static const struct version_info verinfo_null = { 0 };
/* creates 1 user with given shared secret */
struct trusted_module *tm_new(const void *key, size_t keylen);
@@ -185,6 +194,13 @@ hash_t tm_retrieve_secret(const struct trusted_module *tm,
const struct tm_cert *fr, hash_t fr_hmac,
hash_t secret, hash_t kf);
+struct version_info tm_verify_file(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,
+ const struct tm_cert *vr, hash_t vr_hmac,
+ hash_t *response_hmac);
+
hash_t ack_sign(const struct user_request *req, const void *key, size_t keylen);
const char *tm_geterror(void);