summaryrefslogtreecommitdiff
path: root/src/irmd
diff options
context:
space:
mode:
Diffstat (limited to 'src/irmd')
-rw-r--r--src/irmd/configfile.c7
-rw-r--r--src/irmd/oap/cli.c44
-rw-r--r--src/irmd/oap/hdr.c6
-rw-r--r--src/irmd/oap/srv.c6
-rw-r--r--src/irmd/oap/tests/oap_test.c84
-rw-r--r--src/irmd/reg/name.c2
-rw-r--r--src/irmd/reg/proc.c3
-rw-r--r--src/irmd/reg/prog.c3
8 files changed, 128 insertions, 27 deletions
diff --git a/src/irmd/configfile.c b/src/irmd/configfile.c
index 35cf4292..e2e1e554 100644
--- a/src/irmd/configfile.c
+++ b/src/irmd/configfile.c
@@ -457,7 +457,7 @@ static int toml_congestion(toml_table_t * table,
if (congestion.ok) {
if (strcmp(congestion.u.s, "none") == 0)
conf->cong_avoid = CA_NONE;
- else if (strcmp(congestion.u.s, "lfa") == 0)
+ else if (strcmp(congestion.u.s, "mb-ecn") == 0)
conf->cong_avoid = CA_MB_ECN;
else
conf->cong_avoid = CA_INVALID;
@@ -477,6 +477,7 @@ static int toml_dt(toml_table_t * table,
toml_datum_t addr;
toml_datum_t eid;
toml_datum_t ttl;
+ toml_datum_t max_rtt;
addr = toml_int_in(table, "addr_size");
if (addr.ok)
@@ -490,6 +491,10 @@ static int toml_dt(toml_table_t * table,
if (ttl.ok)
conf->max_ttl = ttl.u.i;
+ max_rtt = toml_int_in(table, "max_rtt");
+ if (max_rtt.ok)
+ conf->max_rtt = max_rtt.u.i;
+
if (toml_routing(table, conf) < 0) {
log_err("Invalid routing option.");
return -1;
diff --git a/src/irmd/oap/cli.c b/src/irmd/oap/cli.c
index 3518b4d1..ebfcd71f 100644
--- a/src/irmd/oap/cli.c
+++ b/src/irmd/oap/cli.c
@@ -291,6 +291,13 @@ int oap_cli_prepare(void ** ctx,
goto fail_kex;
}
+ /* A re-keyed flow is encrypted; absent config must fail closed. */
+ if (rekey && !IS_KEX_ALGO_SET(&s->scfg)) {
+ log_err_id(s->id.data, "Refusing re-key without KEX for %s.",
+ info->name);
+ goto fail_kex;
+ }
+
/* Re-key forces server-encap: client-encap forfeits FS/PCS. */
if (rekey && s->scfg.x.mode == KEM_MODE_CLIENT_ENCAP) {
s->scfg.x.mode = KEM_MODE_SERVER_ENCAP;
@@ -385,26 +392,9 @@ static int do_client_kex_complete_kem(struct oap_cli_ctx * s,
struct sec_config * scfg = &s->scfg;
uint8_t * id = s->id.data;
uint8_t key_buf[SYMMKEYSZ];
+ buffer_t ct;
- if (scfg->x.mode == KEM_MODE_SERVER_ENCAP) {
- buffer_t ct;
-
- if (peer_hdr->kex.len == 0) {
- log_err_id(id, "Server did not send KEM CT.");
- return -ECRYPT;
- }
-
- ct.data = peer_hdr->kex.data;
- ct.len = peer_hdr->kex.len;
-
- if (kex_kem_decap(s->pkp, ct, scfg->k.nid, key_buf) < 0) {
- log_err_id(id, "Failed to decapsulate KEM.");
- return -ECRYPT;
- }
-
- log_dbg_id(id, "Client decapsulated server CT.");
-
- } else if (scfg->x.mode == KEM_MODE_CLIENT_ENCAP) {
+ if (scfg->x.mode == KEM_MODE_CLIENT_ENCAP) {
/* Key already derived during prepare */
memcpy(sk->key, s->key, SYMMKEYSZ);
sk->nid = scfg->c.nid;
@@ -413,6 +403,22 @@ static int do_client_kex_complete_kem(struct oap_cli_ctx * s,
return 0;
}
+ /* KEM_MODE_SERVER_ENCAP */
+ if (peer_hdr->kex.len == 0) {
+ log_err_id(id, "Server did not send KEM CT.");
+ return -ECRYPT;
+ }
+
+ ct.data = peer_hdr->kex.data;
+ ct.len = peer_hdr->kex.len;
+
+ if (kex_kem_decap(s->pkp, ct, scfg->k.nid, key_buf) < 0) {
+ log_err_id(id, "Failed to decapsulate KEM.");
+ return -ECRYPT;
+ }
+
+ log_dbg_id(id, "Client decapsulated server CT.");
+
memcpy(sk->key, key_buf, SYMMKEYSZ);
sk->nid = scfg->c.nid;
crypt_secure_clear(key_buf, SYMMKEYSZ);
diff --git a/src/irmd/oap/hdr.c b/src/irmd/oap/hdr.c
index 6f355133..0cff345c 100644
--- a/src/irmd/oap/hdr.c
+++ b/src/irmd/oap/hdr.c
@@ -292,9 +292,9 @@ static void write_oap_fixed(uint8_t * buf,
kex_len |= OAP_KEX_ROLE_BIT;
}
- kex_len = hton16(kex_len);
- memcpy(buf + offset, &kex_len, sizeof(kex_len));
- offset += sizeof(kex_len);
+ v = hton16(kex_len);
+ memcpy(buf + offset, &v, sizeof(v));
+ offset += sizeof(v);
v = hton16((uint16_t) data_len);
memcpy(buf + offset, &v, sizeof(v));
diff --git a/src/irmd/oap/srv.c b/src/irmd/oap/srv.c
index cc3dec5b..d78fc8d4 100644
--- a/src/irmd/oap/srv.c
+++ b/src/irmd/oap/srv.c
@@ -473,6 +473,12 @@ int oap_srv_process(const struct name_info * info,
peer_crt->len = peer_hdr.crt.len;
}
+ /* A re-keyed flow is encrypted; refuse a plaintext re-key. */
+ if (rekey && peer_hdr.kex.len == 0) {
+ log_err_id(id, "Re-key request without KEX.");
+ goto fail_kex;
+ }
+
if (do_server_kex(info, &peer_hdr, &scfg, &local_hdr.kex, sk) < 0)
goto fail_kex;
diff --git a/src/irmd/oap/tests/oap_test.c b/src/irmd/oap/tests/oap_test.c
index 145b68c7..b24bb786 100644
--- a/src/irmd/oap/tests/oap_test.c
+++ b/src/irmd/oap/tests/oap_test.c
@@ -269,6 +269,76 @@ static int test_oap_rekey_badcache_all(void)
return ret;
}
+/* Absent sec config (ENOENT) clears the KEX; a re-key must fail closed. */
+static int test_oap_cli_rejects_rekey_no_kex(void)
+{
+ struct oap_test_ctx ctx;
+
+ TEST_START();
+
+ test_enc_noauth_cfg();
+ test_cfg.cli.kex = NID_undef;
+
+ if (oap_test_setup(&ctx, root_ca_crt_ec, im_ca_crt_ec) < 0)
+ goto fail;
+
+ ctx.rekey = true;
+
+ if (oap_cli_prepare_ctx(&ctx) == 0) {
+ printf("Client prepared a re-key without KEX.\n");
+ goto fail_cleanup;
+ }
+
+ oap_test_teardown(&ctx);
+
+ TEST_SUCCESS();
+
+ return TEST_RC_SUCCESS;
+ fail_cleanup:
+ oap_test_teardown(&ctx);
+ fail:
+ TEST_FAIL();
+ return TEST_RC_FAIL;
+}
+
+static int test_oap_srv_rejects_rekey_no_kex(void)
+{
+ struct oap_test_ctx ctx;
+
+ TEST_START();
+
+ test_enc_noauth_cfg();
+ test_cfg.cli.kex = NID_undef;
+ test_cfg.srv.kex = NID_undef;
+
+ if (oap_test_setup(&ctx, root_ca_crt_ec, im_ca_crt_ec) < 0)
+ goto fail;
+
+ /* First-contact plaintext request, replayed as a re-key. */
+ if (oap_cli_prepare_ctx(&ctx) < 0) {
+ printf("Client prepare failed.\n");
+ goto fail_cleanup;
+ }
+
+ ctx.rekey = true;
+
+ if (oap_srv_process_ctx(&ctx) == 0) {
+ printf("Server accepted a re-key without KEX.\n");
+ goto fail_cleanup;
+ }
+
+ oap_test_teardown(&ctx);
+
+ TEST_SUCCESS();
+
+ return TEST_RC_SUCCESS;
+ fail_cleanup:
+ oap_test_teardown(&ctx);
+ fail:
+ TEST_FAIL();
+ return TEST_RC_FAIL;
+}
+
static int test_oap_roundtrip_kex_only(void)
{
test_enc_noauth_cfg();
@@ -1945,6 +2015,8 @@ int oap_test(int argc,
ret |= test_oap_rekey_all();
ret |= test_oap_rekey_badcache_all();
ret |= test_oap_rekey_srv_badcache_all();
+ ret |= test_oap_cli_rejects_rekey_no_kex();
+ ret |= test_oap_srv_rejects_rekey_no_kex();
ret |= test_oap_roundtrip_all();
ret |= test_oap_roundtrip_md_all();
@@ -1987,6 +2059,11 @@ int oap_test(int argc,
(void) test_oap_roundtrip_auth_only;
(void) test_oap_roundtrip_kex_only;
(void) test_oap_piggyback_data;
+ (void) test_oap_rekey_all;
+ (void) test_oap_rekey_badcache_all;
+ (void) test_oap_rekey_srv_badcache_all;
+ (void) test_oap_cli_rejects_rekey_no_kex;
+ (void) test_oap_srv_rejects_rekey_no_kex;
(void) test_oap_roundtrip;
(void) test_oap_roundtrip_all;
(void) test_oap_roundtrip_md;
@@ -1999,14 +2076,15 @@ int oap_test(int argc,
(void) test_oap_deflated_length_field;
(void) test_oap_nid_without_kex;
(void) test_oap_unsupported_nid;
+ (void) test_oap_unsupported_nid_undefined;
+ (void) test_oap_unsupported_nid_all;
(void) test_oap_cipher_mismatch;
(void) test_oap_srv_enc_cli_none;
(void) test_oap_cli_enc_srv_none;
(void) test_oap_cli_rejects_downgrade;
(void) test_oap_cli_rejects_suite_swap;
(void) test_oap_srv_rejects_weak_kex;
- (void) test_oap_outdated_packet;
- (void) test_oap_future_packet;
+ (void) test_oap_ts_reject_all;
(void) test_oap_replay_packet;
(void) test_oap_replay_generations;
(void) test_oap_missing_root_ca;
@@ -2018,6 +2096,8 @@ int oap_test(int argc,
(void) test_oap_srv_rejects_md_mismatch;
(void) test_oap_server_cert_hidden;
(void) test_oap_sealed_tamper;
+ (void) test_oap_cleartext_echo_tamper;
+ (void) test_oap_response_id_tamper;
(void) test_oap_rekey;
(void) test_oap_rekey_badcache;
diff --git a/src/irmd/reg/name.c b/src/irmd/reg/name.c
index 61a328ec..a3621fc3 100644
--- a/src/irmd/reg/name.c
+++ b/src/irmd/reg/name.c
@@ -157,6 +157,8 @@ static struct prog_entry * __reg_name_get_prog(const struct reg_name * name,
llist_for_each(p, &name->progs) {
struct prog_entry * entry;
entry = list_entry(p, struct prog_entry, next);
+ assert(entry->exec != NULL);
+ assert(entry->exec[0] != NULL);
if (strcmp(entry->exec[0], prog) == 0)
return entry;
}
diff --git a/src/irmd/reg/proc.c b/src/irmd/reg/proc.c
index 8a7e24c9..94ac6b8f 100644
--- a/src/irmd/reg/proc.c
+++ b/src/irmd/reg/proc.c
@@ -119,6 +119,7 @@ static struct name_entry * __reg_proc_get_name(const struct reg_proc * proc,
llist_for_each(p, &proc->names) {
struct name_entry * entry;
entry = list_entry(p, struct name_entry, next);
+ assert(entry->name != NULL);
if (strcmp(entry->name, name) == 0)
return entry;
}
@@ -140,7 +141,7 @@ int reg_proc_add_name(struct reg_proc * proc,
}
entry->name = strdup(name);
- if (entry == NULL) {
+ if (entry->name == NULL) {
log_err("Failed to strdup name.");
goto fail_name;
}
diff --git a/src/irmd/reg/prog.c b/src/irmd/reg/prog.c
index 2d7f9f8d..1e977c89 100644
--- a/src/irmd/reg/prog.c
+++ b/src/irmd/reg/prog.c
@@ -107,6 +107,7 @@ static struct name_entry * __reg_prog_get_name(const struct reg_prog * prog,
llist_for_each(p, &prog->names) {
struct name_entry * entry;
entry = list_entry(p, struct name_entry, next);
+ assert(entry->name != NULL);
if (strcmp(entry->name, name) == 0)
return entry;
}
@@ -128,7 +129,7 @@ int reg_prog_add_name(struct reg_prog * prog,
}
entry->name = strdup(name);
- if (entry == NULL) {
+ if (entry->name == NULL) {
log_err("Failed to strdup name.");
goto fail_name;
}