diff options
Diffstat (limited to 'src/irmd/reg')
| -rw-r--r-- | src/irmd/reg/flow.c | 4 | ||||
| -rw-r--r-- | src/irmd/reg/flow.h | 11 | ||||
| -rw-r--r-- | src/irmd/reg/reg.c | 189 | ||||
| -rw-r--r-- | src/irmd/reg/reg.h | 34 |
4 files changed, 238 insertions, 0 deletions
diff --git a/src/irmd/reg/flow.c b/src/irmd/reg/flow.c index 5c709dea..ccb2562d 100644 --- a/src/irmd/reg/flow.c +++ b/src/irmd/reg/flow.c @@ -24,6 +24,7 @@ #define OUROBOROS_PREFIX "reg/flow" +#include <ouroboros/crypt.h> #include <ouroboros/logs.h> #include "flow.h" @@ -32,6 +33,7 @@ #include <errno.h> #include <stdbool.h> #include <stdlib.h> +#include <string.h> struct reg_flow * reg_flow_create(const struct flow_info * info) { @@ -79,6 +81,8 @@ void reg_flow_destroy(struct reg_flow * flow) { assert(flow != NULL); + crypt_secure_clear(flow->rk.pending_seed, SYMMKEYSZ); + switch(flow->info.state) { case FLOW_ACCEPT_PENDING: clrbuf(flow->req_data); diff --git a/src/irmd/reg/flow.h b/src/irmd/reg/flow.h index 9a4046d3..15fc7b8f 100644 --- a/src/irmd/reg/flow.h +++ b/src/irmd/reg/flow.h @@ -49,6 +49,17 @@ struct reg_flow { bool direct; + /* Tier-2 re-key state (encrypted flows only) */ + struct { + bool encrypted; /* flow carries a cipher */ + uint8_t epoch; /* last epoch installed by app */ + bool initiator; /* OAP initiator (role 0) */ + bool in_flight; /* a re-key is in progress */ + uint8_t pending_seed[SYMMKEYSZ]; + uint8_t pending_epoch; + bool has_pending; /* new seed awaits app pull */ + } rk; + struct ssm_rbuff * n_rb; struct ssm_rbuff * n_1_rb; }; diff --git a/src/irmd/reg/reg.c b/src/irmd/reg/reg.c index 365064e5..70baf64e 100644 --- a/src/irmd/reg/reg.c +++ b/src/irmd/reg/reg.c @@ -25,6 +25,7 @@ The IPC Resource Manager - Registry #define OUROBOROS_PREFIX "reg" #include <ouroboros/bitmap.h> +#include <ouroboros/crypt.h> #include <ouroboros/errno.h> #include <ouroboros/list.h> #include <ouroboros/logs.h> @@ -2102,6 +2103,194 @@ bool reg_flow_is_direct(int flow_id) return ret; } +void reg_flow_set_rekey(int flow_id, + bool initiator) +{ + struct reg_flow * flow; + + pthread_mutex_lock(®.mtx); + + flow = __reg_get_flow(flow_id); + if (flow != NULL) { + flow->rk.encrypted = true; + flow->rk.initiator = initiator; + flow->rk.epoch = 0; + } + + pthread_mutex_unlock(®.mtx); +} + +int reg_flow_get_epoch(int flow_id) +{ + struct reg_flow * flow; + int epoch = -1; + + pthread_mutex_lock(®.mtx); + + flow = __reg_get_flow(flow_id); + if (flow != NULL && flow->rk.encrypted) + epoch = flow->rk.epoch; + + pthread_mutex_unlock(®.mtx); + + return epoch; +} + +bool reg_flow_rekey_pending(int flow_id) +{ + struct reg_flow * flow; + bool ret = false; + + pthread_mutex_lock(®.mtx); + + flow = __reg_get_flow(flow_id); + if (flow != NULL) + ret = flow->rk.has_pending; + + pthread_mutex_unlock(®.mtx); + + return ret; +} + +pid_t reg_flow_get_n_1_pid(int flow_id) +{ + struct reg_flow * flow; + pid_t pid = -1; + + pthread_mutex_lock(®.mtx); + + flow = __reg_get_flow(flow_id); + if (flow != NULL) + pid = flow->info.n_1_pid; + + pthread_mutex_unlock(®.mtx); + + return pid; +} + +int reg_flow_snapshot_rekey_due(struct rekey_info * snap, + int max) +{ + struct list_head * p; + int n = 0; + + pthread_mutex_lock(®.mtx); + + llist_for_each(p, ®.flows) { + struct reg_flow * f; + + if (n == max) + break; + + f = list_entry(p, struct reg_flow, next); + + if (f->info.state != FLOW_ALLOCATED || f->direct) + continue; + + if (!f->rk.encrypted || !f->rk.initiator) + continue; + + if (f->rk.in_flight || f->rk.has_pending) + continue; + + f->rk.in_flight = true; + + snap[n].flow_id = f->info.id; + snap[n].n_pid = f->info.n_pid; + snap[n].n_1_pid = f->info.n_1_pid; + snap[n].epoch = f->rk.epoch; + strcpy(snap[n].name, f->name); + ++n; + } + + pthread_mutex_unlock(®.mtx); + + return n; +} + +void reg_flow_clear_in_flight(int flow_id) +{ + struct reg_flow * flow; + + pthread_mutex_lock(®.mtx); + + flow = __reg_get_flow(flow_id); + if (flow != NULL) + flow->rk.in_flight = false; + + pthread_mutex_unlock(®.mtx); +} + +int reg_flow_store_pending(int flow_id, + const uint8_t * seed, + uint8_t epoch) +{ + struct reg_flow * flow; + int ret = -ENOENT; + + pthread_mutex_lock(®.mtx); + + flow = __reg_get_flow(flow_id); + if (flow != NULL) { + memcpy(flow->rk.pending_seed, seed, SYMMKEYSZ); + flow->rk.pending_epoch = epoch; + flow->rk.has_pending = true; + flow->rk.in_flight = false; + /* Doorbell raised only after the seed is parked. */ + if (flow->n_rb != NULL) + ssm_rbuff_set_bits(flow->n_rb, RB_REKEY); + ret = 0; + } + + pthread_mutex_unlock(®.mtx); + + return ret; +} + +bool reg_flow_take_pending(int flow_id, + uint8_t * seed, + uint8_t * epoch) +{ + struct reg_flow * flow; + bool ret = false; + + pthread_mutex_lock(®.mtx); + + flow = __reg_get_flow(flow_id); + if (flow != NULL && flow->rk.has_pending) { + memcpy(seed, flow->rk.pending_seed, SYMMKEYSZ); + *epoch = flow->rk.pending_epoch; + flow->rk.epoch = flow->rk.pending_epoch; /* app installed it */ + flow->rk.has_pending = false; + crypt_secure_clear(flow->rk.pending_seed, SYMMKEYSZ); + if (flow->n_rb != NULL) + ssm_rbuff_clr_bits(flow->n_rb, RB_REKEY); + ret = true; + } + + pthread_mutex_unlock(®.mtx); + + return ret; +} + +void reg_notify_flow(int flow_id, + int event) +{ + struct reg_flow * flow; + struct reg_proc * proc; + + pthread_mutex_lock(®.mtx); + + flow = __reg_get_flow(flow_id); + if (flow != NULL) { + proc = __reg_get_proc(flow->info.n_pid); + if (proc != NULL) + ssm_flow_set_notify(proc->set, flow_id, event); + } + + pthread_mutex_unlock(®.mtx); +} + int reg_respond_flow_direct(int flow_id, buffer_t * pbuf) { diff --git a/src/irmd/reg/reg.h b/src/irmd/reg/reg.h index 6b576471..e0c64fed 100644 --- a/src/irmd/reg/reg.h +++ b/src/irmd/reg/reg.h @@ -163,6 +163,40 @@ int reg_wait_flow_direct(int flow_id, bool reg_flow_is_direct(int flow_id); +/* Per-flow snapshot for the re-key timer */ +struct rekey_info { + int flow_id; + pid_t n_pid; + pid_t n_1_pid; + char name[NAME_SIZE + 1]; + uint8_t epoch; +}; + +void reg_flow_set_rekey(int flow_id, + bool initiator); + +int reg_flow_get_epoch(int flow_id); + +bool reg_flow_rekey_pending(int flow_id); + +pid_t reg_flow_get_n_1_pid(int flow_id); + +int reg_flow_snapshot_rekey_due(struct rekey_info * snap, + int max); + +void reg_flow_clear_in_flight(int flow_id); + +int reg_flow_store_pending(int flow_id, + const uint8_t * seed, + uint8_t epoch); + +bool reg_flow_take_pending(int flow_id, + uint8_t * seed, + uint8_t * epoch); + +void reg_notify_flow(int flow_id, + int event); + void reg_dealloc_flow(struct flow_info * info); void reg_dealloc_flow_resp(struct flow_info * info); |
