aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorFranklin Wei <me@fwei.tk>2018-06-21 23:02:23 -0400
committerFranklin Wei <me@fwei.tk>2018-06-21 23:02:23 -0400
commit898454639359d49ddb8cb098634473e9207c6e49 (patch)
tree8b7de07e275ef115664aaf038d6c7a1d0cc75b4f
parent6f67db25e477a94fc7160fe1052329e41e1f9da7 (diff)
downloadcsaa-898454639359d49ddb8cb098634473e9207c6e49.zip
csaa-898454639359d49ddb8cb098634473e9207c6e49.tar.gz
csaa-898454639359d49ddb8cb098634473e9207c6e49.tar.bz2
csaa-898454639359d49ddb8cb098634473e9207c6e49.tar.xz
Add a separate client communicating by unix socket
This is pretty rough for now; the service provider only handles one client, and dies ungracefully when anything goes wrong. It seems to work, though.
-rw-r--r--Makefile9
-rw-r--r--client.c184
-rw-r--r--crypto.c79
-rw-r--r--crypto.h17
-rw-r--r--helper.c18
-rw-r--r--helper.h42
-rw-r--r--main.c65
-rw-r--r--service_provider.c184
-rw-r--r--service_provider.h97
-rw-r--r--test.c9
-rw-r--r--test.h3
-rw-r--r--trusted_module.c33
-rw-r--r--trusted_module.h15
13 files changed, 628 insertions, 127 deletions
diff --git a/Makefile b/Makefile
new file mode 100644
index 0000000..9016ba1
--- /dev/null
+++ b/Makefile
@@ -0,0 +1,9 @@
+all: client server Makefile
+CFLAGS = -g -Wall
+
+client: client.o crypto.o test.o
+ cc -o $@ $^ -lcrypto $(CFLAGS)
+server: service_provider.o crypto.o helper.o trusted_module.o main.o test.o
+ cc -o $@ $^ -lcrypto $(CFLAGS)
+clean:
+ rm -f *.o a.out client server
diff --git a/client.c b/client.c
new file mode 100644
index 0000000..ba6066e
--- /dev/null
+++ b/client.c
@@ -0,0 +1,184 @@
+/* Taken from
+ * https://github.com/troydhanson/network/blob/master/unixdomain/01.basic/cli.c */
+
+#define CLIENT
+#include "crypto.h"
+#include "service_provider.h"
+#include "trusted_module.h"
+#include "test.h"
+
+#include <sys/socket.h>
+#include <sys/un.h>
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <assert.h>
+
+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;
+ if(read(fd, &tmr, sizeof(tmr)) != sizeof(tmr))
+ {
+ perror("read");
+ exit(1);
+ }
+
+ assert(tmr.type != REQ_NONE);
+
+ switch(req->type)
+ {
+ case CREATE_FILE:
+ {
+ /* check request values to make sure they actually do what we
+ * want */
+ struct iomt_node acl_node = { req->create.user_id, req->create.user_id, u64_to_hash(3) };
+ if(tmr.type != ACL_UPDATE ||
+ tmr.idx == 0 ||
+ tmr.counter != 0 ||
+ !hash_equals(hash_node(&acl_node), tmr.val))
+ return req_null;
+ break;
+ }
+ case MODIFY_FILE:
+ {
+ /* TODO */
+ break;
+ }
+ case MODIFY_ACL:
+ {
+ /* TODO */
+ break;
+ }
+ }
+
+ hash_t hmac = hmac_sha256(&tmr, sizeof(tmr), "a", 1);
+ write(fd, &hmac, sizeof(hmac));
+
+ return tmr;
+}
+
+static bool verify_sp_ack(int fd, const struct tm_request *tmr)
+{
+ hash_t hmac = hash_null;
+ if(read(fd, &hmac, sizeof(hmac)) != sizeof(hmac))
+ {
+ perror("read 2");
+ exit(2);
+ }
+
+ 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);
+}
+
+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)
+{
+ write(fd, req, sizeof(*req));
+ /* write additional data */
+ switch(req->type)
+ {
+ case MODIFY_ACL:
+ /* send ACL */
+ iomt_serialize(new_acl, write_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);
+
+ /* prefix file with size */
+ write(fd, &len, sizeof(len));
+ write(fd, file_contents, len);
+ break;
+ case CREATE_FILE:
+ case RETRIEVE_INFO:
+ case RETRIEVE_FILE:
+ /* no additional data needed, fall through */
+ default:
+ break;
+ }
+
+ struct tm_request tmr;
+
+ /* sign request */
+ if(need_sign(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);
+ }
+
+ /* verify acknowledgement */
+ return verify_sp_ack(fd, &tmr);
+}
+
+int connect_to_service(const char *sockpath)
+{
+ struct sockaddr_un addr;
+ int fd;
+
+ if ( (fd = socket(AF_UNIX, SOCK_STREAM, 0)) == -1) {
+ perror("socket error");
+ exit(-1);
+ }
+
+ memset(&addr, 0, sizeof(addr));
+ addr.sun_family = AF_UNIX;
+ if (*socket_path == '\0') {
+ *addr.sun_path = '\0';
+ strncpy(addr.sun_path+1, socket_path+1, sizeof(addr.sun_path)-2);
+ } else {
+ strncpy(addr.sun_path, socket_path, sizeof(addr.sun_path)-1);
+ }
+
+ if (connect(fd, (struct sockaddr*)&addr, sizeof(addr)) == -1) {
+ perror("connect error");
+ exit(-1);
+ }
+
+ return fd;
+}
+
+int main(int argc, char *argv[]) {
+ char buf[100];
+ int fd,rc;
+
+ if (argc > 1) socket_path=argv[1];
+
+ fd = connect_to_service(socket_path);
+
+ struct user_request req;
+ req.type = CREATE_FILE;
+ req.create.user_id = 1;
+
+ check("Client file creation", exec_request(fd, &req, NULL, NULL, NULL, NULL, 0));
+ close(fd);
+ fd = connect_to_service(socket_path);
+
+ req.type = MODIFY_FILE;
+ req.modify_file.user_id = 1;
+ req.modify_file.file_idx = 1;
+ 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));
+ close(fd);
+
+ return 0;
+}
diff --git a/crypto.c b/crypto.c
index 1045809..f819fda 100644
--- a/crypto.c
+++ b/crypto.c
@@ -1,4 +1,5 @@
#include "crypto.h"
+#include "trusted_module.h"
#include "test.h"
#include <string.h>
@@ -374,6 +375,51 @@ struct iomt *iomt_dup(const struct iomt *tree)
return newtree;
}
+/* TODO: error checking */
+uint64_t read_u64(int (*read_fn)(void *userdata, void *buf, size_t len), void *userdata)
+{
+ uint64_t n;
+ read_fn(userdata, &n, sizeof(n));
+ return n;
+}
+
+void write_u64(void (*write_fn)(void *userdata, const void *data, size_t len),
+ void *userdata, uint64_t n)
+{
+ write_fn(userdata, &n, sizeof(n));
+}
+
+
+void iomt_serialize(const struct iomt *tree,
+ void (*write_fn)(void *userdata, const void *data, size_t len),
+ void *userdata)
+{
+ /* leafcount isn't needed */
+ if(tree)
+ {
+ write_u64(write_fn, userdata, tree->mt_logleaves);
+
+ write_fn(userdata, tree->mt_nodes, sizeof(hash_t) * (2 * tree->mt_leafcount - 1));
+ write_fn(userdata, tree->mt_leaves, sizeof(struct iomt_node) * tree->mt_leafcount);
+ }
+ else
+ write_u64(write_fn, userdata, 0);
+}
+
+struct iomt *iomt_deserialize(int (*read_fn)(void *userdata, void *buf, size_t len),
+ void *userdata)
+{
+ uint64_t logleaves = read_u64(read_fn, userdata);
+ if(!logleaves)
+ return NULL;
+ struct iomt *tree = iomt_new(logleaves);
+
+ read_fn(userdata, tree->mt_nodes, sizeof(hash_t) * (2 * tree->mt_leafcount - 1));
+ read_fn(userdata, tree->mt_leaves, sizeof(struct iomt_node) * tree->mt_leafcount);
+
+ return tree;
+}
+
void iomt_free(struct iomt *tree)
{
if(tree)
@@ -522,8 +568,40 @@ hash_t calc_lambda(hash_t gamma, const struct iomt *buildcode, const struct iomt
return h;
}
+/* Generate a signed acknowledgement for successful completion of a
+ * request. We append a zero byte to the user request and take the
+ * HMAC. */
+hash_t ack_sign(const struct tm_request *req, int nzeros, const void *key, size_t keylen)
+{
+ HMAC_CTX *ctx = HMAC_CTX_new();
+ HMAC_Init_ex(ctx,
+ key, keylen,
+ EVP_sha256(), NULL);
+
+ HMAC_Update(ctx, (const unsigned char*)req, sizeof(*req));
+
+ unsigned char zero = 0;
+ for(int i = 0; i < nzeros; ++i)
+ HMAC_Update(ctx, &zero, 1);
+
+ hash_t hmac;
+ HMAC_Final(ctx, hmac.hash, NULL);
+ HMAC_CTX_free(ctx);
+
+ return hmac;
+}
+
+bool ack_verify(const struct tm_request *req,
+ const void *secret, size_t secret_len,
+ hash_t hmac)
+{
+ hash_t correct = ack_sign(req, 1, secret, secret_len);
+ return hash_equals(hmac, correct);
+}
+
void crypto_test(void)
{
+#if 1
int *orders;
int *comp = bintree_complement(6, 4, &orders);
int correct[] = { 22, 9, 3, 2 };
@@ -570,4 +648,5 @@ void crypto_test(void)
//dump_hash(root2);
check("Merkle compute", hash_equals(root1, root2));
}
+#endif
}
diff --git a/crypto.h b/crypto.h
index 3d824e6..db91ffa 100644
--- a/crypto.h
+++ b/crypto.h
@@ -4,6 +4,8 @@
#include <stddef.h>
#include <stdint.h>
+struct tm_request;
+
/* Various useful cryptographic functions; shared between TM and SP. */
/* we use SHA256 for h() */
@@ -105,6 +107,13 @@ void iomt_update_leaf_hash(struct iomt *tree, uint64_t leafidx,
/* Create an IOMT where the leaves are the hash of file lines */
struct iomt *iomt_from_lines(const char *filename);
+void iomt_serialize(const struct iomt *tree,
+ void (*write_fn)(void *userdata, const void *data, size_t len),
+ void *userdata);
+
+struct iomt *iomt_deserialize(int (*read_fn)(void *userdata, void *buf, size_t len),
+ void *userdata);
+
void iomt_fill(struct iomt *tree);
void iomt_dump(const struct iomt *tree);
@@ -132,6 +141,14 @@ hash_t crypt_secret(hash_t encrypted_secret,
hash_t calc_lambda(hash_t gamma, const struct iomt *buildcode, const struct iomt *composefile, hash_t kf);
+/* Generate a signed acknowledgement for successful completion of a
+ * request. We append a zero byte to the user request and take the
+ * HMAC. */
+hash_t ack_sign(const struct tm_request *req, int nzeros, const void *key, size_t keylen);
+bool ack_verify(const struct tm_request *req,
+ const void *secret, size_t secret_len,
+ hash_t hmac);
+
/* self-test */
void crypto_test(void);
#endif
diff --git a/helper.c b/helper.c
index 97edd7a..e72d39f 100644
--- a/helper.c
+++ b/helper.c
@@ -90,16 +90,16 @@ struct tm_cert cert_rv_by_idx(const struct trusted_module *tm,
return cert;
}
-/* Fill out a user_request struct to create a file with the index
+/* Fill out a tm_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,
+struct tm_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)
{
/* construct a request to create a file */
- struct user_request req = req_null;
+ struct tm_request req = req_null;
req.idx = file_node->idx;
req.user_id = user_id;
req.type = ACL_UPDATE;
@@ -127,10 +127,10 @@ struct user_request req_filecreate(const struct trusted_module *tm,
return req;
}
-/* Fill out a user_request struct to modify an existing file's
+/* Fill out a tm_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,
+struct tm_request req_filemodify(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,
@@ -139,7 +139,7 @@ struct user_request req_filemodify(const struct trusted_module *tm,
hash_t fileval)
{
/* modification */
- struct user_request req = req_null;
+ struct tm_request req = req_null;
req.type = FILE_UPDATE;
req.idx = file_node->idx;
@@ -166,10 +166,10 @@ 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
+/* Fill out a tm_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,
+struct tm_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,
@@ -177,7 +177,7 @@ struct user_request req_aclmodify(const struct trusted_module *tm,
const hash_t *oldacl_comp, const int *oldacl_orders, size_t oldacl_n,
hash_t newacl_root)
{
- struct user_request req = req_null;
+ struct tm_request req = req_null;
req.type = ACL_UPDATE;
req.idx = file_node->idx;
diff --git a/helper.h b/helper.h
index 6bce20b..1ad948e 100644
--- a/helper.h
+++ b/helper.h
@@ -21,32 +21,32 @@ struct tm_cert cert_rv_by_idx(const struct trusted_module *tm,
uint64_t idx,
hash_t *hmac_out);
-/* Fill out a user_request struct to create a file with the index
+/* Fill out a tm_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);
+struct tm_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
+/* Fill out a tm_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,
- const hash_t *file_comp, const int *file_orders, size_t file_n,
- const struct iomt_node *acl_node,
- const hash_t *acl_comp, const int *acl_orders, size_t acl_n,
- hash_t fileval);
+struct tm_request req_filemodify(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 *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
+/* Fill out a tm_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 tm_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/main.c b/main.c
new file mode 100644
index 0000000..567a441
--- /dev/null
+++ b/main.c
@@ -0,0 +1,65 @@
+#include "service_provider.h"
+#include "test.h"
+
+#include <signal.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <sys/un.h>
+
+int bind_unix_socket(const char *fname)
+{
+ int sockfd = socket(AF_UNIX, SOCK_STREAM, 0);
+
+ struct sockaddr_un addr;
+ memset(&addr, 0, sizeof(addr));
+ addr.sun_family = AF_UNIX;
+ strncpy(addr.sun_path, fname, sizeof(addr.sun_path) - 1);
+ if(bind(sockfd, (struct sockaddr*) &addr, sizeof(addr)) < 0)
+ return -1;
+
+ return sockfd;
+}
+
+static const char *cleanup_socket = NULL;
+void cleanup(void)
+{
+ if(cleanup_socket)
+ unlink(cleanup_socket);
+}
+
+void sigint(int sig)
+{
+ cleanup();
+ exit(1);
+}
+
+void run_tests(void)
+{
+ crypto_test();
+ tm_test();
+ sp_test();
+}
+
+int main()
+{
+ run_tests();
+
+ const char *socket_name = "socket";
+ int sockfd;
+ if((sockfd = bind_unix_socket(socket_name)) < 0)
+ {
+ perror("bind");
+ return 1;
+ }
+
+ cleanup_socket = socket_name;
+
+ atexit(cleanup);
+ signal(SIGINT, sigint);
+
+ sp_main(sockfd);
+}
diff --git a/service_provider.c b/service_provider.c
index 421d377..5dc033b 100644
--- a/service_provider.c
+++ b/service_provider.c
@@ -5,6 +5,10 @@
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
+#include <unistd.h>
+
+#include <sys/types.h>
+#include <sys/socket.h>
#include "crypto.h"
#include "helper.h"
@@ -237,7 +241,7 @@ static void append_version(struct file_record *rec, const struct file_version *v
}
/* This does the majority of the work that actually modifies or
- * creates a file. It expects a filled and signed user_request
+ * creates a file. It expects a filled and signed tm_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 |
@@ -254,7 +258,7 @@ static void append_version(struct file_record *rec, const struct file_version *v
* is essentially an ACL update), the ACL will be set to
* new_acl. `new_acl' must be in persistent storage. */
struct tm_cert sp_request(struct service_provider *sp,
- const struct user_request *req, hash_t req_hmac,
+ const struct tm_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,
@@ -368,9 +372,11 @@ struct tm_cert sp_request(struct service_provider *sp,
return fr;
}
-struct user_request sp_createfile(struct service_provider *sp,
- uint64_t user_id, const void *key, size_t keylen,
- hash_t *ack_hmac)
+struct tm_request sp_createfile(struct service_provider *sp,
+ uint64_t user_id,
+ hash_t (*sign_request)(void *userdata, const struct tm_request *req),
+ void *userdata,
+ hash_t *ack_hmac)
{
int i;
@@ -395,12 +401,12 @@ struct user_request sp_createfile(struct service_provider *sp,
0,
user_id, user_id, u64_to_hash(3));
- struct user_request req = req_filecreate(sp->tm,
+ struct tm_request req = req_filecreate(sp->tm,
i + 1,
sp->iomt->mt_leaves + i,
file_comp, file_orders, sp->iomt->mt_logleaves);
- hash_t req_hmac = hmac_sha256(&req, sizeof(req), key, keylen);
+ hash_t req_hmac = sign_request(userdata, &req);
hash_t fr_hmac;
struct tm_cert fr_cert = sp_request(sp,
@@ -424,11 +430,13 @@ struct user_request sp_createfile(struct service_provider *sp,
}
/* Expects ACL root to already be calculated */
-struct user_request sp_modifyacl(struct service_provider *sp,
- uint64_t user_id, const void *key, size_t keylen,
- uint64_t file_idx,
- struct iomt *new_acl,
- hash_t *ack_hmac)
+struct tm_request sp_modifyacl(struct service_provider *sp,
+ uint64_t user_id,
+ hash_t (*sign_request)(void *userdata, const struct tm_request *req),
+ void *userdata,
+ uint64_t file_idx,
+ struct iomt *new_acl,
+ hash_t *ack_hmac)
{
/* modification */
struct file_record *rec = lookup_record(sp, file_idx);
@@ -447,7 +455,7 @@ struct user_request sp_modifyacl(struct service_provider *sp,
acl_node - rec->acl->mt_leaves,
&acl_orders);
- struct user_request req = req_aclmodify(sp->tm,
+ struct tm_request req = req_aclmodify(sp->tm,
&rec->fr_cert, rec->fr_hmac,
file_node,
file_comp, file_orders, sp->iomt->mt_logleaves,
@@ -460,7 +468,7 @@ struct user_request sp_modifyacl(struct service_provider *sp,
free(acl_comp);
free(acl_orders);
- hash_t req_hmac = hmac_sha256(&req, sizeof(req), key, keylen);
+ hash_t req_hmac = sign_request(userdata, &req);
struct tm_cert new_fr = sp_request(sp,
&req, req_hmac,
@@ -477,13 +485,15 @@ struct user_request sp_modifyacl(struct service_provider *sp,
return req_null;
}
-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 kf,
- const struct iomt *buildcode, const struct iomt *composefile,
- const void *encrypted_file, size_t filelen,
- hash_t *ack_hmac)
+struct tm_request sp_modifyfile(struct service_provider *sp,
+ uint64_t user_id,
+ hash_t (*sign_request)(void *userdata, const struct tm_request *req),
+ void *userdata,
+ uint64_t file_idx,
+ hash_t encrypted_secret, hash_t kf,
+ const struct iomt *buildcode, const struct iomt *composefile,
+ const void *encrypted_file, size_t filelen,
+ hash_t *ack_hmac)
{
/* modification */
struct file_record *rec = lookup_record(sp, file_idx);
@@ -505,7 +515,7 @@ struct user_request sp_modifyfile(struct service_provider *sp,
hash_t gamma = sha256(encrypted_file, filelen);
hash_t lambda = calc_lambda(gamma, buildcode, composefile, kf);
- struct user_request req = req_filemodify(sp->tm,
+ struct tm_request req = req_filemodify(sp->tm,
&rec->fr_cert, rec->fr_hmac,
file_node,
file_comp, file_orders, sp->iomt->mt_logleaves,
@@ -517,7 +527,7 @@ struct user_request sp_modifyfile(struct service_provider *sp,
free(file_orders);
free(acl_orders);
- hash_t req_hmac = hmac_sha256(&req, sizeof(req), key, keylen);
+ hash_t req_hmac = sign_request(userdata, &req);
struct tm_cert vr;
hash_t vr_hmac, fr_hmac;
@@ -539,14 +549,6 @@ struct user_request sp_modifyfile(struct service_provider *sp,
return req_null;
}
-static bool ack_verify(const struct user_request *req,
- const void *secret, size_t secret_len,
- hash_t hmac)
-{
- hash_t correct = ack_sign(req, 1, secret, secret_len);
- return hash_equals(hmac, correct);
-}
-
/* Retrieve authenticated information (using the user's secret as the
* key) on a version of a file; if version is zero, default to the
* latest version. If the file does not exist, the function will still
@@ -701,8 +703,113 @@ void *sp_retrieve_file(struct service_provider *sp,
return ret;
}
+static hash_t get_client_signature(void *userdata, const struct tm_request *req)
+{
+ int *fd = userdata;
+ write(*fd, req, sizeof(*req));
+
+ hash_t hmac;
+ read(*fd, &hmac, sizeof(hmac));
+ 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 */
+ struct user_request user_req;
+ if(read(cl, &user_req, sizeof(user_req)) != sizeof(user_req))
+ return;
+
+ hash_t ack_hmac = hash_null;
+
+ switch(user_req.type)
+ {
+ case CREATE_FILE:
+ sp_createfile(sp, user_req.create.user_id, get_client_signature, &cl, &ack_hmac);
+ break;
+ case MODIFY_ACL:
+ {
+ struct iomt *acl = iomt_deserialize(read_fd, &cl);
+ sp_modifyacl(sp,
+ user_req.modify_acl.user_id,
+ get_client_signature,
+ &cl,
+ user_req.modify_acl.file_idx,
+ acl,
+ &ack_hmac);
+ iomt_free(acl);
+ break;
+ }
+ case MODIFY_FILE:
+ {
+ struct iomt *buildcode = iomt_deserialize(read_fd, &cl);
+ struct iomt *composefile = iomt_deserialize(read_fd, &cl);
+ size_t filelen;
+ read(cl, &filelen, sizeof(filelen));
+ void *filebuf = malloc(filelen);
+ read(cl, filebuf, filelen);
+
+ sp_modifyfile(sp,
+ user_req.modify_file.user_id,
+ get_client_signature,
+ &cl,
+ user_req.modify_file.file_idx,
+ user_req.modify_file.encrypted_secret,
+ user_req.modify_file.kf,
+ buildcode,
+ composefile,
+ filebuf, filelen,
+ &ack_hmac);
+ iomt_free(buildcode);
+ iomt_free(composefile);
+ }
+ }
+
+ write(cl, &ack_hmac, sizeof(ack_hmac));
+}
+
+int sp_main(int sockfd)
+{
+#define BACKLOG 10
+
+ if(listen(sockfd, BACKLOG) < 0)
+ {
+ perror("listen");
+ return 1;
+ }
+
+ int logleaves = 8;
+ struct service_provider *sp = sp_new("a", 1, logleaves);
+
+ while(1)
+ {
+ int cl;
+
+ if((cl = accept(sockfd, NULL, NULL)) < 0)
+ {
+ perror("accept");
+ return 1;
+ }
+
+ sp_handle_client(sp, cl);
+ close(cl);
+ }
+}
+
#include <time.h>
+static hash_t test_sign_request(void *userdata, const struct tm_request *req)
+{
+ const char *str = userdata;
+ return hmac_sha256(req, sizeof(*req), str, strlen(str));
+}
+
void sp_test(void)
{
int logleaves = 5;
@@ -717,7 +824,7 @@ void sp_test(void)
{
hash_t ack_hmac;
- struct user_request req = sp_createfile(sp, 1, "a", 1, &ack_hmac);
+ struct tm_request req = sp_createfile(sp, 1, test_sign_request, "a", &ack_hmac);
check("File creation", ack_verify(&req, "a", 1, ack_hmac));
@@ -734,7 +841,7 @@ void sp_test(void)
#define N_MODIFY 100
start = clock();
for(int i = 0; i < N_MODIFY; ++i)
- req = sp_modifyfile(sp, 1, "a", 1, 1, hash_null, hash_null, buildcode, NULL, "contents", 8, &ack_hmac);
+ req = sp_modifyfile(sp, 1, test_sign_request, "a", 1, hash_null, hash_null, buildcode, NULL, "contents", 8, &ack_hmac);
stop = clock();
printf("%.1f modifications per second\n", (double)N_MODIFY * CLOCKS_PER_SEC / (stop - start));
@@ -792,11 +899,12 @@ void sp_test(void)
#define N_ACLMODIFY 100
for(int i = 0; i < 100; ++i)
{
- struct user_request req = sp_modifyacl(sp,
- 1, "a", 1,
- 1,
- newacl,
- &ack);
+ struct tm_request req = sp_modifyacl(sp,
+ 1,
+ test_sign_request, "a",
+ 1,
+ newacl,
+ &ack);
success &= ack_verify(&req, "a", 1, ack);
}
diff --git a/service_provider.h b/service_provider.h
index 3399cb4..b55285c 100644
--- a/service_provider.h
+++ b/service_provider.h
@@ -9,12 +9,64 @@
struct service_provider;
+/* Client-service protocol: */
+
+/* 1. Client sends user_request to service.
+ *
+ * 2. Client sends additional data to service, if needed.
+ *
+ * 3. Service sends filled tm_request to client for signature.
+ *
+ * 4. Client verifies that the tm_request is appropriate.
+ *
+ * 5. Client sends HMAC(tm_request, user key) to service.
+ *
+ * 6. Service performs action.
+ *
+ * 7. Service sends module's authenticated acknowledgement (and
+ * response, in the case of RETRIEVE_INFO) to client.
+ *
+ * 8. Client verifies acknowledgement against earlier tm_request or
+ * response.
+ */
+
+/* request from the client to the service */
+struct user_request {
+ enum { CREATE_FILE, MODIFY_FILE, MODIFY_ACL, RETRIEVE_INFO, RETRIEVE_FILE } type;
+ union {
+ struct {
+ uint64_t user_id;
+ } create;
+ struct {
+ uint64_t user_id, file_idx;
+ /* ACL IOMT will follow */
+ } modify_acl;
+ struct {
+ uint64_t user_id, file_idx;
+ hash_t encrypted_secret, kf;
+ /* file contents, build code IOMT, and compose file IOMT
+ * will follow */
+
+ /* will respond with module's HMAC of tm_request struct
+ * plus a zero byte */
+ } modify_file;
+ struct {
+ /* same structure for retrieve file and retrieve info */
+ uint64_t user_id, file_idx, version;
+ /* will respond with either version_info struct, plus
+ * HMAC, or file contents and key (which the client can
+ * verify themselves) */
+ } retrieve;
+ };
+} __attribute__((packed));
+
+#ifndef CLIENT
struct service_provider *sp_new(const void *key, size_t keylen, int logleaves);
void sp_free(struct service_provider *sp);
/* see .c file for documentation */
struct tm_cert sp_request(struct service_provider *sp,
- const struct user_request *req, hash_t req_hmac,
+ const struct tm_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,
@@ -26,23 +78,29 @@ struct tm_cert sp_request(struct service_provider *sp,
/* Reserve a new file index with user_id added to the ACL. Returns
* cert on failure. Authenticated with ack_hmac, which is the returned
* request with a zero byte appended, signed by the module. */
-struct user_request sp_createfile(struct service_provider *sp,
- uint64_t user_id, const void *key, size_t keylen,
- hash_t *ack_hmac);
-
-struct user_request sp_modifyacl(struct service_provider *sp,
- uint64_t user_id, const void *key, size_t keylen,
- uint64_t file_idx,
- struct iomt *new_acl,
- hash_t *ack_hmac);
-
-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 kf,
- const struct iomt *buildcode, const struct iomt *composefile,
- const void *encrypted_file, size_t filelen,
- hash_t *ack_hmac);
+struct tm_request sp_createfile(struct service_provider *sp,
+ uint64_t user_id,
+ hash_t (*sign_request)(void *userdata, const struct tm_request *req),
+ void *userdata,
+ hash_t *ack_hmac);
+
+struct tm_request sp_modifyacl(struct service_provider *sp,
+ uint64_t user_id,
+ hash_t (*sign_request)(void *userdata, const struct tm_request *req),
+ void *userdata,
+ uint64_t file_idx,
+ struct iomt *new_acl,
+ hash_t *ack_hmac);
+
+struct tm_request sp_modifyfile(struct service_provider *sp,
+ uint64_t user_id,
+ hash_t (*sign_request)(void *userdata, const struct tm_request *req),
+ void *userdata,
+ uint64_t file_idx,
+ hash_t encrypted_secret, hash_t kf,
+ const struct iomt *buildcode, const struct iomt *composefile,
+ const void *encrypted_file, size_t filelen,
+ hash_t *ack_hmac);
/* Retrieve authenticated information on a version of a file; if
* version is zero, default to the latest version. */
@@ -59,6 +117,9 @@ void *sp_retrieve_file(struct service_provider *sp,
hash_t *encrypted_secret,
size_t *len);
+int sp_main(int sockfd);
+
void sp_test(void);
+#endif
#endif
diff --git a/test.c b/test.c
index 69f12de..e8bf44a 100644
--- a/test.c
+++ b/test.c
@@ -6,16 +6,11 @@
void check(const char *name, int condition)
{
printf("%s: %s", name, condition ? "\033[32;1mPASS\033[0m\n" : "\033[31;1mFAIL\033[0m\n");
+#if 0
if(!condition)
{
printf("%s\n", tm_geterror());
tm_seterror(NULL);
}
-}
-
-int main()
-{
- crypto_test();
- tm_test();
- sp_test();
+#endif
}
diff --git a/test.h b/test.h
index 3f19a59..46cfa6f 100644
--- a/test.h
+++ b/test.h
@@ -1,2 +1,5 @@
/* testing */
void check(const char *name, int condition);
+
+/* in main.c */
+void run_tests(void);
diff --git a/trusted_module.c b/trusted_module.c
index 7ebd716..2c021e3 100644
--- a/trusted_module.c
+++ b/trusted_module.c
@@ -386,13 +386,13 @@ bool tm_set_equiv_root(struct trusted_module *tm,
}
/* user id is 1-indexed */
-static hash_t req_sign(const struct trusted_module *tm, const struct user_request *req, int id)
+static hash_t req_sign(const struct trusted_module *tm, const struct tm_request *req, int id)
{
return hmac_sha256(req, sizeof(*req), tm->user_keys[id - 1].key, tm->user_keys[id - 1].len);
}
/* verify HMAC of user request */
-static bool req_verify(const struct trusted_module *tm, const struct user_request *req, uint64_t id, hash_t hmac)
+static bool req_verify(const struct trusted_module *tm, const struct tm_request *req, uint64_t id, hash_t hmac)
{
if(id < 1 || id >= tm->n_users + 1)
return false;
@@ -400,30 +400,7 @@ static bool req_verify(const struct trusted_module *tm, const struct user_reques
return hash_equals(calculated, hmac);
}
-/* Generate a signed acknowledgement for successful completion of a
- * request. We append a zero byte to the user request and take the
- * HMAC. */
-hash_t ack_sign(const struct user_request *req, int nzeros, const void *key, size_t keylen)
-{
- HMAC_CTX *ctx = HMAC_CTX_new();
- HMAC_Init_ex(ctx,
- key, keylen,
- EVP_sha256(), NULL);
-
- HMAC_Update(ctx, (const unsigned char*)req, sizeof(*req));
-
- unsigned char zero = 0;
- for(int i = 0; i < nzeros; ++i)
- HMAC_Update(ctx, &zero, 1);
-
- hash_t hmac;
- HMAC_Final(ctx, hmac.hash, NULL);
- HMAC_CTX_free(ctx);
-
- return hmac;
-}
-
-static hash_t req_ack(const struct trusted_module *tm, const struct user_request *req)
+static hash_t req_ack(const struct trusted_module *tm, const struct tm_request *req)
{
return ack_sign(req,
1,
@@ -435,7 +412,7 @@ static hash_t req_ack(const struct trusted_module *tm, const struct user_request
/*
* This function handles all transformations on the IOMT except
* inserting a placeholder (handled above). The function takes its
- * parameter in the form of a user_request struct, which must be
+ * parameter in the form of a tm_request struct, which must be
* authenticated or else the function will fail. When a request is
* successfully completed, *ack_hmac will be updated to the value
* HMAC(<request> + 1, K), where + denotes concatenation, and K is the
@@ -483,7 +460,7 @@ static hash_t req_ack(const struct trusted_module *tm, const struct user_request
* be updated to reflect the incremented file counter.
*/
struct tm_cert tm_request(struct trusted_module *tm,
- const struct user_request *req, hash_t req_hmac,
+ const struct tm_request *req, hash_t req_hmac,
hash_t *hmac_out,
struct tm_cert *vr_out, hash_t *vr_hmac,
hash_t *hmac_ack)
diff --git a/trusted_module.h b/trusted_module.h
index f78d5f2..7e1cd4b 100644
--- a/trusted_module.h
+++ b/trusted_module.h
@@ -8,7 +8,7 @@
#include "crypto.h"
struct trusted_module;
-struct user_request;
+struct tm_request;
struct tm_cert {
enum { CERT_NONE = 0, NU, EQ, RV, RU, FR, VR } type;
@@ -50,7 +50,7 @@ struct tm_cert {
};
};
-struct user_request {
+struct tm_request {
uint64_t idx; /* file index */
uint64_t user_id; /* user id */
enum { REQ_NONE = 0, ACL_UPDATE, FILE_UPDATE } type;
@@ -94,10 +94,12 @@ struct version_info {
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_request req_null = { REQ_NONE };
static const struct tm_cert cert_null = { CERT_NONE };
static const struct version_info verinfo_null = { 0 };
+#ifndef CLIENT
+
/* creates 1 user with given shared secret */
struct trusted_module *tm_new(const void *key, size_t keylen);
void tm_free(struct trusted_module *tm);
@@ -164,7 +166,7 @@ bool tm_set_equiv_root(struct trusted_module *tm,
/* process a user's request to transform the IOMT in some way */
struct tm_cert tm_request(struct trusted_module *tm,
- const struct user_request *req, hash_t req_hmac,
+ const struct tm_request *req, hash_t req_hmac,
hash_t *hmac_out,
struct tm_cert *vr_out, hash_t *vr_hmac,
hash_t *ack_hmac);
@@ -203,9 +205,10 @@ struct version_info tm_verify_file(const struct trusted_module *tm,
const struct tm_cert *vr, hash_t vr_hmac,
hash_t *response_hmac);
-hash_t ack_sign(const struct user_request *req, int nzeros, const void *key, size_t keylen);
-
const char *tm_geterror(void);
void tm_seterror(const char *error);
+
+#endif
+
#endif