From dea99b85dc52341265ae2e8463afee8a9709127a Mon Sep 17 00:00:00 2001 From: Uros Majstorovic Date: Thu, 11 Jan 2018 18:03:01 +0100 Subject: fe310 platform introdiced --- code/build.sh | 2 +- code/config_posix.h | 5 + code/core/Makefile | 9 +- code/core/config.h | 5 - code/core/core.c | 3 +- code/core/core.h | 4 +- code/core/crypto/Makefile | 4 +- code/core/crypto/chacha/Makefile | 3 +- code/core/crypto/compat/Makefile | 3 +- code/core/crypto/curve25519/Makefile | 3 +- code/core/crypto/include/chacha.h | 2 +- code/core/crypto/poly1305/Makefile | 3 +- code/core/crypto/sha/Makefile | 3 +- code/core/crypto/test/Makefile | 4 +- code/core/htable/Makefile | 3 +- code/core/posix/Makefile | 3 +- code/core/vconn/Makefile | 14 + code/core/vconn/vconn.c | 613 +++++++++++++++++++++++++++++++++++ code/core/vconn/vconn.h | 22 ++ code/test/Makefile | 7 +- code/test/init_vconn.c | 2 +- code/test/vc_client.c | 2 +- code/test/vc_server.c | 2 +- code/test/vcs.c | 2 +- code/util/Makefile | 5 +- code/vconn/Makefile | 13 - code/vconn/vconn.c | 613 ----------------------------------- code/vconn/vconn.h | 22 -- 28 files changed, 695 insertions(+), 681 deletions(-) create mode 100644 code/config_posix.h delete mode 100644 code/core/config.h create mode 100644 code/core/vconn/Makefile create mode 100644 code/core/vconn/vconn.c create mode 100644 code/core/vconn/vconn.h delete mode 100644 code/vconn/Makefile delete mode 100644 code/vconn/vconn.c delete mode 100644 code/vconn/vconn.h (limited to 'code') diff --git a/code/build.sh b/code/build.sh index ce29ff5..a71b792 100755 --- a/code/build.sh +++ b/code/build.sh @@ -1,6 +1,6 @@ #!/bin/sh -subdirs="core vconn util test" +subdirs="core util test" for i in $subdirs; do (cd $i && make $1 && cd ..) || exit; diff --git a/code/config_posix.h b/code/config_posix.h new file mode 100644 index 0000000..ad67d8a --- /dev/null +++ b/code/config_posix.h @@ -0,0 +1,5 @@ +#define ECP_WITH_PTHREAD 1 +#define ECP_WITH_HTABLE 1 +#define ECP_WITH_RBUF 1 +#define ECP_WITH_MSGQ 1 +#define ECP_DEBUG 1 \ No newline at end of file diff --git a/code/core/Makefile b/code/core/Makefile index ed0f760..88d8c84 100644 --- a/code/core/Makefile +++ b/code/core/Makefile @@ -1,9 +1,8 @@ -MAKE=make -CFLAGS = -I. -pthread -O3 $(PIC) - -obj = core.o timer.o rbuf.o rbuf_send.o rbuf_recv.o msgq.o -subdirs = crypto posix htable +include ../Makefile.platform +CFLAGS=$(CFLAGS_PL) $(PIC) -I. +obj = core.o timer.o $(obj_rbuf) +subdirs = crypto $(vconn) $(htable) $(platform) %.o: %.c $(CC) $(CFLAGS) -c $< diff --git a/code/core/config.h b/code/core/config.h deleted file mode 100644 index ad67d8a..0000000 --- a/code/core/config.h +++ /dev/null @@ -1,5 +0,0 @@ -#define ECP_WITH_PTHREAD 1 -#define ECP_WITH_HTABLE 1 -#define ECP_WITH_RBUF 1 -#define ECP_WITH_MSGQ 1 -#define ECP_DEBUG 1 \ No newline at end of file diff --git a/code/core/core.c b/code/core/core.c index 6eecce2..f81bbc6 100644 --- a/code/core/core.c +++ b/code/core/core.c @@ -590,7 +590,7 @@ int ecp_conn_close(ECPConnection *conn, ecp_cts_t timeout) { refcount = conn->refcount; pthread_mutex_unlock(&conn->mutex); - if (timeout && refcount) { + if (timeout && refcount && sock->ctx->tm.sleep_ms) { sock->ctx->tm.sleep_ms(timeout); pthread_mutex_lock(&conn->mutex); refcount = conn->refcount; @@ -1695,6 +1695,7 @@ int ecp_receiver(ECPSocket *sock) { ecp_cts_t next = 0; if (sock->ctx->tr.recv == NULL) return ECP_ERR; + sock->running = 1; while(sock->running) { ssize_t rv = sock->ctx->tr.recv(&sock->sock, pkt_buf, ECP_MAX_PKT, &addr, next ? next : sock->poll_timeout); diff --git a/code/core/core.h b/code/core/core.h index 7029bd7..3f8fd38 100644 --- a/code/core/core.h +++ b/code/core/core.h @@ -94,7 +94,7 @@ struct ECPConnection; struct ECPSeqItem; struct ECPFragIter; -typedef long ssize_t; +// typedef long ssize_t; typedef uint32_t ecp_ack_t; #define ECP_SIZE_ACKB (sizeof(ecp_ack_t)*8) @@ -130,6 +130,8 @@ typedef uint32_t ecp_seq_t; #define ECP_SIZE_PLD_RAW_BUF(X,T,P) (ECP_SIZE_PLD(X,T)+((P) ? ((P)->pcount+1)*(ECP_SIZE_PKT_HDR+ECP_SIZE_MSG_BUF(T,P)+ECP_AEAD_SIZE_TAG) : 0)) #define ECP_SIZE_PKT_RAW_BUF(X,T,P) (ECP_SIZE_PLD_RAW_BUF(X,T,P)+ECP_SIZE_PKT_HDR+ECP_AEAD_SIZE_TAG) +#include + #ifdef ECP_WITH_PTHREAD #include #endif diff --git a/code/core/crypto/Makefile b/code/core/crypto/Makefile index 2fabea2..a7145c7 100644 --- a/code/core/crypto/Makefile +++ b/code/core/crypto/Makefile @@ -1,5 +1,5 @@ -MAKE=make -CFLAGS=-Iinclude -I.. -D__BEGIN_HIDDEN_DECLS= -D__END_HIDDEN_DECLS= -O3 $(PIC) +include ../../Makefile.platform +CFLAGS=$(CFLAGS_PL) $(PIC) -Iinclude -I.. -D__BEGIN_HIDDEN_DECLS= -D__END_HIDDEN_DECLS= obj = e_chacha20poly1305.o crypto.o obj_dep = compat/explicit_bzero.o compat/timingsafe_memcmp.o compat/timingsafe_bcmp.o \ diff --git a/code/core/crypto/chacha/Makefile b/code/core/crypto/chacha/Makefile index 071a1b1..8a977ae 100644 --- a/code/core/crypto/chacha/Makefile +++ b/code/core/crypto/chacha/Makefile @@ -1,4 +1,5 @@ -CFLAGS=-I../include -D__BEGIN_HIDDEN_DECLS= -D__END_HIDDEN_DECLS= -O3 $(PIC) +include ../../../Makefile.platform +CFLAGS=$(CFLAGS_PL) $(PIC) -I../include -D__BEGIN_HIDDEN_DECLS= -D__END_HIDDEN_DECLS= obj = chacha.o diff --git a/code/core/crypto/compat/Makefile b/code/core/crypto/compat/Makefile index a0dec2d..1afe391 100644 --- a/code/core/crypto/compat/Makefile +++ b/code/core/crypto/compat/Makefile @@ -1,4 +1,5 @@ -CFLAGS=-I../include -D__BEGIN_HIDDEN_DECLS= -D__END_HIDDEN_DECLS= -O3 $(PIC) +include ../../../Makefile.platform +CFLAGS=$(CFLAGS_PL) $(PIC) -I../include -D__BEGIN_HIDDEN_DECLS= -D__END_HIDDEN_DECLS= getentropy = getentropy_osx obj = explicit_bzero.o timingsafe_memcmp.o timingsafe_bcmp.o # arc4random.o arc4random_uniform.o $(getentropy).o diff --git a/code/core/crypto/curve25519/Makefile b/code/core/crypto/curve25519/Makefile index 1a96045..c3f94f0 100644 --- a/code/core/crypto/curve25519/Makefile +++ b/code/core/crypto/curve25519/Makefile @@ -1,4 +1,5 @@ -CFLAGS=-I../include -D__BEGIN_HIDDEN_DECLS= -D__END_HIDDEN_DECLS= -DED25519 -O3 $(PIC) +include ../../../Makefile.platform +CFLAGS=$(CFLAGS_PL) $(PIC) -I../include -D__BEGIN_HIDDEN_DECLS= -D__END_HIDDEN_DECLS= -DED25519 obj = curve25519.o curve25519-generic.o diff --git a/code/core/crypto/include/chacha.h b/code/core/crypto/include/chacha.h index 11885b7..25a3ef3 100644 --- a/code/core/crypto/include/chacha.h +++ b/code/core/crypto/include/chacha.h @@ -32,7 +32,7 @@ typedef struct { } ChaCha_ctx; void ChaCha_set_key(ChaCha_ctx *ctx, const unsigned char *key, - unsigned int keybits); + uint32_t keybits); void ChaCha_set_iv(ChaCha_ctx *ctx, const unsigned char *iv, const unsigned char *counter); void ChaCha(ChaCha_ctx *ctx, unsigned char *out, const unsigned char *in, diff --git a/code/core/crypto/poly1305/Makefile b/code/core/crypto/poly1305/Makefile index e780491..6bc384f 100644 --- a/code/core/crypto/poly1305/Makefile +++ b/code/core/crypto/poly1305/Makefile @@ -1,4 +1,5 @@ -CFLAGS=-I../include -D__BEGIN_HIDDEN_DECLS= -D__END_HIDDEN_DECLS= -O3 $(PIC) +include ../../../Makefile.platform +CFLAGS=$(CFLAGS_PL) $(PIC) -I../include -D__BEGIN_HIDDEN_DECLS= -D__END_HIDDEN_DECLS= obj = poly1305.o diff --git a/code/core/crypto/sha/Makefile b/code/core/crypto/sha/Makefile index f078644..1eb727f 100644 --- a/code/core/crypto/sha/Makefile +++ b/code/core/crypto/sha/Makefile @@ -1,4 +1,5 @@ -CFLAGS=-I../include -D__BEGIN_HIDDEN_DECLS= -D__END_HIDDEN_DECLS= -O3 $(PIC) +include ../../../Makefile.platform +CFLAGS=$(CFLAGS_PL) $(PIC) -I../include -D__BEGIN_HIDDEN_DECLS= -D__END_HIDDEN_DECLS= obj = sha1dgst.o sha1_one.o sha256.o sha512.o diff --git a/code/core/crypto/test/Makefile b/code/core/crypto/test/Makefile index f274209..2a5fa3e 100644 --- a/code/core/crypto/test/Makefile +++ b/code/core/crypto/test/Makefile @@ -1,4 +1,6 @@ -CFLAGS=-I.. -I../include -O3 +include ../../../Makefile.platform +CFLAGS=$(CFLAGS_PL) -I.. -I../include +LDFLAGS=$(LDFLAGS_PL) aead_dep=../compat/explicit_bzero.o ../compat/timingsafe_memcmp.o ../compat/timingsafe_bcmp.o \ ../chacha/chacha.o ../poly1305/poly1305.o ../curve25519/curve25519.o ../curve25519/curve25519-generic.o \ diff --git a/code/core/htable/Makefile b/code/core/htable/Makefile index af8d7c1..eb73403 100644 --- a/code/core/htable/Makefile +++ b/code/core/htable/Makefile @@ -1,4 +1,5 @@ -CFLAGS=-I.. -std=gnu89 $(PIC) +include ../../Makefile.platform +CFLAGS=$(CFLAGS_PL) $(PIC) -I.. -std=gnu89 obj = htable.o hashtable.o hashtable_itr.o diff --git a/code/core/posix/Makefile b/code/core/posix/Makefile index 00c8048..6dd42e2 100644 --- a/code/core/posix/Makefile +++ b/code/core/posix/Makefile @@ -1,4 +1,5 @@ -CFLAGS=-I.. $(PIC) +include ../../Makefile.platform +CFLAGS=$(CFLAGS_PL) $(PIC) -I.. obj_tr = transport.o obj_tm = time.o diff --git a/code/core/vconn/Makefile b/code/core/vconn/Makefile new file mode 100644 index 0000000..613601c --- /dev/null +++ b/code/core/vconn/Makefile @@ -0,0 +1,14 @@ +include ../../Makefile.platform +CFLAGS=$(CFLAGS_PL) $(PIC) -I.. + +obj = vconn.o + + +%.o: %.c %.h + $(CC) $(CFLAGS) -c $< + +all: $(obj) + $(AR) rcs libecpvconn.a $(obj) + +clean: + rm -f *.o *.a \ No newline at end of file diff --git a/code/core/vconn/vconn.c b/code/core/vconn/vconn.c new file mode 100644 index 0000000..dadff0f --- /dev/null +++ b/code/core/vconn/vconn.c @@ -0,0 +1,613 @@ +#include "core.h" +#include "vconn.h" + +#include + +#ifdef ECP_WITH_PTHREAD +static pthread_mutex_t key_perma_mutex; +static pthread_mutex_t key_next_mutex; +#endif + +static void *key_perma_table; +static void *key_next_table; + +static unsigned char key_null[ECP_ECDH_SIZE_KEY] = { 0 }; + +static ECPConnHandler handler_vc; +static ECPConnHandler handler_vl; + +static int vconn_create(ECPConnection *conn, unsigned char *payload, size_t size) { + ECPContext *ctx = conn->sock->ctx; + ECPVConnIn *conn_v = (ECPVConnIn *)conn; + int rv = ECP_OK; + + if (conn->out) return ECP_ERR; + if (conn->type != ECP_CTYPE_VCONN) return ECP_ERR; + if (size < 2*ECP_ECDH_SIZE_KEY) return ECP_ERR; + + conn_v->key_next_curr = 0; + memset(conn_v->key_next, 0, sizeof(conn_v->key_next)); + memset(conn_v->key_out, 0, sizeof(conn_v->key_out)); + memcpy(conn_v->key_next[conn_v->key_next_curr], payload, ECP_ECDH_SIZE_KEY); + memcpy(conn_v->key_out, payload+ECP_ECDH_SIZE_KEY, ECP_ECDH_SIZE_KEY); + +#ifdef ECP_WITH_PTHREAD + pthread_mutex_lock(&key_next_mutex); +#endif +#ifdef ECP_WITH_HTABLE + rv = ctx->ht.init ? ctx->ht.insert(key_next_table, conn_v->key_next[conn_v->key_next_curr], conn) : ECP_ERR; +#endif +#ifdef ECP_WITH_PTHREAD + pthread_mutex_unlock(&key_next_mutex); +#endif + + return rv; +} + +static void vconn_destroy(ECPConnection *conn) { + ECPContext *ctx = conn->sock->ctx; + ECPVConnIn *conn_v = (ECPVConnIn *)conn; + + if (conn->out) return; + if (conn->type != ECP_CTYPE_VCONN) return; + +#ifdef ECP_WITH_PTHREAD + pthread_mutex_lock(&key_next_mutex); + pthread_mutex_lock(&conn->mutex); +#endif +#ifdef ECP_WITH_HTABLE + if (ctx->ht.init) { + int i; + for (i=0; ikey_next[i], key_null, ECP_ECDH_SIZE_KEY)) ctx->ht.remove(key_next_table, conn_v->key_next[i]); + } + } +#endif +#ifdef ECP_WITH_PTHREAD + pthread_mutex_unlock(&conn->mutex); + pthread_mutex_unlock(&key_next_mutex); +#endif +} + +static ssize_t _vconn_send_open(ECPConnection *conn, ECPTimerItem *ti) { + ECPBuffer packet; + ECPBuffer payload; + unsigned char pkt_buf[ECP_SIZE_PKT_BUF(0, ECP_MTYPE_KGET_REQ, conn)]; + unsigned char pld_buf[ECP_SIZE_PLD_BUF(0, ECP_MTYPE_KGET_REQ, conn)]; + + packet.buffer = pkt_buf; + packet.size = ECP_SIZE_PKT_BUF(0, ECP_MTYPE_KGET_REQ, conn); + payload.buffer = pld_buf; + payload.size = ECP_SIZE_PLD_BUF(0, ECP_MTYPE_KGET_REQ, conn); + + ecp_pld_set_type(pld_buf, ECP_MTYPE_KGET_REQ); + return ecp_pld_send_ll(conn, &packet, ECP_ECDH_IDX_PERMA, ECP_ECDH_IDX_INV, &payload, ECP_SIZE_PLD(0, ECP_MTYPE_KGET_REQ), ti); +} + +static ssize_t vconn_open(ECPConnection *conn) { + int rv = ECP_OK; + ECPTimerItem ti; + ECPVConnection *conn_v = (ECPVConnection *)conn; + ECPConnection *conn_next = conn_v->next; + + if (conn_next == NULL) return ECP_ERR; + + ssize_t _rv = ecp_timer_send(conn_next, _vconn_send_open, ECP_MTYPE_KGET_REP, 3, 3000); + if (_rv < 0) return _rv; + + return _rv; +} + +static ssize_t vconn_handle_open(ECPConnection *conn, ecp_seq_t seq, unsigned char mtype, unsigned char *msg, ssize_t size, ECP2Buffer *b) { + if (conn->type != ECP_CTYPE_VCONN) return ECP_ERR; + + if (mtype & ECP_MTYPE_FLAG_REP) { + if (!conn->out) return ECP_ERR; + if (size < 0) { + ecp_conn_handler_msg_t *handler = NULL; + while (conn->type == ECP_CTYPE_VCONN) { + ECPVConnection *conn_v = (ECPVConnection *)conn; + conn = conn_v->next; + } + handler = conn->sock->ctx->handler[conn->type] ? conn->sock->ctx->handler[conn->type]->msg[ECP_MTYPE_OPEN] : NULL; + return handler ? handler(conn, seq, mtype, msg, size, b) : size; + } + + return ecp_conn_handle_open(conn, seq, mtype, msg, size, b); + } else { + ECPContext *ctx = conn->sock->ctx; + ECPVConnIn *conn_v = (ECPVConnIn *)conn; + int rv = ECP_OK; + unsigned char ctype = 0; + + if (conn->out) return ECP_ERR; + if (size < 0) return size; + if (size < 1+2*ECP_ECDH_SIZE_KEY) return ECP_ERR; + +#ifdef ECP_WITH_PTHREAD + pthread_mutex_lock(&key_next_mutex); + pthread_mutex_lock(&conn->mutex); +#endif + + ctype = msg[0]; + msg++; + + if (!ecp_conn_is_open(conn)) conn->flags |= ECP_CONN_FLAG_OPEN; + if (memcmp(conn_v->key_next[conn_v->key_next_curr], msg, ECP_ECDH_SIZE_KEY)) { + conn_v->key_next_curr = (conn_v->key_next_curr + 1) % ECP_MAX_NODE_KEY; +#ifdef ECP_WITH_HTABLE + if (ctx->ht.init) { + if (memcmp(conn_v->key_next[conn_v->key_next_curr], key_null, ECP_ECDH_SIZE_KEY)) ctx->ht.remove(key_next_table, conn_v->key_next[conn_v->key_next_curr]); + rv = ctx->ht.insert(key_next_table, conn_v->key_next[conn_v->key_next_curr], conn); + } else { + rv = ECP_ERR; + } +#endif + if (!rv) memcpy(conn_v->key_next[conn_v->key_next_curr], msg, ECP_ECDH_SIZE_KEY); + } + +#ifdef ECP_WITH_PTHREAD + pthread_mutex_unlock(&conn->mutex); + pthread_mutex_unlock(&key_next_mutex); +#endif + + if (rv) return rv; + + return 1+2*ECP_ECDH_SIZE_KEY; + } + + return ECP_ERR; +} + +static ssize_t vconn_handle_relay(ECPConnection *conn, ecp_seq_t seq, unsigned char mtype, unsigned char *msg, ssize_t size, ECP2Buffer *b) { + ECPContext *ctx = conn->sock->ctx; + ECPConnection *conn_out = NULL; + ECPVConnIn *conn_v = (ECPVConnIn *)conn; + ssize_t rv; + + if (conn->out) return ECP_ERR; + if (conn->type != ECP_CTYPE_VCONN) return ECP_ERR; + if (b == NULL) return ECP_ERR; + + if (size < 0) return size; + if (size < ECP_MIN_PKT) return ECP_ERR_MIN_PKT; + +#ifdef ECP_WITH_PTHREAD + pthread_mutex_lock(&key_perma_mutex); +#endif +#ifdef ECP_WITH_HTABLE + conn_out = ctx->ht.init ? ctx->ht.search(key_perma_table, conn_v->key_out) : NULL; +#endif + if (conn_out) { +#ifdef ECP_WITH_PTHREAD + pthread_mutex_lock(&conn_out->mutex); +#endif + conn_out->refcount++; +#ifdef ECP_WITH_PTHREAD + pthread_mutex_unlock(&conn_out->mutex); +#endif + } +#ifdef ECP_WITH_PTHREAD + pthread_mutex_unlock(&key_perma_mutex); +#endif + + if (conn_out == NULL) return ECP_ERR; + + ECPBuffer payload; + payload.buffer = msg - ECP_SIZE_PLD_HDR - 1; + payload.size = b->payload->size - (payload.buffer - b->payload->buffer); + + ecp_pld_set_type(payload.buffer, ECP_MTYPE_EXEC); + rv = ecp_pld_send(conn_out, b->packet, &payload, ECP_SIZE_PLD_HDR+1+size); + +#ifdef ECP_WITH_PTHREAD + pthread_mutex_lock(&conn_out->mutex); +#endif + conn_out->refcount--; +#ifdef ECP_WITH_PTHREAD + pthread_mutex_unlock(&conn_out->mutex); +#endif + + if (rv < 0) return rv; + return size; +} + +static int vlink_insert(ECPConnection *conn) { + int rv = ECP_OK; + ECPContext *ctx = conn->sock->ctx; + +#ifdef ECP_WITH_PTHREAD + pthread_mutex_lock(&key_perma_mutex); +#endif +#ifdef ECP_WITH_HTABLE + rv = ctx->ht.init ? ctx->ht.insert(key_perma_table, ctx->cr.dh_pub_get_buf(&conn->node.public), conn) : ECP_OK; +#endif +#ifdef ECP_WITH_PTHREAD + pthread_mutex_unlock(&key_perma_mutex); +#endif + + return rv; +} + +static void vlink_remove(ECPConnection *conn) { + ECPContext *ctx = conn->sock->ctx; + +#ifdef ECP_WITH_PTHREAD + pthread_mutex_lock(&key_perma_mutex); +#endif +#ifdef ECP_WITH_HTABLE + if (ctx->ht.init) ctx->ht.remove(key_perma_table, ctx->cr.dh_pub_get_buf(&conn->node.public)); +#endif +#ifdef ECP_WITH_PTHREAD + pthread_mutex_unlock(&key_perma_mutex); +#endif +} + +static int vlink_create(ECPConnection *conn, unsigned char *payload, size_t size) { + ECPContext *ctx = conn->sock->ctx; + + if (conn->out) return ECP_ERR; + if (conn->type != ECP_CTYPE_VLINK) return ECP_ERR; + + // XXX should verify perma_key + if (size < ECP_ECDH_SIZE_KEY) return ECP_ERR; + ctx->cr.dh_pub_from_buf(&conn->node.public, payload); + + return vlink_insert(conn); +} + +static void vlink_destroy(ECPConnection *conn) { + ECPContext *ctx = conn->sock->ctx; + + if (conn->out) return; + if (conn->type != ECP_CTYPE_VLINK) return; + + vlink_remove(conn); +} + +static ssize_t _vlink_send_open(ECPConnection *conn, ECPTimerItem *ti) { + ECPSocket *sock = conn->sock; + ECPContext *ctx = sock->ctx; + + ECPBuffer packet; + ECPBuffer payload; + unsigned char pkt_buf[ECP_SIZE_PKT_BUF(ECP_ECDH_SIZE_KEY+1, ECP_MTYPE_OPEN_REQ, conn)]; + unsigned char pld_buf[ECP_SIZE_PLD_BUF(ECP_ECDH_SIZE_KEY+1, ECP_MTYPE_OPEN_REQ, conn)]; + unsigned char *buf = ecp_pld_get_buf(pld_buf, ECP_MTYPE_OPEN_REQ); + int rv = ECP_OK; + + packet.buffer = pkt_buf; + packet.size = ECP_SIZE_PKT_BUF(ECP_ECDH_SIZE_KEY+1, ECP_MTYPE_OPEN_REQ, conn); + payload.buffer = pld_buf; + payload.size = ECP_SIZE_PLD_BUF(ECP_ECDH_SIZE_KEY+1, ECP_MTYPE_OPEN_REQ, conn); + + // XXX server should verify perma_key + ecp_pld_set_type(pld_buf, ECP_MTYPE_OPEN_REQ); + buf[0] = conn->type; + memcpy(buf+1, ctx->cr.dh_pub_get_buf(&sock->key_perma.public), ECP_ECDH_SIZE_KEY); + + return ecp_pld_send_wtimer(conn, &packet, &payload, ECP_SIZE_PLD(ECP_ECDH_SIZE_KEY+1, ECP_MTYPE_OPEN_REQ), ti); +} + +static ssize_t vlink_open(ECPConnection *conn) { + return ecp_timer_send(conn, _vlink_send_open, ECP_MTYPE_OPEN_REP, 3, 500); +} + +static void vlink_close(ECPConnection *conn) { + vlink_remove(conn); +} + +static ssize_t vlink_handle_open(ECPConnection *conn, ecp_seq_t seq, unsigned char mtype, unsigned char *msg, ssize_t size, ECP2Buffer *b) { + ssize_t rv; + int is_open; + + if (conn->type != ECP_CTYPE_VLINK) return ECP_ERR; + + if (size < 0) return size; + +#ifdef ECP_WITH_PTHREAD + pthread_mutex_lock(&conn->mutex); +#endif + is_open = ecp_conn_is_open(conn); +#ifdef ECP_WITH_PTHREAD + pthread_mutex_unlock(&conn->mutex); +#endif + + rv = ecp_conn_handle_open(conn, seq, mtype, msg, size, b); + if (rv < 0) return rv; + + if (mtype & ECP_MTYPE_FLAG_REP) { + if (!conn->out) return ECP_ERR; + if (!is_open) { + int rv = vlink_insert(conn); + if (rv) return rv; + } + return rv; + } else { + if (conn->out) return ECP_ERR; + if (size < rv+ECP_ECDH_SIZE_KEY) return ECP_ERR; + + msg += rv; + + // XXX should verify perma_key + return rv+ECP_ECDH_SIZE_KEY; + } + + return ECP_ERR; +} + +static ssize_t vlink_handle_relay(ECPConnection *conn, ecp_seq_t seq, unsigned char mtype, unsigned char *msg, ssize_t size, ECP2Buffer *b) { + ECPContext *ctx = conn->sock->ctx; + ssize_t rv; + + if (conn->type != ECP_CTYPE_VLINK) return ECP_ERR; + if (b == NULL) return ECP_ERR; + + if (size < 0) return size; + if (size < ECP_MIN_PKT) return ECP_ERR_MIN_PKT; + +#ifdef ECP_WITH_PTHREAD + pthread_mutex_lock(&key_next_mutex); +#endif +#ifdef ECP_WITH_HTABLE + conn = ctx->ht.init ? ctx->ht.search(key_next_table, msg+ECP_SIZE_PROTO+1) : NULL; +#endif + if (conn) { +#ifdef ECP_WITH_PTHREAD + pthread_mutex_lock(&conn->mutex); +#endif + conn->refcount++; +#ifdef ECP_WITH_PTHREAD + pthread_mutex_unlock(&conn->mutex); +#endif + } +#ifdef ECP_WITH_PTHREAD + pthread_mutex_unlock(&key_next_mutex); +#endif + + if (conn == NULL) return ECP_ERR; + + ECPBuffer payload; + payload.buffer = msg - ECP_SIZE_PLD_HDR - 1; + payload.size = b->payload->size - (payload.buffer - b->payload->buffer); + + ecp_pld_set_type(payload.buffer, ECP_MTYPE_EXEC); + rv = ecp_pld_send(conn, b->packet, &payload, ECP_SIZE_PLD_HDR+1+size); + +#ifdef ECP_WITH_PTHREAD + pthread_mutex_lock(&conn->mutex); +#endif + conn->refcount--; +#ifdef ECP_WITH_PTHREAD + pthread_mutex_unlock(&conn->mutex); +#endif + + if (rv < 0) return rv; + return size; +} + +static ssize_t vconn_set_msg(ECPConnection *conn, ECPBuffer *payload, unsigned char mtype) { + if (conn->out && (conn->type == ECP_CTYPE_VCONN) && ((mtype == ECP_MTYPE_OPEN_REQ) || (mtype == ECP_MTYPE_KGET_REQ))) { + ECPVConnection *conn_v = (ECPVConnection *)conn; + ECPContext *ctx = conn->sock->ctx; + ECPConnection *conn_next = conn_v->next; + unsigned char *buf = NULL; + int rv; + + if (payload->size < ECP_SIZE_PLD_HDR + 3 + 2 * ECP_ECDH_SIZE_KEY) return ECP_ERR; + if (conn_next == NULL) return ECP_ERR; + + ecp_pld_set_type(payload->buffer, ECP_MTYPE_OPEN_REQ); + buf = ecp_pld_get_buf(payload->buffer, 0); + + buf[0] = ECP_CTYPE_VCONN; + rv = ecp_conn_dhkey_get_curr(conn_next, NULL, buf+1); + if (rv) return rv; + + memcpy(buf+1+ECP_ECDH_SIZE_KEY, ctx->cr.dh_pub_get_buf(&conn_next->node.public), ECP_ECDH_SIZE_KEY); + buf[1+2*ECP_ECDH_SIZE_KEY] = ECP_MTYPE_RELAY; + + return ECP_SIZE_PLD_HDR + 3 + 2 * ECP_ECDH_SIZE_KEY; + } else { + if (payload->size < ECP_SIZE_PLD_HDR + 1) return ECP_ERR; + + ecp_pld_set_type(payload->buffer, ECP_MTYPE_RELAY); + + return ECP_SIZE_PLD_HDR + 1; + } + +} + +/* Memory limited version: */ +static ssize_t vconn_pack(ECPConnection *conn, ECPBuffer *packet, unsigned char s_idx, unsigned char c_idx, ECPBuffer *payload, size_t pld_size, ECPSeqItem *si, ECPNetAddr *addr) { + ECPContext *ctx = conn->sock->ctx; + + if (conn->parent) { + unsigned char mtype = ecp_pld_get_type(payload->buffer); + ssize_t rv, hdr_size = vconn_set_msg(conn->parent, packet, mtype); + if (hdr_size < 0) return hdr_size; + + rv = ecp_conn_pack(conn, packet->buffer+hdr_size, packet->size-hdr_size, s_idx, c_idx, payload->buffer, pld_size, si, NULL); + if (rv < 0) return rv; + + if (payload->size < rv+hdr_size) return ECP_ERR; + memcpy(payload->buffer, packet->buffer, rv+hdr_size); + + return vconn_pack(conn->parent, packet, ECP_ECDH_IDX_INV, ECP_ECDH_IDX_INV, payload, rv+hdr_size, NULL, addr); + } else { + return ecp_conn_pack(conn, packet->buffer, packet->size, s_idx, c_idx, payload->buffer, pld_size, si, addr); + } +} + +static ssize_t vconn_pack_raw(ECPSocket *sock, ECPConnection *parent, ECPBuffer *packet, unsigned char s_idx, unsigned char c_idx, ecp_dh_public_t *public, ecp_aead_key_t *shsec, unsigned char *nonce, ecp_seq_t seq, ECPBuffer *payload, size_t pld_size, ECPNetAddr *addr) { + ECPContext *ctx = sock->ctx; + + if (parent) { + unsigned char mtype = ecp_pld_get_type(payload->buffer); + ssize_t rv, hdr_size = vconn_set_msg(parent, packet, mtype); + if (hdr_size < 0) return hdr_size; + + rv = ecp_pack(ctx, packet->buffer+hdr_size, packet->size-hdr_size, s_idx, c_idx, public, shsec, nonce, seq, payload->buffer, pld_size); + if (rv < 0) return rv; + + if (payload->size < rv+hdr_size) return ECP_ERR; + memcpy(payload->buffer, packet->buffer, rv+hdr_size); + + return vconn_pack(parent, packet, ECP_ECDH_IDX_INV, ECP_ECDH_IDX_INV, payload, rv+hdr_size, NULL, addr); + } else { + return ecp_pack(ctx, packet->buffer, packet->size, s_idx, c_idx, public, shsec, nonce, seq, payload->buffer, pld_size); + } +} + +/* Non memory limited version: */ +/* +static ssize_t vconn_pack(ECPConnection *conn, ECPBuffer *packet, unsigned char s_idx, unsigned char c_idx, ECPBuffer *payload, size_t pld_size, ECPSeqItem *si, ECPNetAddr *addr) { + ECPContext *ctx = conn->sock->ctx; + + if (conn->parent) { + ECPBuffer payload_; + unsigned char pld_buf[ECP_MAX_PLD]; + + payload_.buffer = pld_buf; + payload_.size = ECP_MAX_PLD; + + unsigned char mtype = ecp_pld_get_type(payload->buffer); + ssize_t rv, hdr_size = vconn_set_msg(conn->parent, &payload_, mtype); + if (hdr_size < 0) return hdr_size; + + rv = ecp_conn_pack(conn, payload_.buffer+hdr_size, payload_.size-hdr_size, s_idx, c_idx, payload->buffer, pld_size, si, NULL); + if (rv < 0) return rv; + + return vconn_pack(conn->parent, packet, ECP_ECDH_IDX_INV, ECP_ECDH_IDX_INV, &payload_, rv+hdr_size, NULL, addr); + } else { + return ecp_conn_pack(conn, packet->buffer, packet->size, s_idx, c_idx, payload->buffer, pld_size, si, addr); + } +} + +static ssize_t vconn_pack_raw(ECPSocket *sock, ECPConnection *parent, ECPBuffer *packet, unsigned char s_idx, unsigned char c_idx, ecp_dh_public_t *public, ecp_aead_key_t *shsec, unsigned char *nonce, ecp_seq_t seq, ECPBuffer *payload, size_t pld_size, ECPNetAddr *addr) { + ECPContext *ctx = sock->ctx; + + if (parent) { + ECPBuffer payload_; + unsigned char pld_buf[ECP_MAX_PLD]; + + payload_.buffer = pld_buf; + payload_.size = ECP_MAX_PLD; + + unsigned char mtype = ecp_pld_get_type(payload->buffer); + ssize_t rv, hdr_size = vconn_set_msg(parent, &payload_, mtype); + if (hdr_size < 0) return hdr_size; + + rv = ecp_pack(ctx, payload_.buffer+hdr_size, payload_.size-hdr_size, s_idx, c_idx, public, shsec, nonce, seq, payload->buffer, pld_size); + if (rv < 0) return rv; + + return vconn_pack(parent, packet, ECP_ECDH_IDX_INV, ECP_ECDH_IDX_INV, &payload_, rv+hdr_size, NULL, addr); + } else { + return ecp_pack(ctx, packet->buffer, packet->size, s_idx, c_idx, public, shsec, nonce, seq, payload->buffer, pld_size); + } +} +*/ + +int ecp_ctx_vconn_init(ECPContext *ctx) { + int rv; + + rv = ecp_conn_handler_init(&handler_vc); + if (rv) return rv; + + handler_vc.conn_create = vconn_create; + handler_vc.conn_destroy = vconn_destroy; + handler_vc.conn_open = vconn_open; + handler_vc.msg[ECP_MTYPE_OPEN] = vconn_handle_open; + handler_vc.msg[ECP_MTYPE_EXEC] = ecp_conn_handle_exec; + handler_vc.msg[ECP_MTYPE_RELAY] = vconn_handle_relay; + ctx->handler[ECP_CTYPE_VCONN] = &handler_vc; + + rv = ecp_conn_handler_init(&handler_vl); + if (rv) return rv; + + handler_vl.conn_create = vlink_create; + handler_vl.conn_destroy = vlink_destroy; + handler_vl.conn_open = vlink_open; + handler_vl.conn_close = vlink_close; + handler_vl.msg[ECP_MTYPE_OPEN] = vlink_handle_open; + handler_vl.msg[ECP_MTYPE_EXEC] = ecp_conn_handle_exec; + handler_vl.msg[ECP_MTYPE_RELAY] = vlink_handle_relay; + ctx->handler[ECP_CTYPE_VLINK] = &handler_vl; + + ctx->pack = vconn_pack; + ctx->pack_raw = vconn_pack_raw; + +#ifdef ECP_WITH_PTHREAD + rv = pthread_mutex_init(&key_perma_mutex, NULL); + if (!rv) pthread_mutex_init(&key_next_mutex, NULL); + if (rv) return ECP_ERR; +#endif + +#ifdef ECP_WITH_HTABLE + if (ctx->ht.init) { + key_perma_table = ctx->ht.create(ctx); + key_next_table = ctx->ht.create(ctx); + if ((key_perma_table == NULL) || (key_next_table == NULL)) return ECP_ERR; + } +#endif + + return ECP_OK; +} + +int ecp_vconn_init(ECPConnection *conn, ECPNode *conn_node, ECPVConnection vconn[], ECPNode vconn_node[], int size) { + ECPSocket *sock = conn->sock; + int i, rv; + + rv = ecp_conn_init(conn, conn_node); + if (rv) return rv; + + conn->parent = (ECPConnection *)&vconn[size-1]; + conn->pcount = size; + for (i=0; i #include "core.h" -#include "vconn.h" +#include "vconn/vconn.h" static int v_rng(void *buf, size_t bufsize) { int fd; diff --git a/code/test/vc_client.c b/code/test/vc_client.c index 9ea3d1b..e654e76 100644 --- a/code/test/vc_client.c +++ b/code/test/vc_client.c @@ -4,7 +4,7 @@ #include #include "core.h" -#include "vconn.h" +#include "vconn/vconn.h" #include "util.h" ECPContext ctx; diff --git a/code/test/vc_server.c b/code/test/vc_server.c index 8525ad4..04b8104 100644 --- a/code/test/vc_server.c +++ b/code/test/vc_server.c @@ -4,7 +4,7 @@ #include #include "core.h" -#include "vconn.h" +#include "vconn/vconn.h" #include "util.h" ECPContext ctx; diff --git a/code/test/vcs.c b/code/test/vcs.c index 1dbf67d..23e2557 100644 --- a/code/test/vcs.c +++ b/code/test/vcs.c @@ -5,7 +5,7 @@ #include "core.h" #include "util.h" -#include "vconn.h" +#include "vconn/vconn.h" ECPContext ctx; ECPSocket sock; diff --git a/code/util/Makefile b/code/util/Makefile index 0e76307..caa8226 100644 --- a/code/util/Makefile +++ b/code/util/Makefile @@ -1,5 +1,6 @@ -CFLAGS = -I../core -pthread -O3 $(PIC) -LDFLAGS=-lm -pthread +include ../Makefile.platform +CFLAGS=$(CFLAGS_PL) -I../core +LDFLAGS=$(LDFLAGS_PL) obj=util.o dep=../core/libecpcore.a ../core/crypto/libecpcr.a ../core/htable/libecpht.a ../core/posix/libecptr.a ../core/posix/libecptm.a ./libecputil.a diff --git a/code/vconn/Makefile b/code/vconn/Makefile deleted file mode 100644 index 0292b0d..0000000 --- a/code/vconn/Makefile +++ /dev/null @@ -1,13 +0,0 @@ -CFLAGS = -I../core -pthread -O3 $(PIC) - -obj = vconn.o - - -%.o: %.c %.h - $(CC) $(CFLAGS) -c $< - -all: $(obj) - $(AR) rcs libecpvconn.a $(obj) - -clean: - rm -f *.o *.a \ No newline at end of file diff --git a/code/vconn/vconn.c b/code/vconn/vconn.c deleted file mode 100644 index dadff0f..0000000 --- a/code/vconn/vconn.c +++ /dev/null @@ -1,613 +0,0 @@ -#include "core.h" -#include "vconn.h" - -#include - -#ifdef ECP_WITH_PTHREAD -static pthread_mutex_t key_perma_mutex; -static pthread_mutex_t key_next_mutex; -#endif - -static void *key_perma_table; -static void *key_next_table; - -static unsigned char key_null[ECP_ECDH_SIZE_KEY] = { 0 }; - -static ECPConnHandler handler_vc; -static ECPConnHandler handler_vl; - -static int vconn_create(ECPConnection *conn, unsigned char *payload, size_t size) { - ECPContext *ctx = conn->sock->ctx; - ECPVConnIn *conn_v = (ECPVConnIn *)conn; - int rv = ECP_OK; - - if (conn->out) return ECP_ERR; - if (conn->type != ECP_CTYPE_VCONN) return ECP_ERR; - if (size < 2*ECP_ECDH_SIZE_KEY) return ECP_ERR; - - conn_v->key_next_curr = 0; - memset(conn_v->key_next, 0, sizeof(conn_v->key_next)); - memset(conn_v->key_out, 0, sizeof(conn_v->key_out)); - memcpy(conn_v->key_next[conn_v->key_next_curr], payload, ECP_ECDH_SIZE_KEY); - memcpy(conn_v->key_out, payload+ECP_ECDH_SIZE_KEY, ECP_ECDH_SIZE_KEY); - -#ifdef ECP_WITH_PTHREAD - pthread_mutex_lock(&key_next_mutex); -#endif -#ifdef ECP_WITH_HTABLE - rv = ctx->ht.init ? ctx->ht.insert(key_next_table, conn_v->key_next[conn_v->key_next_curr], conn) : ECP_ERR; -#endif -#ifdef ECP_WITH_PTHREAD - pthread_mutex_unlock(&key_next_mutex); -#endif - - return rv; -} - -static void vconn_destroy(ECPConnection *conn) { - ECPContext *ctx = conn->sock->ctx; - ECPVConnIn *conn_v = (ECPVConnIn *)conn; - - if (conn->out) return; - if (conn->type != ECP_CTYPE_VCONN) return; - -#ifdef ECP_WITH_PTHREAD - pthread_mutex_lock(&key_next_mutex); - pthread_mutex_lock(&conn->mutex); -#endif -#ifdef ECP_WITH_HTABLE - if (ctx->ht.init) { - int i; - for (i=0; ikey_next[i], key_null, ECP_ECDH_SIZE_KEY)) ctx->ht.remove(key_next_table, conn_v->key_next[i]); - } - } -#endif -#ifdef ECP_WITH_PTHREAD - pthread_mutex_unlock(&conn->mutex); - pthread_mutex_unlock(&key_next_mutex); -#endif -} - -static ssize_t _vconn_send_open(ECPConnection *conn, ECPTimerItem *ti) { - ECPBuffer packet; - ECPBuffer payload; - unsigned char pkt_buf[ECP_SIZE_PKT_BUF(0, ECP_MTYPE_KGET_REQ, conn)]; - unsigned char pld_buf[ECP_SIZE_PLD_BUF(0, ECP_MTYPE_KGET_REQ, conn)]; - - packet.buffer = pkt_buf; - packet.size = ECP_SIZE_PKT_BUF(0, ECP_MTYPE_KGET_REQ, conn); - payload.buffer = pld_buf; - payload.size = ECP_SIZE_PLD_BUF(0, ECP_MTYPE_KGET_REQ, conn); - - ecp_pld_set_type(pld_buf, ECP_MTYPE_KGET_REQ); - return ecp_pld_send_ll(conn, &packet, ECP_ECDH_IDX_PERMA, ECP_ECDH_IDX_INV, &payload, ECP_SIZE_PLD(0, ECP_MTYPE_KGET_REQ), ti); -} - -static ssize_t vconn_open(ECPConnection *conn) { - int rv = ECP_OK; - ECPTimerItem ti; - ECPVConnection *conn_v = (ECPVConnection *)conn; - ECPConnection *conn_next = conn_v->next; - - if (conn_next == NULL) return ECP_ERR; - - ssize_t _rv = ecp_timer_send(conn_next, _vconn_send_open, ECP_MTYPE_KGET_REP, 3, 3000); - if (_rv < 0) return _rv; - - return _rv; -} - -static ssize_t vconn_handle_open(ECPConnection *conn, ecp_seq_t seq, unsigned char mtype, unsigned char *msg, ssize_t size, ECP2Buffer *b) { - if (conn->type != ECP_CTYPE_VCONN) return ECP_ERR; - - if (mtype & ECP_MTYPE_FLAG_REP) { - if (!conn->out) return ECP_ERR; - if (size < 0) { - ecp_conn_handler_msg_t *handler = NULL; - while (conn->type == ECP_CTYPE_VCONN) { - ECPVConnection *conn_v = (ECPVConnection *)conn; - conn = conn_v->next; - } - handler = conn->sock->ctx->handler[conn->type] ? conn->sock->ctx->handler[conn->type]->msg[ECP_MTYPE_OPEN] : NULL; - return handler ? handler(conn, seq, mtype, msg, size, b) : size; - } - - return ecp_conn_handle_open(conn, seq, mtype, msg, size, b); - } else { - ECPContext *ctx = conn->sock->ctx; - ECPVConnIn *conn_v = (ECPVConnIn *)conn; - int rv = ECP_OK; - unsigned char ctype = 0; - - if (conn->out) return ECP_ERR; - if (size < 0) return size; - if (size < 1+2*ECP_ECDH_SIZE_KEY) return ECP_ERR; - -#ifdef ECP_WITH_PTHREAD - pthread_mutex_lock(&key_next_mutex); - pthread_mutex_lock(&conn->mutex); -#endif - - ctype = msg[0]; - msg++; - - if (!ecp_conn_is_open(conn)) conn->flags |= ECP_CONN_FLAG_OPEN; - if (memcmp(conn_v->key_next[conn_v->key_next_curr], msg, ECP_ECDH_SIZE_KEY)) { - conn_v->key_next_curr = (conn_v->key_next_curr + 1) % ECP_MAX_NODE_KEY; -#ifdef ECP_WITH_HTABLE - if (ctx->ht.init) { - if (memcmp(conn_v->key_next[conn_v->key_next_curr], key_null, ECP_ECDH_SIZE_KEY)) ctx->ht.remove(key_next_table, conn_v->key_next[conn_v->key_next_curr]); - rv = ctx->ht.insert(key_next_table, conn_v->key_next[conn_v->key_next_curr], conn); - } else { - rv = ECP_ERR; - } -#endif - if (!rv) memcpy(conn_v->key_next[conn_v->key_next_curr], msg, ECP_ECDH_SIZE_KEY); - } - -#ifdef ECP_WITH_PTHREAD - pthread_mutex_unlock(&conn->mutex); - pthread_mutex_unlock(&key_next_mutex); -#endif - - if (rv) return rv; - - return 1+2*ECP_ECDH_SIZE_KEY; - } - - return ECP_ERR; -} - -static ssize_t vconn_handle_relay(ECPConnection *conn, ecp_seq_t seq, unsigned char mtype, unsigned char *msg, ssize_t size, ECP2Buffer *b) { - ECPContext *ctx = conn->sock->ctx; - ECPConnection *conn_out = NULL; - ECPVConnIn *conn_v = (ECPVConnIn *)conn; - ssize_t rv; - - if (conn->out) return ECP_ERR; - if (conn->type != ECP_CTYPE_VCONN) return ECP_ERR; - if (b == NULL) return ECP_ERR; - - if (size < 0) return size; - if (size < ECP_MIN_PKT) return ECP_ERR_MIN_PKT; - -#ifdef ECP_WITH_PTHREAD - pthread_mutex_lock(&key_perma_mutex); -#endif -#ifdef ECP_WITH_HTABLE - conn_out = ctx->ht.init ? ctx->ht.search(key_perma_table, conn_v->key_out) : NULL; -#endif - if (conn_out) { -#ifdef ECP_WITH_PTHREAD - pthread_mutex_lock(&conn_out->mutex); -#endif - conn_out->refcount++; -#ifdef ECP_WITH_PTHREAD - pthread_mutex_unlock(&conn_out->mutex); -#endif - } -#ifdef ECP_WITH_PTHREAD - pthread_mutex_unlock(&key_perma_mutex); -#endif - - if (conn_out == NULL) return ECP_ERR; - - ECPBuffer payload; - payload.buffer = msg - ECP_SIZE_PLD_HDR - 1; - payload.size = b->payload->size - (payload.buffer - b->payload->buffer); - - ecp_pld_set_type(payload.buffer, ECP_MTYPE_EXEC); - rv = ecp_pld_send(conn_out, b->packet, &payload, ECP_SIZE_PLD_HDR+1+size); - -#ifdef ECP_WITH_PTHREAD - pthread_mutex_lock(&conn_out->mutex); -#endif - conn_out->refcount--; -#ifdef ECP_WITH_PTHREAD - pthread_mutex_unlock(&conn_out->mutex); -#endif - - if (rv < 0) return rv; - return size; -} - -static int vlink_insert(ECPConnection *conn) { - int rv = ECP_OK; - ECPContext *ctx = conn->sock->ctx; - -#ifdef ECP_WITH_PTHREAD - pthread_mutex_lock(&key_perma_mutex); -#endif -#ifdef ECP_WITH_HTABLE - rv = ctx->ht.init ? ctx->ht.insert(key_perma_table, ctx->cr.dh_pub_get_buf(&conn->node.public), conn) : ECP_OK; -#endif -#ifdef ECP_WITH_PTHREAD - pthread_mutex_unlock(&key_perma_mutex); -#endif - - return rv; -} - -static void vlink_remove(ECPConnection *conn) { - ECPContext *ctx = conn->sock->ctx; - -#ifdef ECP_WITH_PTHREAD - pthread_mutex_lock(&key_perma_mutex); -#endif -#ifdef ECP_WITH_HTABLE - if (ctx->ht.init) ctx->ht.remove(key_perma_table, ctx->cr.dh_pub_get_buf(&conn->node.public)); -#endif -#ifdef ECP_WITH_PTHREAD - pthread_mutex_unlock(&key_perma_mutex); -#endif -} - -static int vlink_create(ECPConnection *conn, unsigned char *payload, size_t size) { - ECPContext *ctx = conn->sock->ctx; - - if (conn->out) return ECP_ERR; - if (conn->type != ECP_CTYPE_VLINK) return ECP_ERR; - - // XXX should verify perma_key - if (size < ECP_ECDH_SIZE_KEY) return ECP_ERR; - ctx->cr.dh_pub_from_buf(&conn->node.public, payload); - - return vlink_insert(conn); -} - -static void vlink_destroy(ECPConnection *conn) { - ECPContext *ctx = conn->sock->ctx; - - if (conn->out) return; - if (conn->type != ECP_CTYPE_VLINK) return; - - vlink_remove(conn); -} - -static ssize_t _vlink_send_open(ECPConnection *conn, ECPTimerItem *ti) { - ECPSocket *sock = conn->sock; - ECPContext *ctx = sock->ctx; - - ECPBuffer packet; - ECPBuffer payload; - unsigned char pkt_buf[ECP_SIZE_PKT_BUF(ECP_ECDH_SIZE_KEY+1, ECP_MTYPE_OPEN_REQ, conn)]; - unsigned char pld_buf[ECP_SIZE_PLD_BUF(ECP_ECDH_SIZE_KEY+1, ECP_MTYPE_OPEN_REQ, conn)]; - unsigned char *buf = ecp_pld_get_buf(pld_buf, ECP_MTYPE_OPEN_REQ); - int rv = ECP_OK; - - packet.buffer = pkt_buf; - packet.size = ECP_SIZE_PKT_BUF(ECP_ECDH_SIZE_KEY+1, ECP_MTYPE_OPEN_REQ, conn); - payload.buffer = pld_buf; - payload.size = ECP_SIZE_PLD_BUF(ECP_ECDH_SIZE_KEY+1, ECP_MTYPE_OPEN_REQ, conn); - - // XXX server should verify perma_key - ecp_pld_set_type(pld_buf, ECP_MTYPE_OPEN_REQ); - buf[0] = conn->type; - memcpy(buf+1, ctx->cr.dh_pub_get_buf(&sock->key_perma.public), ECP_ECDH_SIZE_KEY); - - return ecp_pld_send_wtimer(conn, &packet, &payload, ECP_SIZE_PLD(ECP_ECDH_SIZE_KEY+1, ECP_MTYPE_OPEN_REQ), ti); -} - -static ssize_t vlink_open(ECPConnection *conn) { - return ecp_timer_send(conn, _vlink_send_open, ECP_MTYPE_OPEN_REP, 3, 500); -} - -static void vlink_close(ECPConnection *conn) { - vlink_remove(conn); -} - -static ssize_t vlink_handle_open(ECPConnection *conn, ecp_seq_t seq, unsigned char mtype, unsigned char *msg, ssize_t size, ECP2Buffer *b) { - ssize_t rv; - int is_open; - - if (conn->type != ECP_CTYPE_VLINK) return ECP_ERR; - - if (size < 0) return size; - -#ifdef ECP_WITH_PTHREAD - pthread_mutex_lock(&conn->mutex); -#endif - is_open = ecp_conn_is_open(conn); -#ifdef ECP_WITH_PTHREAD - pthread_mutex_unlock(&conn->mutex); -#endif - - rv = ecp_conn_handle_open(conn, seq, mtype, msg, size, b); - if (rv < 0) return rv; - - if (mtype & ECP_MTYPE_FLAG_REP) { - if (!conn->out) return ECP_ERR; - if (!is_open) { - int rv = vlink_insert(conn); - if (rv) return rv; - } - return rv; - } else { - if (conn->out) return ECP_ERR; - if (size < rv+ECP_ECDH_SIZE_KEY) return ECP_ERR; - - msg += rv; - - // XXX should verify perma_key - return rv+ECP_ECDH_SIZE_KEY; - } - - return ECP_ERR; -} - -static ssize_t vlink_handle_relay(ECPConnection *conn, ecp_seq_t seq, unsigned char mtype, unsigned char *msg, ssize_t size, ECP2Buffer *b) { - ECPContext *ctx = conn->sock->ctx; - ssize_t rv; - - if (conn->type != ECP_CTYPE_VLINK) return ECP_ERR; - if (b == NULL) return ECP_ERR; - - if (size < 0) return size; - if (size < ECP_MIN_PKT) return ECP_ERR_MIN_PKT; - -#ifdef ECP_WITH_PTHREAD - pthread_mutex_lock(&key_next_mutex); -#endif -#ifdef ECP_WITH_HTABLE - conn = ctx->ht.init ? ctx->ht.search(key_next_table, msg+ECP_SIZE_PROTO+1) : NULL; -#endif - if (conn) { -#ifdef ECP_WITH_PTHREAD - pthread_mutex_lock(&conn->mutex); -#endif - conn->refcount++; -#ifdef ECP_WITH_PTHREAD - pthread_mutex_unlock(&conn->mutex); -#endif - } -#ifdef ECP_WITH_PTHREAD - pthread_mutex_unlock(&key_next_mutex); -#endif - - if (conn == NULL) return ECP_ERR; - - ECPBuffer payload; - payload.buffer = msg - ECP_SIZE_PLD_HDR - 1; - payload.size = b->payload->size - (payload.buffer - b->payload->buffer); - - ecp_pld_set_type(payload.buffer, ECP_MTYPE_EXEC); - rv = ecp_pld_send(conn, b->packet, &payload, ECP_SIZE_PLD_HDR+1+size); - -#ifdef ECP_WITH_PTHREAD - pthread_mutex_lock(&conn->mutex); -#endif - conn->refcount--; -#ifdef ECP_WITH_PTHREAD - pthread_mutex_unlock(&conn->mutex); -#endif - - if (rv < 0) return rv; - return size; -} - -static ssize_t vconn_set_msg(ECPConnection *conn, ECPBuffer *payload, unsigned char mtype) { - if (conn->out && (conn->type == ECP_CTYPE_VCONN) && ((mtype == ECP_MTYPE_OPEN_REQ) || (mtype == ECP_MTYPE_KGET_REQ))) { - ECPVConnection *conn_v = (ECPVConnection *)conn; - ECPContext *ctx = conn->sock->ctx; - ECPConnection *conn_next = conn_v->next; - unsigned char *buf = NULL; - int rv; - - if (payload->size < ECP_SIZE_PLD_HDR + 3 + 2 * ECP_ECDH_SIZE_KEY) return ECP_ERR; - if (conn_next == NULL) return ECP_ERR; - - ecp_pld_set_type(payload->buffer, ECP_MTYPE_OPEN_REQ); - buf = ecp_pld_get_buf(payload->buffer, 0); - - buf[0] = ECP_CTYPE_VCONN; - rv = ecp_conn_dhkey_get_curr(conn_next, NULL, buf+1); - if (rv) return rv; - - memcpy(buf+1+ECP_ECDH_SIZE_KEY, ctx->cr.dh_pub_get_buf(&conn_next->node.public), ECP_ECDH_SIZE_KEY); - buf[1+2*ECP_ECDH_SIZE_KEY] = ECP_MTYPE_RELAY; - - return ECP_SIZE_PLD_HDR + 3 + 2 * ECP_ECDH_SIZE_KEY; - } else { - if (payload->size < ECP_SIZE_PLD_HDR + 1) return ECP_ERR; - - ecp_pld_set_type(payload->buffer, ECP_MTYPE_RELAY); - - return ECP_SIZE_PLD_HDR + 1; - } - -} - -/* Memory limited version: */ -static ssize_t vconn_pack(ECPConnection *conn, ECPBuffer *packet, unsigned char s_idx, unsigned char c_idx, ECPBuffer *payload, size_t pld_size, ECPSeqItem *si, ECPNetAddr *addr) { - ECPContext *ctx = conn->sock->ctx; - - if (conn->parent) { - unsigned char mtype = ecp_pld_get_type(payload->buffer); - ssize_t rv, hdr_size = vconn_set_msg(conn->parent, packet, mtype); - if (hdr_size < 0) return hdr_size; - - rv = ecp_conn_pack(conn, packet->buffer+hdr_size, packet->size-hdr_size, s_idx, c_idx, payload->buffer, pld_size, si, NULL); - if (rv < 0) return rv; - - if (payload->size < rv+hdr_size) return ECP_ERR; - memcpy(payload->buffer, packet->buffer, rv+hdr_size); - - return vconn_pack(conn->parent, packet, ECP_ECDH_IDX_INV, ECP_ECDH_IDX_INV, payload, rv+hdr_size, NULL, addr); - } else { - return ecp_conn_pack(conn, packet->buffer, packet->size, s_idx, c_idx, payload->buffer, pld_size, si, addr); - } -} - -static ssize_t vconn_pack_raw(ECPSocket *sock, ECPConnection *parent, ECPBuffer *packet, unsigned char s_idx, unsigned char c_idx, ecp_dh_public_t *public, ecp_aead_key_t *shsec, unsigned char *nonce, ecp_seq_t seq, ECPBuffer *payload, size_t pld_size, ECPNetAddr *addr) { - ECPContext *ctx = sock->ctx; - - if (parent) { - unsigned char mtype = ecp_pld_get_type(payload->buffer); - ssize_t rv, hdr_size = vconn_set_msg(parent, packet, mtype); - if (hdr_size < 0) return hdr_size; - - rv = ecp_pack(ctx, packet->buffer+hdr_size, packet->size-hdr_size, s_idx, c_idx, public, shsec, nonce, seq, payload->buffer, pld_size); - if (rv < 0) return rv; - - if (payload->size < rv+hdr_size) return ECP_ERR; - memcpy(payload->buffer, packet->buffer, rv+hdr_size); - - return vconn_pack(parent, packet, ECP_ECDH_IDX_INV, ECP_ECDH_IDX_INV, payload, rv+hdr_size, NULL, addr); - } else { - return ecp_pack(ctx, packet->buffer, packet->size, s_idx, c_idx, public, shsec, nonce, seq, payload->buffer, pld_size); - } -} - -/* Non memory limited version: */ -/* -static ssize_t vconn_pack(ECPConnection *conn, ECPBuffer *packet, unsigned char s_idx, unsigned char c_idx, ECPBuffer *payload, size_t pld_size, ECPSeqItem *si, ECPNetAddr *addr) { - ECPContext *ctx = conn->sock->ctx; - - if (conn->parent) { - ECPBuffer payload_; - unsigned char pld_buf[ECP_MAX_PLD]; - - payload_.buffer = pld_buf; - payload_.size = ECP_MAX_PLD; - - unsigned char mtype = ecp_pld_get_type(payload->buffer); - ssize_t rv, hdr_size = vconn_set_msg(conn->parent, &payload_, mtype); - if (hdr_size < 0) return hdr_size; - - rv = ecp_conn_pack(conn, payload_.buffer+hdr_size, payload_.size-hdr_size, s_idx, c_idx, payload->buffer, pld_size, si, NULL); - if (rv < 0) return rv; - - return vconn_pack(conn->parent, packet, ECP_ECDH_IDX_INV, ECP_ECDH_IDX_INV, &payload_, rv+hdr_size, NULL, addr); - } else { - return ecp_conn_pack(conn, packet->buffer, packet->size, s_idx, c_idx, payload->buffer, pld_size, si, addr); - } -} - -static ssize_t vconn_pack_raw(ECPSocket *sock, ECPConnection *parent, ECPBuffer *packet, unsigned char s_idx, unsigned char c_idx, ecp_dh_public_t *public, ecp_aead_key_t *shsec, unsigned char *nonce, ecp_seq_t seq, ECPBuffer *payload, size_t pld_size, ECPNetAddr *addr) { - ECPContext *ctx = sock->ctx; - - if (parent) { - ECPBuffer payload_; - unsigned char pld_buf[ECP_MAX_PLD]; - - payload_.buffer = pld_buf; - payload_.size = ECP_MAX_PLD; - - unsigned char mtype = ecp_pld_get_type(payload->buffer); - ssize_t rv, hdr_size = vconn_set_msg(parent, &payload_, mtype); - if (hdr_size < 0) return hdr_size; - - rv = ecp_pack(ctx, payload_.buffer+hdr_size, payload_.size-hdr_size, s_idx, c_idx, public, shsec, nonce, seq, payload->buffer, pld_size); - if (rv < 0) return rv; - - return vconn_pack(parent, packet, ECP_ECDH_IDX_INV, ECP_ECDH_IDX_INV, &payload_, rv+hdr_size, NULL, addr); - } else { - return ecp_pack(ctx, packet->buffer, packet->size, s_idx, c_idx, public, shsec, nonce, seq, payload->buffer, pld_size); - } -} -*/ - -int ecp_ctx_vconn_init(ECPContext *ctx) { - int rv; - - rv = ecp_conn_handler_init(&handler_vc); - if (rv) return rv; - - handler_vc.conn_create = vconn_create; - handler_vc.conn_destroy = vconn_destroy; - handler_vc.conn_open = vconn_open; - handler_vc.msg[ECP_MTYPE_OPEN] = vconn_handle_open; - handler_vc.msg[ECP_MTYPE_EXEC] = ecp_conn_handle_exec; - handler_vc.msg[ECP_MTYPE_RELAY] = vconn_handle_relay; - ctx->handler[ECP_CTYPE_VCONN] = &handler_vc; - - rv = ecp_conn_handler_init(&handler_vl); - if (rv) return rv; - - handler_vl.conn_create = vlink_create; - handler_vl.conn_destroy = vlink_destroy; - handler_vl.conn_open = vlink_open; - handler_vl.conn_close = vlink_close; - handler_vl.msg[ECP_MTYPE_OPEN] = vlink_handle_open; - handler_vl.msg[ECP_MTYPE_EXEC] = ecp_conn_handle_exec; - handler_vl.msg[ECP_MTYPE_RELAY] = vlink_handle_relay; - ctx->handler[ECP_CTYPE_VLINK] = &handler_vl; - - ctx->pack = vconn_pack; - ctx->pack_raw = vconn_pack_raw; - -#ifdef ECP_WITH_PTHREAD - rv = pthread_mutex_init(&key_perma_mutex, NULL); - if (!rv) pthread_mutex_init(&key_next_mutex, NULL); - if (rv) return ECP_ERR; -#endif - -#ifdef ECP_WITH_HTABLE - if (ctx->ht.init) { - key_perma_table = ctx->ht.create(ctx); - key_next_table = ctx->ht.create(ctx); - if ((key_perma_table == NULL) || (key_next_table == NULL)) return ECP_ERR; - } -#endif - - return ECP_OK; -} - -int ecp_vconn_init(ECPConnection *conn, ECPNode *conn_node, ECPVConnection vconn[], ECPNode vconn_node[], int size) { - ECPSocket *sock = conn->sock; - int i, rv; - - rv = ecp_conn_init(conn, conn_node); - if (rv) return rv; - - conn->parent = (ECPConnection *)&vconn[size-1]; - conn->pcount = size; - for (i=0; i