aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorFranklin Wei <me@fwei.tk>2018-06-22 22:57:25 -0400
committerFranklin Wei <me@fwei.tk>2018-06-22 22:57:25 -0400
commit77094976e17f3c1151dc7210815f0d47029ea54b (patch)
tree0c10179dacb7d6a696132c1cd63aba1559c8c437
parent898454639359d49ddb8cb098634473e9207c6e49 (diff)
downloadcsaa-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--.gitignore5
-rw-r--r--client.c101
-rw-r--r--crypto.c17
-rw-r--r--crypto.h5
-rw-r--r--service_provider.c80
-rw-r--r--service_provider.h4
-rw-r--r--trusted_module.c30
-rw-r--r--trusted_module.h18
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
diff --git a/client.c b/client.c
index ba6066e..27e8a4d 100644
--- a/client.c
+++ b/client.c
@@ -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;
diff --git a/crypto.c b/crypto.c
index f819fda..4125f7b 100644
--- a/crypto.c
+++ b/crypto.c
@@ -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
diff --git a/crypto.h b/crypto.h
index db91ffa..fe251d9 100644
--- a/crypto.h
+++ b/crypto.h
@@ -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);