diff options
Diffstat (limited to 'src/irmd')
| -rw-r--r-- | src/irmd/configfile.c | 7 | ||||
| -rw-r--r-- | src/irmd/oap/cli.c | 44 | ||||
| -rw-r--r-- | src/irmd/oap/hdr.c | 6 | ||||
| -rw-r--r-- | src/irmd/oap/srv.c | 6 | ||||
| -rw-r--r-- | src/irmd/oap/tests/oap_test.c | 84 | ||||
| -rw-r--r-- | src/irmd/reg/name.c | 2 | ||||
| -rw-r--r-- | src/irmd/reg/proc.c | 3 | ||||
| -rw-r--r-- | src/irmd/reg/prog.c | 3 |
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; } |
