summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/irmd/main.c219
-rw-r--r--src/lib/crypt.c4
-rw-r--r--src/lib/dev.c87
-rw-r--r--src/lib/pb/irm.proto3
4 files changed, 188 insertions, 125 deletions
diff --git a/src/irmd/main.c b/src/irmd/main.c
index 5e58052d..59c1c5ec 100644
--- a/src/irmd/main.c
+++ b/src/irmd/main.c
@@ -30,6 +30,7 @@
#define OUROBOROS_PREFIX "irmd"
+#include <ouroboros/crypt.h>
#include <ouroboros/hash.h>
#include <ouroboros/errno.h>
#include <ouroboros/sockets.h>
@@ -76,6 +77,7 @@
#define IPCP_HASH_LEN(p) hash_len((p)->dir_hash_algo)
#define BIND_TIMEOUT 10 /* ms */
#define DEALLOC_TIME 300 /* s */
+#define MSGBUFSZ 2048
#define registry_has_name(name) \
(registry_get_name(name) != NULL)
@@ -1349,6 +1351,14 @@ static int flow_accept(pid_t pid,
int flow_id;
int ret;
buffer_t tmp = {NULL, 0};
+ void * pkp; /* my public key pair */
+ ssize_t key_len;
+ uint8_t buf[MSGBUFSZ];
+ uint8_t * s = NULL;
+ int err;
+
+ /* piggyback of user data not yet implemented */
+ assert(data != NULL && data->len == 0 && data->data == NULL);
pthread_rwlock_wrlock(&irmd.reg_lock);
@@ -1379,8 +1389,26 @@ static int flow_accept(pid_t pid,
if (ret == -1)
return -EPIPE;
- if (irmd_get_state() != IRMD_RUNNING)
+ if (irmd_get_state() != IRMD_RUNNING) {
+ log_dbg("Terminating accept: IRMd shutting down.");
return -EIRMD;
+ }
+
+ s = malloc(SYMMKEYSZ);
+ if (s == NULL) {
+ log_err("Failed to malloc symmetric key.");
+ err = -ENOMEM;
+ goto fail_malloc_s;
+ }
+
+ key_len = crypt_dh_pkp_create(&pkp, buf);
+ if (key_len < 0) {
+ log_err("Failed to generate key pair.");
+ err = -ECRYPT;
+ goto fail_pkp;
+ }
+
+ log_dbg("Generated ephemeral keys for %d.", pid);
pthread_rwlock_wrlock(&irmd.reg_lock);
@@ -1388,7 +1416,8 @@ static int flow_accept(pid_t pid,
if (f == NULL) {
pthread_rwlock_unlock(&irmd.reg_lock);
log_warn("Port_id was not created yet.");
- return -EPERM;
+ err = -EPERM;
+ goto fail_rp;
}
pid_n = f->n_pid;
@@ -1405,7 +1434,8 @@ static int flow_accept(pid_t pid,
reg_flow_set_state(f, FLOW_NULL);
reg_flow_destroy(f);
log_dbg("Process gone while accepting flow.");
- return -EPERM;
+ err = -EPERM;
+ goto fail_rp;
}
pthread_mutex_lock(&rp->lock);
@@ -1423,7 +1453,8 @@ static int flow_accept(pid_t pid,
reg_flow_set_state(f, FLOW_NULL);
reg_flow_destroy(f);
log_err("Entry in wrong state.");
- return -EPERM;
+ err = -EPERM;
+ goto fail_rp;
}
registry_names_del_proc(pid);
@@ -1434,11 +1465,26 @@ static int flow_accept(pid_t pid,
f_out->qs = f->qs;
f_out->mpl = f->mpl;
- if (f->qs.cypher_s != 0) /* crypto requested, send pubkey */
- tmp = *data;
+ if (f->qs.cypher_s != 0) { /* crypto requested */
+ tmp.len = key_len; /* send this pubkey */
+ tmp.data = (uint8_t *) buf;
+
+ if (crypt_dh_derive(pkp, f->data.data, f->data.len, s) < 0) {
+ list_del(&f->next);
+ bmp_release(irmd.flow_ids, f->flow_id);
+ freebuf(f->data);
+ pthread_rwlock_unlock(&irmd.reg_lock);
+ clear_reg_flow(f);
+ reg_flow_set_state(f, FLOW_NULL);
+ reg_flow_destroy(f);
+ log_err("Failed to derive common secret for %d.",
+ flow_id);
+ err = -ECRYPT;
+ goto fail_rp;
+ }
+ }
- *data = f->data; /* pass owner */
- clrbuf (f->data);
+ freebuf(f->data);
pthread_rwlock_unlock(&irmd.reg_lock);
@@ -1450,14 +1496,29 @@ static int flow_accept(pid_t pid,
clear_reg_flow(f);
reg_flow_set_state(f, FLOW_NULL);
reg_flow_destroy(f);
- return -EPERM;
+ err = -EPERM;
+ goto fail_rp;
}
reg_flow_set_state(f, FLOW_ALLOCATED);
+ crypt_dh_pkp_destroy(pkp);
+
+ if (f_out->qs.cypher_s > 0) {
+ data->data = s;
+ data->len = SYMMKEYSZ;
+ }
+
log_info("Flow on flow_id %d allocated.", f->flow_id);
return 0;
+
+ fail_rp:
+ crypt_dh_pkp_destroy(pkp);
+ fail_pkp:
+ free(s);
+ fail_malloc_s:
+ return err;
}
static int flow_join(pid_t pid,
@@ -1466,11 +1527,11 @@ static int flow_join(pid_t pid,
struct timespec * dl,
struct reg_flow * f_out)
{
- struct reg_flow * f;
+ struct reg_flow * f;
struct reg_ipcp * ipcp;
- int flow_id;
- int state;
- uint8_t * hash;
+ int flow_id;
+ int state;
+ uint8_t * hash;
log_info("Allocating flow for %d to %s.", pid, dst);
@@ -1563,13 +1624,44 @@ static int flow_alloc(pid_t pid,
int flow_id;
int state;
uint8_t * hash;
+ ssize_t key_len;
+ void * pkp; /* my public key pair */
+ buffer_t tmp; /* buffer for public key */
+ uint8_t buf[MSGBUFSZ];
+ uint8_t * s = NULL;
+ int err;
log_info("Allocating flow for %d to %s.", pid, dst);
+ /* piggyback of user data not yet implemented */
+ assert(data != NULL && data->len == 0 && data->data == NULL);
+
+ if (qs.cypher_s > 0) {
+ s = malloc(SYMMKEYSZ);
+ if (s == NULL) {
+ log_err("Failed to malloc symmetric key.");
+ err = -ENOMEM;
+ goto fail_malloc_s;
+ }
+
+ key_len = crypt_dh_pkp_create(&pkp, buf);
+ if (key_len < 0) {
+ log_err("Failed to generate key pair.");
+ err = -ECRYPT;
+ goto fail_pkp;
+ }
+
+ log_dbg("Generated ephemeral keys for %d.", pid);
+
+ tmp.data = (uint8_t *) buf;
+ tmp.len = (size_t) key_len;
+ }
+
ipcp = registry_get_ipcp_by_dst_name(dst, pid);
if (ipcp == NULL) {
log_info("Destination %s unreachable.", dst);
- return -1;
+ err = -ENOTALLOC;
+ goto fail_ipcp;
}
pthread_rwlock_wrlock(&irmd.reg_lock);
@@ -1578,15 +1670,16 @@ static int flow_alloc(pid_t pid,
if (!bmp_is_id_valid(irmd.flow_ids, flow_id)) {
pthread_rwlock_unlock(&irmd.reg_lock);
log_err("Could not allocate flow_id.");
- return -EBADF;
+ err = -EBADF;
+ goto fail_ipcp;
}
f = reg_flow_create(pid, ipcp->pid, flow_id, qs);
if (f == NULL) {
- bmp_release(irmd.flow_ids, flow_id);
pthread_rwlock_unlock(&irmd.reg_lock);
log_err("Could not allocate flow_id.");
- return -ENOMEM;
+ err = -ENOMEM;
+ goto fail_flow;
}
list_add(&f->next, &irmd.flows);
@@ -1596,32 +1689,34 @@ static int flow_alloc(pid_t pid,
assert(reg_flow_get_state(f) == FLOW_ALLOC_PENDING);
hash = malloc(IPCP_HASH_LEN(ipcp));
- if (hash == NULL)
- /* sanitizer cleans this */
- return -ENOMEM;
+ if (hash == NULL) {
+ /* sanitizer cleans regflow */
+ err = -ENOMEM;
+ goto fail_flow;
+ }
str_hash(ipcp->dir_hash_algo, hash, dst);
if (ipcp_flow_alloc(ipcp->pid, flow_id, pid, hash,
- IPCP_HASH_LEN(ipcp), qs, *data)) {
+ IPCP_HASH_LEN(ipcp), qs, tmp)) {
reg_flow_set_state(f, FLOW_NULL);
/* sanitizer cleans this */
log_warn("Flow_allocation %d failed.", flow_id);
- free(hash);
- return -EAGAIN;
+ err = -ENOTALLOC;
+ goto fail_alloc;
}
- free(hash);
-
state = reg_flow_wait_state(f, FLOW_ALLOCATED, dl);
if (state != FLOW_ALLOCATED) {
if (state == -ETIMEDOUT) {
log_err("Flow allocation timed out");
- return -ETIMEDOUT;
+ err = -ETIMEDOUT;
+ goto fail_alloc;
}
log_warn("Pending flow to %s torn down.", dst);
- return -EPIPE;
+ err = -EPIPE;
+ goto fail_alloc;
}
pthread_rwlock_wrlock(&irmd.reg_lock);
@@ -1632,14 +1727,41 @@ static int flow_alloc(pid_t pid,
f_out->n_pid = f->n_pid;
f_out->n_1_pid = f->n_1_pid;
f_out->mpl = f->mpl;
- *data = f->data; /* pass owner */
- clrbuf(f->data);
+ if (qs.cypher_s > 0 &&
+ crypt_dh_derive(pkp, f->data.data, f->data.len, s) < 0) {
+ freebuf(f->data);
+ pthread_rwlock_unlock(&irmd.reg_lock);
+ log_err("Failed to derive common secret for %d.", flow_id);
+ err = -ECRYPT;
+ goto fail_alloc;
+ }
+
+ freebuf(f->data);
pthread_rwlock_unlock(&irmd.reg_lock);
+ free(hash);
+ crypt_dh_pkp_destroy(pkp);
+
+ data->data = s;
+ data->len = SYMMKEYSZ;
+
log_info("Flow on flow_id %d allocated.", flow_id);
return 0;
+
+ fail_alloc:
+ free(hash);
+ fail_flow:
+ bmp_release(irmd.flow_ids, flow_id);
+ fail_ipcp:
+ if (qs.cypher_s > 0)
+ crypt_dh_pkp_destroy(pkp);
+ fail_pkp:
+ free(s);
+ fail_malloc_s:
+ return err;
+
}
static int flow_dealloc(pid_t pid,
@@ -2178,34 +2300,35 @@ static irm_msg_t * do_command_msg(irm_msg_t * msg)
if (res == 0) {
qosspec_msg_t * qs_msg;
qs_msg = qos_spec_s_to_msg(&f.qs);
- ret_msg->has_flow_id = true;
- ret_msg->flow_id = f.flow_id;
- ret_msg->has_pid = true;
- ret_msg->pid = f.n_1_pid;
- ret_msg->qosspec = qs_msg;
- ret_msg->has_mpl = true;
- ret_msg->mpl = f.mpl;
- ret_msg->has_pk = true;
- ret_msg->pk.data = data.data;
- ret_msg->pk.len = data.len;
+ ret_msg->has_flow_id = true;
+ ret_msg->flow_id = f.flow_id;
+ ret_msg->has_pid = true;
+ ret_msg->pid = f.n_1_pid;
+ ret_msg->qosspec = qs_msg;
+ ret_msg->has_mpl = true;
+ ret_msg->mpl = f.mpl;
+ ret_msg->has_symmkey = data.len != 0;
+ ret_msg->symmkey.data = data.data;
+ ret_msg->symmkey.len = data.len;
}
break;
case IRM_MSG_CODE__IRM_FLOW_ALLOC:
data.len = msg->pk.len;
data.data = msg->pk.data;
+ msg->has_pk = false;
qs = qos_spec_msg_to_s(msg->qosspec);
assert(data.len > 0 ? data.data != NULL : data.data == NULL);
res = flow_alloc(msg->pid, msg->dst, qs, dl, &f, &data);
if (res == 0) {
- ret_msg->has_flow_id = true;
- ret_msg->flow_id = f.flow_id;
- ret_msg->has_pid = true;
- ret_msg->pid = f.n_1_pid;
- ret_msg->has_mpl = true;
- ret_msg->mpl = f.mpl;
- ret_msg->has_pk = true;
- ret_msg->pk.data = data.data;
- ret_msg->pk.len = data.len;
+ ret_msg->has_flow_id = true;
+ ret_msg->flow_id = f.flow_id;
+ ret_msg->has_pid = true;
+ ret_msg->pid = f.n_1_pid;
+ ret_msg->has_mpl = true;
+ ret_msg->mpl = f.mpl;
+ ret_msg->has_symmkey = data.len != 0;
+ ret_msg->symmkey.data = data.data;
+ ret_msg->symmkey.len = data.len;
}
break;
case IRM_MSG_CODE__IRM_FLOW_JOIN:
diff --git a/src/lib/crypt.c b/src/lib/crypt.c
index c5d6101a..2f0404a2 100644
--- a/src/lib/crypt.c
+++ b/src/lib/crypt.c
@@ -154,8 +154,8 @@ static int __openssl_ecdh_gen_key(void ** kp)
static ssize_t openssl_ecdh_pkp_create(void ** pkp,
uint8_t * pk)
{
- uint8_t * pos;
- ssize_t len;
+ uint8_t * pos;
+ ssize_t len;
assert(pkp != NULL);
assert(*pkp == NULL);
diff --git a/src/lib/dev.c b/src/lib/dev.c
index 3d45f016..d1f827f3 100644
--- a/src/lib/dev.c
+++ b/src/lib/dev.c
@@ -759,13 +759,8 @@ int flow_accept(qosspec_t * qs,
irm_msg_t msg = IRM_MSG__INIT;
irm_msg_t * recv_msg;
int fd;
- void * pkp; /* public key pair */
- uint8_t s[SYMMKEYSZ]; /* secret key for flow */
- uint8_t buf[MSGBUFSZ];
int err = -EIRMD;
- ssize_t key_len;
-
- memset(s, 0, SYMMKEYSZ);
+ uint8_t * symmkey;
msg.code = IRM_MSG_CODE__IRM_FLOW_ACCEPT;
msg.has_pid = true;
@@ -778,23 +773,7 @@ int flow_accept(qosspec_t * qs,
msg.timeo_nsec = timeo->tv_nsec;
}
- key_len = crypt_dh_pkp_create(&pkp, buf);
- if (key_len < 0) {
- err = -ECRYPT;
- goto fail_crypt_pkp;
- }
- if (key_len > 0) {
- msg.has_pk = true;
- msg.pk.data = buf;
- msg.pk.len = (uint32_t) key_len;
- }
-
- pthread_cleanup_push(crypt_dh_pkp_destroy, pkp);
-
recv_msg = send_recv_irm_msg(&msg);
-
- pthread_cleanup_pop(false);
-
if (recv_msg == NULL)
goto fail_recv;
@@ -810,17 +789,11 @@ int flow_accept(qosspec_t * qs,
!recv_msg->has_mpl || recv_msg->qosspec == NULL)
goto fail_msg;
- if (recv_msg->pk.len != 0 &&
- crypt_dh_derive(pkp, recv_msg->pk.data,
- recv_msg->pk.len, s) < 0) {
- err = -ECRYPT;
- goto fail_msg;
- }
-
- crypt_dh_pkp_destroy(pkp);
+ symmkey = recv_msg->has_symmkey ? recv_msg->symmkey.data : NULL;
fd = flow_init(recv_msg->flow_id, recv_msg->pid,
- qos_spec_msg_to_s(recv_msg->qosspec), s,
+ qos_spec_msg_to_s(recv_msg->qosspec),
+ symmkey,
recv_msg->mpl);
irm_msg__free_unpacked(recv_msg, NULL);
@@ -828,7 +801,6 @@ int flow_accept(qosspec_t * qs,
if (fd < 0)
return fd;
-
pthread_rwlock_rdlock(&ai.lock);
if (qs != NULL)
@@ -841,8 +813,6 @@ int flow_accept(qosspec_t * qs,
fail_msg:
irm_msg__free_unpacked(recv_msg, NULL);
fail_recv:
- crypt_dh_pkp_destroy(pkp);
- fail_crypt_pkp:
return err;
}
@@ -850,15 +820,10 @@ int flow_alloc(const char * dst,
qosspec_t * qs,
const struct timespec * timeo)
{
- irm_msg_t msg = IRM_MSG__INIT;
- irm_msg_t * recv_msg;
- int fd;
- void * pkp = NULL; /* public key pair */
- uint8_t s[SYMMKEYSZ]; /* secret key for flow */
- uint8_t buf[MSGBUFSZ];
- int err = -EIRMD;
-
- memset(s, 0, SYMMKEYSZ);
+ irm_msg_t msg = IRM_MSG__INIT;
+ irm_msg_t * recv_msg;
+ int fd;
+ int err = -EIRMD;
#ifdef QOS_DISABLE_CRC
if (qs != NULL)
@@ -877,25 +842,10 @@ int flow_alloc(const char * dst,
msg.timeo_nsec = timeo->tv_nsec;
}
- if (qs != NULL && qs->cypher_s != 0) {
- ssize_t key_len;
-
- key_len = crypt_dh_pkp_create(&pkp, buf);
- if (key_len < 0) {
- err = -ECRYPT;
- goto fail_crypt_pkp;
- }
-
- msg.has_pk = true;
- msg.pk.data = buf;
- msg.pk.len = (uint32_t) key_len;
- }
-
recv_msg = send_recv_irm_msg(&msg);
qosspec_msg__free_unpacked(msg.qosspec, NULL);
-
if (recv_msg == NULL)
- goto fail_send;
+ goto fail_send_recv;
if (!recv_msg->has_result)
goto fail_result;
@@ -909,19 +859,10 @@ int flow_alloc(const char * dst,
!recv_msg->has_mpl)
goto fail_result;
- if (qs != NULL && qs->cypher_s != 0) {
- if (!recv_msg->has_pk || recv_msg->pk.len == 0) {
- err = -ECRYPT;
- goto fail_result;
- }
-
- if (crypt_dh_derive(pkp, recv_msg->pk.data,
- recv_msg->pk.len, s) < 0) {
+ if ((qs != NULL && qs->cypher_s != 0) &&
+ (!recv_msg->has_symmkey || recv_msg->symmkey.len != SYMMKEYSZ)) {
err = -ECRYPT;
goto fail_result;
- }
-
- crypt_dh_pkp_destroy(pkp);
}
/* TODO: Make sure qosspec is set in msg */
@@ -929,7 +870,7 @@ int flow_alloc(const char * dst,
*qs = qos_spec_msg_to_s(recv_msg->qosspec);
fd = flow_init(recv_msg->flow_id, recv_msg->pid,
- qs == NULL ? qos_raw : *qs, s,
+ qs == NULL ? qos_raw : *qs, recv_msg->symmkey.data,
recv_msg->mpl);
irm_msg__free_unpacked(recv_msg, NULL);
@@ -938,9 +879,7 @@ int flow_alloc(const char * dst,
fail_result:
irm_msg__free_unpacked(recv_msg, NULL);
- fail_send:
- crypt_dh_pkp_destroy(pkp);
- fail_crypt_pkp:
+ fail_send_recv:
return err;
}
diff --git a/src/lib/pb/irm.proto b/src/lib/pb/irm.proto
index 94db28a4..366e462c 100644
--- a/src/lib/pb/irm.proto
+++ b/src/lib/pb/irm.proto
@@ -92,5 +92,6 @@ message irm_msg {
optional sint32 mpl = 19;
optional string comp = 20;
optional bytes pk = 21; /* piggyback */
- optional sint32 result = 22;
+ optional bytes symmkey = 22;
+ optional sint32 result = 23;
}