commit bc68c15d118c7b607c26a672a558b5e93e817ec3 Author: h Date: Wed Nov 6 14:44:39 2024 -0500 slows diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..8a90096 --- /dev/null +++ b/.gitignore @@ -0,0 +1,3 @@ +*.o +.ccls-cache/ +slows diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..578d85e --- /dev/null +++ b/Makefile @@ -0,0 +1,17 @@ +CC=gcc +CFLAGS=-Wall -Wextra -ggdb -std=gnu99 +SRC=arith.c circ.c client.c hosts.c parse.c pre.c online.c msg.c com.c +OBJ=$(SRC:.c=.o) +LIBS=-lcrypto + +all: client + +.SUFFIXES: .c .o +.c.o: + $(CC) -c $(CFLAGS) $*.c + +client: $(OBJ) + $(CC) $(LIBS) -o slows $(OBJ) + +clean: + rm -f *.o slows diff --git a/arith.c b/arith.c new file mode 100644 index 0000000..1b72f1e --- /dev/null +++ b/arith.c @@ -0,0 +1,68 @@ +#include "arith.h" +#include +#include + +// Field: 18446744073709551557 + +const uint64_t MOD = 18446744073709551557ULL; + +fp *rand_fp() { + uint64_t v = ((uint64_t)rand() << 32) | ((uint64_t)rand()); + v = v % MOD; + fp *x = malloc(sizeof(fp)); + x->val = v; + return x; +} + +fp *from(uint64_t v) { + fp *x = malloc(sizeof(fp)); + x->val = v % MOD; + return x; +} + +fp *add(fp *a, fp *b) { + fp *x = malloc(sizeof(fp)); + x->val = (a->val + b->val); + if (x->val > MOD || (x->val < a->val && x->val < b->val)) { + x->val -= MOD; + } + x->val %= MOD; + return x; +} + +fp *mul(fp *a, fp *b) { + uint64_t v = b->val; + uint64_t r = a->val; + uint64_t o = 0; + while (v > 0) { + if (v % 2 == 1) { + uint64_t tmp = o + r; + if (tmp > MOD || (tmp < o && tmp < r)) { + tmp -= MOD; + } + o = tmp % MOD; + } + // r + r + uint64_t tmp = r + r; + if (tmp > MOD || (tmp < r)) { + tmp -= MOD; + } + r = tmp % MOD; + + v >>= 1; + } + o = o % MOD; + fp *x = malloc(sizeof(fp)); + x->val = o; + return x; +} + +fp *neg(fp *a) { + fp *x = malloc(sizeof(fp)); + x->val = MOD - a->val; + return x; +} + +int is_zero(fp *x) { return (x->val == 0); } + +uint64_t get_output(fp *x) { return x->val; } diff --git a/arith.h b/arith.h new file mode 100644 index 0000000..63b0de5 --- /dev/null +++ b/arith.h @@ -0,0 +1,38 @@ +#ifndef H_ARITH +#define H_ARITH + +#include + +// Field element (invariant: val <= MOD) +typedef struct { + uint64_t val; +} fp; + +// An authenticated share: consists of linear shares of (x, Delta * x) +struct share { + fp *s; + fp *s_mac; +}; + +// Generate a fully random field element +fp *rand_fp(); + +// Convert a uint to a Fp +fp *from(uint64_t v); + +// Add two field elements together +fp *add(fp *a, fp *b); + +// Multiply two field elements together +fp *mul(fp *a, fp *b); + +// Negate a field element (-x) +fp *neg(fp *a); + +// Check if a field element is zero. +int is_zero(fp *x); + +// Produce a printable uint64 from the field element. +uint64_t get_output(fp *o); + +#endif diff --git a/circ.c b/circ.c new file mode 100644 index 0000000..e2f5ba9 --- /dev/null +++ b/circ.c @@ -0,0 +1,155 @@ +#include "circ.h" +#include +#include +#include + +#define MAX(x, y) (((x) > (y)) ? (x) : (y)) + +struct wires *g_wires; + +void init_circuit(char *file) { + + char *line = NULL; + size_t len = 0; + ssize_t read; + + g_wires = NULL; + + FILE *fp = fopen(file, "r"); + if (fp == NULL) { + printf("Circuit file not found.\n"); + exit(1); + } + + while ((read = getline(&line, &len, fp)) != -1) { + char *wname = malloc(200 * sizeof(char)); + char op[4]; + char *in1 = malloc(200 * sizeof(char)); + char *in2 = malloc(200 * sizeof(char)); + int ret = sscanf(line, "%200s = %3s %200s %200s", wname, op, in1, in2); + if (ret == 4) { + if (strcmp(op, "inp") == 0) { + struct wire *w = malloc(sizeof(struct wire)); + w->wname = wname; + w->operation = 2; + w->val = from(atoi(in2)); + w->depth = 0; + w->in1 = NULL; + w->in2 = NULL; + w->is_output = 0; + w->input_name = in1; + struct wires *cur = malloc(sizeof(struct wires)); + cur->w = w; + cur->next = g_wires; + g_wires = cur; + } else if (strcmp(op, "add") == 0) { + struct wire *inw1; + struct wire *inw2; + struct wires *a; + for (a = g_wires; a != NULL; a = a->next) { + if (strcmp(a->w->wname, in1) == 0) { + inw1 = a->w; + } + if (strcmp(a->w->wname, in2) == 0) { + inw2 = a->w; + } + } + + struct wire *w = malloc(sizeof(struct wire)); + w->wname = wname; + w->operation = 0; + w->val = 0; + w->depth = MAX(inw1->depth, inw2->depth) + 1; + w->in1 = inw1; + w->in2 = inw2; + w->is_output = 0; + struct wires *cur = malloc(sizeof(struct wires)); + cur->w = w; + cur->next = g_wires; + g_wires = cur; + + } else if (strcmp(op, "mul") == 0) { + struct wire *inw1; + struct wire *inw2; + struct wires *a; + for (a = g_wires; a != NULL; a = a->next) { + if (strcmp(a->w->wname, in1) == 0) { + inw1 = a->w; + } + if (strcmp(a->w->wname, in2) == 0) { + inw2 = a->w; + } + } + struct wire *w = malloc(sizeof(struct wire)); + w->wname = wname; + w->operation = 1; + w->val = 0; + w->depth = MAX(inw1->depth, inw2->depth) + 1; + w->in1 = inw1; + w->in2 = inw2; + w->is_output = 0; + struct wires *cur = malloc(sizeof(struct wires)); + cur->w = w; + cur->next = g_wires; + g_wires = cur; + } + } else if (ret == 3) { + if (strcmp(op, "inp") == 0) { + + struct wire *w = malloc(sizeof(struct wire)); + w->wname = wname; + w->operation = 2; + w->val = 0; + w->depth = 0; + w->in1 = NULL; + w->in2 = NULL; + w->is_output = 0; + w->input_name = in1; + struct wires *cur = malloc(sizeof(struct wires)); + cur->w = w; + cur->next = g_wires; + g_wires = cur; + } else if (strcmp(op, "con") == 0) { + struct wire *w = malloc(sizeof(struct wire)); + w->wname = wname; + w->operation = 3; + w->val = from(atoi(in1)); + w->depth = 0; + w->in1 = NULL; + w->in2 = NULL; + w->is_output = 0; + struct wires *cur = malloc(sizeof(struct wires)); + cur->w = w; + cur->next = g_wires; + g_wires = cur; + } + } else { + char *wwname = malloc(200 * sizeof(char)); + int nret = sscanf(line, "out %200s", wwname); + if (nret == 1) { + struct wire *inw1; + struct wires *a; + for (a = g_wires; a != NULL; a = a->next) { + if (strcmp(a->w->wname, wwname) == 0) { + inw1 = a->w; + } + } + inw1->is_output = 1; + } + // otherwise ignore the command + } + } + + struct wires *cur = g_wires; + struct wires *prev = NULL; + struct wires *next; + + while (cur != NULL) { + next = cur->next; + cur->next = prev; + prev = cur; + cur = next; + } + + g_wires = prev; +} diff --git a/circ.h b/circ.h new file mode 100644 index 0000000..4df216c --- /dev/null +++ b/circ.h @@ -0,0 +1,33 @@ +#ifndef H_CIRC +#define H_CIRC + +#include "arith.h" + +// A wire value. +struct wire { + char *wname; // wire name + struct wire *in1; // input value 1 into gate + struct wire *in2; // input value 2 into gate + int depth; // the circuit forms a DAG -> this is the DAG depth. It is *not + // necessary* to use this. + fp *val; // IF constant, this is the constant value on the wire + // IF input (for this party), this is the value for that input + int operation; + // 0 for addition, 1 for multiplication, 2 for input, 3 for constant + // if its an input wire or constant wire, in1 and in2 are null. + + int is_output; // If the wire is an output wire. + char *input_name; // name of user who provides input if wire is input wire + + struct share *share; // TODO: fill this in when evaluating the circuit +}; + +// A linked list of wires; this holds the wires ready in evaluation order. +struct wires { + struct wires *next; + struct wire *w; +}; + +void init_circuit(char *file); + +#endif diff --git a/client.c b/client.c new file mode 100644 index 0000000..ec6f5ea --- /dev/null +++ b/client.c @@ -0,0 +1,179 @@ +#include "circ.h" +#include "hosts.h" +#include "online.h" +#include "parse.h" +#include "pre.h" +#include +#include +#include +#include +#include +#include + +extern char *f_host; // host filename (ignore) +extern char *f_circ; // circuit filename (ignore) +extern char *f_pre; // preprocess filename (ignore) + +extern struct host *conns[1024]; // external connections to other parties +extern int num_conns; // number of total connections +extern char *glob_name; // global ident for this party + +extern fp *delta; + +extern struct wires *g_wires; // circuit wires stored linearly (order matters!) + +extern struct randv *auth_rand; // authenticated randomness (ie; malicious + // secret shares of random values) +extern struct triple *auth_triples; // authenticated triples (ie; malicious + // secret shares of a, b, ab) + +void initialize() { + init_hosts(f_host); + init_circuit(f_circ); + init_preprocess(f_pre); + + printf("\n\n\n --- CONNECTIONS --- \n\n"); + for (int i = 0; i < num_conns; i++) { + printf("Connected with %s:%d at %d\n", conns[i]->name, conns[i]->c_port, + conns[i]->h_port); + } + + printf("\n --- PREPROCESSING --- \n\n"); + + printf("GLOBAL MAC SHARE: [%lu]\n", delta->val); + + struct triple *t; + for (t = auth_triples; t != NULL; t = t->next) { + printf("TRIPLE [a] = (%lu %lu) [b] = (%lu %lu) [c] = (%lu %lu)\n", + t->a->s->val, t->a->s_mac->val, t->b->s->val, t->b->s_mac->val, + t->ab->s->val, t->ab->s_mac->val); + } + + struct randv *r; + + for (r = auth_rand; r != NULL; r = r->next) { + printf("RAND [r] = (%lu %lu)", r->s->s->val, r->s->s_mac->val); + if (r->value != NULL) { + printf(" (r = %lu)\n", r->value->val); + } else { + printf("\n"); + } + } + + printf("\n --- WIRES --- \n\n"); + + struct wires *a; + + for (a = g_wires; a != NULL; a = a->next) { + if (a->w->operation == 2) { + printf("INPUT WIRE BY [%s] ", a->w->input_name); + if (strcmp(a->w->input_name, glob_name) == 0) { + printf("(i = %lu)\n", a->w->val->val); + } else { + printf("\n"); + } + } + } +} + +uint8_t check_arr(uint8_t *ready, int len) { + for (int i = 0; i < len; i++) { + if (((ready[i] & 1) == 0) || ((ready[i] & 2) == 0)) { + return 0; + } + } + return 1; +} + +void wait_for_connections() { + + printf("\n\n\n --- PHASE 1 --- \n\n\n"); + + printf("Waiting for connections...\n"); + + struct pollfd *fds = malloc(sizeof(struct pollfd) * num_conns); + + uint8_t *is_ready = malloc(sizeof(uint8_t) * num_conns); + for (int i = 0; i < num_conns; i++) { + is_ready[i] = 0; + } + + while (check_arr(is_ready, num_conns) == 0) { + int numfds = 0; + // send out a ping to all hosts, and wait 10 seconds for an ack + char pepega[4] = {'p', 'i', 'n', 'g'}; + for (int i = 0; i < num_conns; i++) { + if ((is_ready[i] & 1) == 0) { + printf("Pinging %s\n", conns[i]->name); + sendto(conns[i]->sockfd, pepega, 4, 0, + (const struct sockaddr *)&conns[i]->conn, + sizeof(conns[i]->conn)); + fds[numfds].fd = conns[i]->sockfd; + fds[numfds].events = POLLIN; + fds[numfds].revents = 0; + numfds += 1; + } else if ((is_ready[i] & 2) == 0) { + fds[numfds].fd = conns[i]->sockfd; + fds[numfds].events = POLLIN; + fds[numfds].revents = 0; + numfds += 1; + } + } + + int out = poll(fds, numfds, 10000); + + if (out > 0) { + for (int i = 0; i < numfds; i++) { + if (fds[i].revents > 0) { + int connid = 0; + for (int j = 0; j < num_conns; j++) { + if (conns[j]->sockfd == fds[i].fd) { + connid = j; + } + } + + unsigned char buf[4] = {0}; + socklen_t len = sizeof(conns[connid]->conn); + recvfrom(fds[i].fd, buf, 4, 0, + (struct sockaddr *)&(conns[connid]->conn), &len); + + if (buf[0] == 'p' && buf[1] == 'i' && buf[2] == 'n' && + buf[3] == 'g') { + printf("Received ping from %s, acking\n", conns[connid]->name); + char omega[4] = {'a', 'c', 'k', 'n'}; + sendto(fds[i].fd, omega, 4, 0, + (const struct sockaddr *)&conns[connid]->conn, + sizeof(conns[connid]->conn)); + is_ready[connid] |= 2; + } else if (buf[0] == 'a' && buf[1] == 'c' && buf[2] == 'k' && + buf[3] == 'n') { + printf("Received ack from %s\n", conns[connid]->name); + is_ready[connid] |= 1; + } + } + } + } + } + + free(is_ready); + + sleep(5); +} + +int main(int argc, char **argv) { + srand(time(NULL)); + parse(argc, argv); + + printf("Got host file: %s\n", f_host); + printf("Got circuit file: %s\n", f_circ); + printf("Got preprocessing file: %s\n\n\n", f_pre); + + initialize(); + + wait_for_connections(); + + printf("\n\n\n --- PHASE 2 ---\n\n\n"); + + spdz_online(conns, num_conns, glob_name, delta, g_wires, auth_rand, + auth_triples); +} diff --git a/com.c b/com.c new file mode 100644 index 0000000..f664fbf --- /dev/null +++ b/com.c @@ -0,0 +1,31 @@ + +#include "arith.h" +#include +#include +#include + +char *commit(fp *data, fp *random) { + char inp_data[16]; + char *outbuf = malloc(32 * sizeof(char)); + for (int i = 0; i < 32; i++) { + outbuf[i] = 0; + } + ((uint64_t *)inp_data)[0] = data->val; + ((uint64_t *)inp_data)[1] = random->val; + SHA256((unsigned char *)inp_data, 8, (unsigned char *)outbuf); + return outbuf; +}; + +void check_open(fp *data, fp *random, char *commitment) { + char inp_data[16]; + char *outbuf = malloc(32 * sizeof(char)); + for (int i = 0; i < 32; i++) { + outbuf[i] = 0; + } + ((uint64_t *)inp_data)[0] = data->val; + ((uint64_t *)inp_data)[1] = random->val; + SHA256((unsigned char *)inp_data, 8, (unsigned char *)outbuf); + for (int i = 0; i < 32; i++) { + assert(outbuf[i] == commitment[i]); + } +}; diff --git a/com.h b/com.h new file mode 100644 index 0000000..48bb06b --- /dev/null +++ b/com.h @@ -0,0 +1,16 @@ + +#ifndef H_COM +#define H_COM + +#include "arith.h" +#include + +// Produces a char[32] 32 byte array with the commitment contained within. +// NOTE: IT IS 32 BYTES EXACTLY. +char *commit(fp *data, fp *random); + +// Checks the opening of a 32 byte commitment (makes commitment correctly bound +// data). +char *check_open(fp *data, fp *random, char *commitment); + +#endif diff --git a/hosts.c b/hosts.c new file mode 100644 index 0000000..a02d89c --- /dev/null +++ b/hosts.c @@ -0,0 +1,88 @@ +#include "hosts.h" +#include +#include +#include +#include +#include +#include + +struct host *conns[1024]; +int num_conns = 0; +char *glob_name; + +int init_conn(int h_port) { + + int sock_fd = socket(AF_INET, SOCK_DGRAM, 0); + + if (sock_fd < 0) { + printf("Socket initialization failed."); + exit(1); + } + + struct sockaddr_in serv_addr; + + memset(&serv_addr, 0, sizeof(serv_addr)); + + serv_addr.sin_family = AF_INET; + serv_addr.sin_port = htons(h_port); + serv_addr.sin_addr.s_addr = htonl(INADDR_ANY); + + if (bind(sock_fd, (struct sockaddr *)&serv_addr, sizeof(serv_addr)) < 0) { + printf("Failed to bind socket.\n"); + exit(1); + } + + return sock_fd; +} + +void init_hosts(char *file) { + + char *line = NULL; + size_t len = 0; + ssize_t read; + + FILE *fp = fopen(file, "r"); + if (fp == NULL) { + printf("Host file not found.\n"); + exit(1); + } + + int name = 1; + + while ((read = getline(&line, &len, fp)) != -1) { + if (name == 1) { + glob_name = malloc(sizeof(char) * (strlen(line) + 1)); + strcpy(glob_name, line); + glob_name[strcspn(glob_name, "\n")] = 0; + printf("Name: %s", glob_name); + name = 0; + } else { + char *cname = malloc(200 * sizeof(char)); + char *addr = malloc(32 * sizeof(char)); + int c_port; + int h_port; + int ret = sscanf(line, "%200s %d %32s %d", cname, &h_port, addr, &c_port); + if (ret != 4) { + printf("Could not parse host file.\n"); + exit(1); + } + struct host *h = malloc(sizeof(struct host)); + h->name = cname; + h->h_port = h_port; + h->c_port = c_port; + h->sockfd = init_conn(h_port); + + struct sockaddr_in conn_addr; + + memset(&conn_addr, 0, sizeof(conn_addr)); + + conn_addr.sin_family = AF_INET; + conn_addr.sin_port = htons(c_port); + conn_addr.sin_addr.s_addr = inet_addr(addr); + free(addr); + h->conn = conn_addr; + conns[num_conns] = h; + num_conns += 1; + } + } +} diff --git a/hosts.h b/hosts.h new file mode 100644 index 0000000..3b0e644 --- /dev/null +++ b/hosts.h @@ -0,0 +1,17 @@ +#ifndef H_HOST +#define H_HOST + +#include + +// A connection. +struct host { + char *name; + int sockfd; + struct sockaddr_in conn; + int h_port; + int c_port; +}; + +void init_hosts(char *file); + +#endif diff --git a/msg.c b/msg.c new file mode 100644 index 0000000..069f22f --- /dev/null +++ b/msg.c @@ -0,0 +1,77 @@ +#include "msg.h" +#include "hosts.h" +#include +#include +#include +#include +#include + +fp *packet_to_fp(packet *p) { + fp *f = malloc(sizeof(fp)); + f->val = be64toh(((uint64_t *)p->data)[0]); + return f; +} + +packet *fp_to_packet(fp *elem) { + uint64_t *buf = malloc(sizeof(char) * 8); + buf[0] = htobe64(elem->val); + packet *p = malloc(sizeof(packet)); + p->data = (uint8_t *)buf; + p->len = 8; + return p; +} + +packet *to_packet(uint8_t *data, uint8_t len) { + packet *p = malloc(sizeof(packet)); + p->data = data; + p->len = len; + return p; +} + +void broadcast(struct host **conns, int num_conns, packet *data) { + + char *transmit = malloc(sizeof(char) * data->len + 1); + transmit[0] = (char)data->len; + memcpy((transmit + 1), data->data, data->len); + for (int i = 0; i < num_conns; i++) { + sendto(conns[i]->sockfd, transmit, data->len + 1, 0, + (const struct sockaddr *)&conns[i]->conn, sizeof(conns[i]->conn)); + } + free(transmit); +} + +packet *recv_broadcasts(struct host **conns, int num_conns) { + + packet *packets = malloc(sizeof(packet) * num_conns); + + for (int i = 0; i < num_conns; i++) { + packets[i].data = NULL; + packets[i].len = 0; + } + + for (int i = 0; i < num_conns; i++) { + uint8_t *buf = malloc(sizeof(uint8_t) * 64); + socklen_t len = sizeof(conns[i]->conn); + recvfrom(conns[i]->sockfd, buf, 64, 0, (struct sockaddr *)&(conns[i]->conn), + &len); + uint8_t size = buf[0]; + packets[i].data = (buf + 1); + packets[i].len = size; + } + + return packets; +} + +packet *recv_single_broadcast(struct host *con) { + packet *p = malloc(sizeof(packet)); + p->data = NULL; + p->len = 0; + uint8_t *buf = malloc(sizeof(uint8_t) * 64); + socklen_t len = sizeof(con->conn); + recvfrom(con->sockfd, buf, 64, 0, (struct sockaddr *)&(con->conn), &len); + uint8_t size = buf[0]; + p->data = (buf + 1); + p->len = size; + + return p; +} diff --git a/msg.h b/msg.h new file mode 100644 index 0000000..4288df1 --- /dev/null +++ b/msg.h @@ -0,0 +1,33 @@ +#ifndef H_MSG +#define H_MSG + +#include "arith.h" +#include "hosts.h" +#include + +typedef struct { + uint8_t *data; + uint8_t len; +} packet; + +// Convert a packet (recieved on the network) into a field element. +fp *packet_to_fp(packet *p); + +// Convert a field element to a packet. +packet *fp_to_packet(fp *elem); + +// Convert a char [len] array into a packet. +// Note: this is necessary for the commitments sent. +packet *to_packet(uint8_t *data, uint8_t len); + +// Broadcast to all connections a packet. +void broadcast(struct host **conns, int num_conns, packet *data); + +// Recieve from all connections a packet. +packet *recv_broadcasts(struct host **conns, int num_conns); + +// Recieve from a single connection a packet. (Can use it for recieving the +// initial input opening for wires). +packet *recv_single_broadcast(struct host *con); + +#endif diff --git a/online.c b/online.c new file mode 100644 index 0000000..7e35cfc --- /dev/null +++ b/online.c @@ -0,0 +1,85 @@ +#include "online.h" +#include "arith.h" +#include "circ.h" +#include "com.h" +#include "hosts.h" +#include "msg.h" +#include "pre.h" +#include +#include +#include +#include + +// here we want to open a share: +// to do this, players +// 1. broadcast openings to plain shares +// 2. commit to mac candidate differences +// 3. open commitments +// 4. check the commitments; if they don't verify abort +// 5. if the sum is not 0, abort +fp *secure_open(struct host **conns, int num_conns, fp *delta, + struct share *s) { + + // TODO: implement this +}; + +// Add a constant to a shared value [x] -> [x + c] +// a single arbitrary party should do the s -> s + c update: you may assume this +// party is named "p0" everyone updates macs! +struct share *const_add(struct share *s, fp *constant, fp *delta, + char *glob_name) { + // TODO: implement this + +}; + +// Multiply a constant to a shared value [x] -> [cx] +struct share *const_mul(struct share *s, fp *constant) { + // TODO: implement this +}; + +// Do a local share add ([x], [y]) -> [x + y] +struct share *local_add(struct share *s1, struct share *s2) { + // TODO: implement this +}; + +// Do a local share sub ([x], [y]) -> [x - y] +struct share *local_sub(struct share *s1, struct share *s2) { + // TODO: implement this + // (not strictly necessary, but useful for mult) +}; + +// Use the opening and a triple to do a multiplication +// Do a multiplication ([x], [y]) -> [xy] +struct share *multiply(struct host **conns, int num_conns, fp *delta, + char *glob_name, struct share *s1, struct share *s2, + struct triple *t) { + // TODO: implement this +}; + +// Arguments: +// 1. conns is the list of connections. [ This is for broadcasting ]. +// 2. num_conns is the number of connections. [ For broadcasting ] +// 3. glob_name is the global name of you (the party). [ For const add ].. +// 4. delta is the SPDZ global mac share. +// 5. g_wires is the global linked list of wires in eval order. +// 6. auth_rand is a list of random shares [r] (along with input vals) +// 7. auth_triples is a list of beaver triples [a], [b], [ab]. +// Proceed through g_wires and evaluate each wire until you hit the end. +void spdz_online(struct host **conns, int num_conns, char *glob_name, fp *delta, + struct wires *g_wires, struct randv *auth_rand, + struct triple *auth_triples) { + + // 1. loop through all the wires in the g_wires linked list + // + // 2. Check what operation is the wire from: do the operation (multiply, add) + // dont forget the edge case when one of the input wires is a + // constant! + // + // 3. (within the previous check): if the wire is input, use up an auth_rand + // random share and produce shares of the input + // 4. (within the previous check): if the wire is output, calculate it and + // then at the end do a secure opening to find the output value. + + // NOTE: don't worry about freeing or managing stuff, we don't care about + // memory leaks or anything lol this aint a C class +} diff --git a/online.h b/online.h new file mode 100644 index 0000000..107a2c7 --- /dev/null +++ b/online.h @@ -0,0 +1,14 @@ + +#ifndef H_ONL +#define H_ONL + +#include "arith.h" +#include "circ.h" +#include "hosts.h" +#include "pre.h" + +void spdz_online(struct host **conns, int num_conns, char *glob_name, + fp *mac_share, struct wires *g_wires, struct randv *auth_rand, + struct triple *auth_triples); + +#endif diff --git a/parse.c b/parse.c new file mode 100644 index 0000000..0e9f77c --- /dev/null +++ b/parse.c @@ -0,0 +1,50 @@ +#include +#include +#include +#include + +extern char *optarg; +char *f_pre; +char *f_host; +char *f_circ; + +int parse(int argc, char **argv) { + char opt; + bool h; + bool c; + bool p; + + while ((opt = getopt(argc, argv, "h:c:p:")) != EOF) { + switch (opt) { + case 'h': + f_host = optarg; + h = true; + break; + case 'c': + f_circ = optarg; + c = true; + break; + case 'p': + f_pre = optarg; + p = true; + break; + } + } + + if (!h) { + printf("Please provide all arguments.\n"); + exit(1); + } + + if (!c) { + printf("Please provide all arguments.\n"); + exit(1); + } + + if (!p) { + printf("Please provide all arguments.\n"); + exit(1); + } + + return optind; +} diff --git a/parse.h b/parse.h new file mode 100644 index 0000000..b1c757d --- /dev/null +++ b/parse.h @@ -0,0 +1,6 @@ +#ifndef H_PARSE +#define H_PARSE + +int parse(int argc, char **argv); + +#endif diff --git a/pre.c b/pre.c new file mode 100644 index 0000000..580b976 --- /dev/null +++ b/pre.c @@ -0,0 +1,85 @@ +#include "pre.h" +#include "circ.h" +#include +#include +#include +#include +#include + +struct randv *auth_rand; +struct triple *auth_triples; + +fp *delta; + +void init_preprocess(char *file) { + char *line = NULL; + size_t len = 0; + ssize_t read; + + auth_rand = NULL; + auth_triples = NULL; + + FILE *fp = fopen(file, "r"); + if (fp == NULL) { + printf("Preprocessing file not found.\n"); + exit(1); + } + + while ((read = getline(&line, &len, fp)) != -1) { + char *wname = malloc(200 * sizeof(char)); + uint64_t share; + uint64_t share_mac; + uint64_t val; + int ret = sscanf(line, "rand %200s (%lu, %lu) %lu", wname, &share, + &share_mac, &val); + if (ret == 4) { + struct randv *rand_value = malloc(sizeof(struct randv)); + rand_value->wname = wname; + rand_value->next = auth_rand; + rand_value->s = malloc(sizeof(struct share)); + rand_value->s->s = from(share); + rand_value->s->s_mac = from(share_mac); + rand_value->value = from(val); + auth_rand = rand_value; + } else if (ret == 3) { + struct randv *rand_value = malloc(sizeof(struct randv)); + rand_value->wname = wname; + rand_value->next = auth_rand; + rand_value->s = malloc(sizeof(struct share)); + rand_value->s->s = from(share); + rand_value->s->s_mac = from(share_mac); + rand_value->value = NULL; + auth_rand = rand_value; + } else { + uint64_t share_a; + uint64_t share_mac_a; + uint64_t share_b; + uint64_t share_mac_b; + uint64_t share_ab; + uint64_t share_mac_ab; + int ret = sscanf(line, "triple (%lu, %lu) (%lu, %lu) (%lu, %lu)", + &share_a, &share_mac_a, &share_b, &share_mac_b, + &share_ab, &share_mac_ab); + if (ret == 6) { + struct triple *tp = malloc(sizeof(struct triple)); + tp->next = auth_triples; + tp->a = malloc(sizeof(struct share)); + tp->a->s = from(share_a); + tp->a->s_mac = from(share_mac_a); + tp->b = malloc(sizeof(struct share)); + tp->b->s = from(share_b); + tp->b->s_mac = from(share_mac_b); + tp->ab = malloc(sizeof(struct share)); + tp->ab->s = from(share_ab); + tp->ab->s_mac = from(share_mac_ab); + auth_triples = tp; + } else { + uint64_t macv; + int mac = sscanf(line, "mac %lu", &macv); + if (mac == 1) { + delta = from(macv); + } + } + } + } +} diff --git a/pre.h b/pre.h new file mode 100644 index 0000000..b1ef0a2 --- /dev/null +++ b/pre.h @@ -0,0 +1,25 @@ +#ifndef H_PRE +#define H_PRE + +#include "arith.h" + +// A linked list of Beaver triples [a], [b], [ab] +struct triple { + struct triple *next; + struct share *a; + struct share *b; + struct share *ab; +}; + +// A linked list of authenticated maliciously secure random shares [r], each +// associated with a wire. This should be used for generating shares of input. +struct randv { + struct randv *next; + char *wname; // name of associated wire + struct share *s; // authenticated share + fp *value; // r (if applicable; ie wire is the user's input) +}; + +void init_preprocess(char *file); + +#endif diff --git a/test0/ccfg1 b/test0/ccfg1 new file mode 100644 index 0000000..c4ccdaa --- /dev/null +++ b/test0/ccfg1 @@ -0,0 +1,10 @@ +w1 = inp p0 34 +w2 = inp p1 +w3 = inp p1 +w4 = inp p0 22 + +w5 = mul w1 w3 +w6 = add w4 w2 +w7 = add w5 w6 + +out w7 diff --git a/test0/ccfg2 b/test0/ccfg2 new file mode 100644 index 0000000..81bb09e --- /dev/null +++ b/test0/ccfg2 @@ -0,0 +1,10 @@ +w1 = inp p0 +w2 = inp p1 38 +w3 = inp p1 11 +w4 = inp p0 + +w5 = mul w1 w3 +w6 = add w4 w2 +w7 = add w5 w6 + +out w7 diff --git a/test0/hcfg1 b/test0/hcfg1 new file mode 100644 index 0000000..fe18012 --- /dev/null +++ b/test0/hcfg1 @@ -0,0 +1,2 @@ +p0 +p1 8001 127.0.0.1 8010 diff --git a/test0/hcfg2 b/test0/hcfg2 new file mode 100644 index 0000000..95e2b14 --- /dev/null +++ b/test0/hcfg2 @@ -0,0 +1,2 @@ +p1 +p0 8010 127.0.0.1 8001 diff --git a/test0/pcfg1 b/test0/pcfg1 new file mode 100644 index 0000000..eb630f5 --- /dev/null +++ b/test0/pcfg1 @@ -0,0 +1,8 @@ +mac 5 + +rand w1 (30, 73) 33 +rand w2 (9, 109) +rand w3 (11, 223) +rand w4 (33, 50) 50 + +triple (129, 4431) (33, 999) (26805, 475214) diff --git a/test0/pcfg2 b/test0/pcfg2 new file mode 100644 index 0000000..27af214 --- /dev/null +++ b/test0/pcfg2 @@ -0,0 +1,8 @@ +mac 8 + +rand w1 (3, 356) +rand w2 (10, 138) 19 +rand w3 (21, 193) 32 +rand w4 (17, 600) + +triple (328, 1510) (87, 561) (28035, 237706) diff --git a/test1/ccfg1 b/test1/ccfg1 new file mode 100644 index 0000000..8236dfa --- /dev/null +++ b/test1/ccfg1 @@ -0,0 +1,10 @@ +w1 = inp p0 34 +w2 = inp p1 +w3 = inp p1 +w4 = inp p2 + +w5 = mul w1 w2 +w6 = mul w3 w4 +w7 = add w5 w6 + +out w7 diff --git a/test1/ccfg2 b/test1/ccfg2 new file mode 100644 index 0000000..e6ee67a --- /dev/null +++ b/test1/ccfg2 @@ -0,0 +1,10 @@ +w1 = inp p0 +w2 = inp p1 38 +w3 = inp p1 11 +w4 = inp p2 + +w5 = mul w1 w2 +w6 = mul w3 w4 +w7 = add w5 w6 + +out w7 diff --git a/test1/ccfg3 b/test1/ccfg3 new file mode 100644 index 0000000..cc308bf --- /dev/null +++ b/test1/ccfg3 @@ -0,0 +1,10 @@ +w1 = inp p0 +w2 = inp p1 +w3 = inp p1 +w4 = inp p2 18 + +w5 = mul w1 w2 +w6 = mul w3 w4 +w7 = add w5 w6 + +out w7 diff --git a/test1/hcfg1 b/test1/hcfg1 new file mode 100644 index 0000000..d721ce5 --- /dev/null +++ b/test1/hcfg1 @@ -0,0 +1,3 @@ +p0 +p1 8000 127.0.0.1 8010 +p2 8001 127.0.0.1 8020 diff --git a/test1/hcfg2 b/test1/hcfg2 new file mode 100644 index 0000000..fa6e02f --- /dev/null +++ b/test1/hcfg2 @@ -0,0 +1,3 @@ +p1 +p0 8010 127.0.0.1 8000 +p2 8011 127.0.0.1 8021 diff --git a/test1/hcfg3 b/test1/hcfg3 new file mode 100644 index 0000000..952334e --- /dev/null +++ b/test1/hcfg3 @@ -0,0 +1,3 @@ +p2 +p0 8020 127.0.0.1 8001 +p1 8021 127.0.0.1 8011 diff --git a/test1/pcfg1 b/test1/pcfg1 new file mode 100644 index 0000000..38ecba8 --- /dev/null +++ b/test1/pcfg1 @@ -0,0 +1,9 @@ +mac 8 + +rand w1 (30, 1000) 115 +rand w2 (9, 231) +rand w3 (11, 223) +rand w4 (10, 400) + +triple (722, 187202) (363, 6006) (667401, 6189301) +triple (218331, 183634) (4398, 4313) (300405, 2821) diff --git a/test1/pcfg2 b/test1/pcfg2 new file mode 100644 index 0000000..4f3b77b --- /dev/null +++ b/test1/pcfg2 @@ -0,0 +1,9 @@ +mac 10 + +rand w1 (3, 200) +rand w2 (10, 458) 50 +rand w3 (21, 111) 40 +rand w4 (17, 600) + +triple (9469, 87813) (109, 5125) (9135512, 37765626) +triple (855730, 12895925) (7, 5387) (3245747137, 89995070763) diff --git a/test1/pcfg3 b/test1/pcfg3 new file mode 100644 index 0000000..815e9ba --- /dev/null +++ b/test1/pcfg3 @@ -0,0 +1,9 @@ +mac 2 + +rand w1 (82, 1100) +rand w2 (31, 311) +rand w3 (8, 466) +rand w4 (33, 200) 60 + +triple (5089, 30585) (170, 1709) (6847, 152240273) +triple (353, 8408721) (42, 79240) (1531871516, 5563307576)