summaryrefslogtreecommitdiff
path: root/src/irmd
diff options
context:
space:
mode:
Diffstat (limited to 'src/irmd')
-rw-r--r--src/irmd/main.c1
-rw-r--r--src/irmd/oap.c130
-rw-r--r--src/irmd/oap/auth.c4
-rw-r--r--src/irmd/oap/cli.c2
-rw-r--r--src/irmd/oap/srv.c2
-rw-r--r--src/irmd/oap/tests/oap_test.c72
-rw-r--r--src/irmd/oap/tests/oap_test_ml_dsa.c1
-rw-r--r--src/irmd/reg/tests/reg_test.c2
8 files changed, 79 insertions, 135 deletions
diff --git a/src/irmd/main.c b/src/irmd/main.c
index e610a015..a85a9bf0 100644
--- a/src/irmd/main.c
+++ b/src/irmd/main.c
@@ -2416,6 +2416,7 @@ int main(int argc,
pthread_sigmask(SIG_UNBLOCK, &sigset, NULL);
crypt_secure_malloc_fini();
+ crypt_cleanup();
reg_clear();
diff --git a/src/irmd/oap.c b/src/irmd/oap.c
deleted file mode 100644
index 1831f533..00000000
--- a/src/irmd/oap.c
+++ /dev/null
@@ -1,130 +0,0 @@
-/*
- * Ouroboros - Copyright (C) 2016 - 2026
- *
- * OAP - Shared credential and configuration loading
- *
- * Dimitri Staessens <dimitri@ouroboros.rocks>
- * Sander Vrijders <sander@ouroboros.rocks>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., http://www.fsf.org/about/contact/.
- */
-
-#if defined(__linux__) || defined(__CYGWIN__)
- #define _DEFAULT_SOURCE
-#else
- #define _POSIX_C_SOURCE 200809L
-#endif
-
-#define OUROBOROS_PREFIX "irmd/oap"
-
-#include <ouroboros/crypt.h>
-#include <ouroboros/errno.h>
-#include <ouroboros/logs.h>
-
-#include "config.h"
-
-#include <assert.h>
-#include <string.h>
-#include <sys/stat.h>
-
-/*
- * Shared credential and configuration loading helpers
- */
-
-#ifndef OAP_TEST_MODE
-
-static bool file_exists(const char * path)
-{
- struct stat s;
-
- if (stat(path, &s) < 0 && errno == ENOENT) {
- log_dbg("File %s does not exist.", path);
- return false;
- }
-
- return true;
-}
-
-int load_credentials(const char * name,
- const struct name_sec_paths * paths,
- void ** pkp,
- void ** crt)
-{
- assert(paths != NULL);
- assert(pkp != NULL);
- assert(crt != NULL);
-
- *pkp = NULL;
- *crt = NULL;
-
- if (!file_exists(paths->crt) || !file_exists(paths->key)) {
- log_info("No authentication certificates for %s.", name);
- return 0;
- }
-
- if (crypt_load_crt_file(paths->crt, crt) < 0) {
- log_err("Failed to load %s for %s.", paths->crt, name);
- goto fail_crt;
- }
-
- if (crypt_load_privkey_file(paths->key, pkp) < 0) {
- log_err("Failed to load %s for %s.", paths->key, name);
- goto fail_key;
- }
-
- log_info("Loaded authentication certificates for %s.", name);
-
- return 0;
-
- fail_key:
- crypt_free_crt(*crt);
- *crt = NULL;
- fail_crt:
- return -EAUTH;
-}
-
-int load_kex_config(const char * name,
- const char * path,
- struct sec_config * cfg)
-{
- assert(name != NULL);
- assert(cfg != NULL);
-
- memset(cfg, 0, sizeof(*cfg));
-
- /* Load encryption config */
- if (!file_exists(path))
- log_dbg("No encryption %s for %s.", path, name);
-
- if (load_sec_config_file(cfg, path) < 0) {
- log_warn("Failed to load %s for %s.", path, name);
- return -1;
- }
-
- if (!IS_KEX_ALGO_SET(cfg)) {
- log_info("Key exchange not configured for %s.", name);
- return 0;
- }
-
- if (cfg->c.nid == NID_undef || crypt_nid_to_str(cfg->c.nid) == NULL) {
- log_err("Invalid cipher NID %d for %s.", cfg->c.nid, name);
- return -ECRYPT;
- }
-
- log_info("Encryption enabled for %s.", name);
-
- return 0;
-}
-
-#endif /* OAP_TEST_MODE */
diff --git a/src/irmd/oap/auth.c b/src/irmd/oap/auth.c
index a11ab158..4b86f055 100644
--- a/src/irmd/oap/auth.c
+++ b/src/irmd/oap/auth.c
@@ -183,7 +183,7 @@ int oap_auth_peer(char * name,
const struct oap_hdr * peer_hdr)
{
void * crt;
- void * pk;
+ void * pk = NULL;
buffer_t sign; /* Signed region */
uint8_t * id = peer_hdr->id.data;
@@ -244,8 +244,8 @@ int oap_auth_peer(char * name,
return 0;
fail_check_sig:
- crypt_free_key(pk);
fail_crt:
+ crypt_free_key(pk);
crypt_free_crt(crt);
fail_check:
return -EAUTH;
diff --git a/src/irmd/oap/cli.c b/src/irmd/oap/cli.c
index 8ecd317d..7a202da7 100644
--- a/src/irmd/oap/cli.c
+++ b/src/irmd/oap/cli.c
@@ -50,7 +50,7 @@
struct oap_cli_ctx {
uint8_t __id[OAP_ID_SIZE];
buffer_t id;
- uint8_t kex_buf[MSGBUFSZ];
+ uint8_t kex_buf[CRYPT_KEY_BUFSZ];
uint8_t req_hash[MAX_HASH_SIZE];
size_t req_hash_len;
int req_md_nid;
diff --git a/src/irmd/oap/srv.c b/src/irmd/oap/srv.c
index 36391e50..afc54acc 100644
--- a/src/irmd/oap/srv.c
+++ b/src/irmd/oap/srv.c
@@ -384,7 +384,7 @@ int oap_srv_process(const struct name_info * info,
struct oap_hdr peer_hdr;
struct oap_hdr local_hdr;
struct sec_config kcfg;
- uint8_t kex_buf[MSGBUFSZ];
+ uint8_t kex_buf[CRYPT_KEY_BUFSZ];
uint8_t hash_buf[MAX_HASH_SIZE];
buffer_t req_hash = BUF_INIT;
ssize_t hash_ret;
diff --git a/src/irmd/oap/tests/oap_test.c b/src/irmd/oap/tests/oap_test.c
index 2f0f0b4d..a324b586 100644
--- a/src/irmd/oap/tests/oap_test.c
+++ b/src/irmd/oap/tests/oap_test.c
@@ -1071,6 +1071,74 @@ static int test_oap_replay_packet(void)
return TEST_RC_FAIL;
}
+/* Server rejects client certificate when root CA is missing from store */
+static int test_oap_missing_root_ca(void)
+{
+ struct oap_test_ctx ctx;
+ void * im_ca = NULL;
+
+ test_default_cfg();
+
+ TEST_START();
+
+ memset(&ctx, 0, sizeof(ctx));
+
+ strcpy(ctx.srv.info.name, "test-1.unittest.o7s");
+ strcpy(ctx.cli.info.name, "test-1.unittest.o7s");
+
+ if (oap_auth_init() < 0) {
+ printf("Failed to init OAP.\n");
+ goto fail;
+ }
+
+ /* Load intermediate CA but intentionally omit the root CA */
+ if (crypt_load_crt_str(im_ca_crt_ec, &im_ca) < 0) {
+ printf("Failed to load intermediate CA cert.\n");
+ goto fail_fini;
+ }
+
+ ctx.im_ca = im_ca;
+
+ if (oap_auth_add_ca_crt(im_ca) < 0) {
+ printf("Failed to add intermediate CA cert to store.\n");
+ goto fail_fini;
+ }
+
+ if (oap_cli_prepare_ctx(&ctx) < 0) {
+ printf("Client prepare failed.\n");
+ goto fail_fini;
+ }
+
+ /* Server processes and signs response - succeeds without root CA */
+ if (oap_srv_process_ctx(&ctx) < 0) {
+ printf("Server process failed.\n");
+ goto fail_teardown;
+ }
+
+ /* Client verifies server certificate against trust store:
+ * should reject because root CA is not in the store */
+ if (oap_cli_complete_ctx(&ctx) == 0) {
+ printf("Client should reject without root CA.\n");
+ goto fail_teardown;
+ }
+
+ oap_test_teardown(&ctx);
+
+ TEST_SUCCESS();
+ return TEST_RC_SUCCESS;
+
+ fail_teardown:
+ oap_test_teardown(&ctx);
+ TEST_FAIL();
+ return TEST_RC_FAIL;
+ fail_fini:
+ crypt_free_crt(im_ca);
+ oap_auth_fini();
+ fail:
+ TEST_FAIL();
+ return TEST_RC_FAIL;
+}
+
/* Test that client rejects server with wrong certificate name */
static int test_oap_server_name_mismatch(void)
{
@@ -1149,6 +1217,7 @@ int oap_test(int argc,
ret |= test_oap_outdated_packet();
ret |= test_oap_future_packet();
ret |= test_oap_replay_packet();
+ ret |= test_oap_missing_root_ca();
ret |= test_oap_server_name_mismatch();
#else
(void) test_oap_roundtrip_auth_only;
@@ -1173,9 +1242,12 @@ int oap_test(int argc,
(void) test_oap_outdated_packet;
(void) test_oap_future_packet;
(void) test_oap_replay_packet;
+ (void) test_oap_missing_root_ca;
(void) test_oap_server_name_mismatch;
ret = TEST_RC_SKIP;
#endif
+ crypt_cleanup();
+
return ret;
}
diff --git a/src/irmd/oap/tests/oap_test_ml_dsa.c b/src/irmd/oap/tests/oap_test_ml_dsa.c
index f9e6bdb2..81b307ab 100644
--- a/src/irmd/oap/tests/oap_test_ml_dsa.c
+++ b/src/irmd/oap/tests/oap_test_ml_dsa.c
@@ -442,6 +442,7 @@ int oap_test_ml_dsa(int argc,
ret = TEST_RC_SKIP;
#endif
+ crypt_cleanup();
return ret;
}
diff --git a/src/irmd/reg/tests/reg_test.c b/src/irmd/reg/tests/reg_test.c
index b426c0dd..f4b0188b 100644
--- a/src/irmd/reg/tests/reg_test.c
+++ b/src/irmd/reg/tests/reg_test.c
@@ -1491,7 +1491,7 @@ static int test_wait_accepting_fail_name(void)
static void * test_call_flow_accept(void * o)
{
struct timespec abstime;
- struct timespec timeo = TIMESPEC_INIT_MS(10);
+ struct timespec timeo = TIMESPEC_INIT_MS(30);
buffer_t pbuf = BUF_INIT;
struct proc_info pinfo = TEST_PROC_INFO;