diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/irmd/main.c | 219 | ||||
-rw-r--r-- | src/lib/crypt.c | 4 | ||||
-rw-r--r-- | src/lib/dev.c | 87 | ||||
-rw-r--r-- | src/lib/pb/irm.proto | 3 |
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; } |