From 67c55d5869d5473e5139614637f31ea37746181d Mon Sep 17 00:00:00 2001 From: Dimitri Staessens Date: Thu, 11 Jun 2026 10:03:14 +0000 Subject: irmd: Specify peer authentication contract OAP accepted requests and responses without a certificate even when the peer was expected to authenticate. An on-path attacker could strip the certificate and signature from a flow allocation response and substitute its own key exchange, silently downgrading the handshake to unauthenticated. Add an auth=required|optional policy to enc.conf, enforced per role: a client config requires the server to present a valid certificate, a server config requires the same from the client. Default is required for client side (https), optional server side. The client side default can be changed via OAP_CLIENT_AUTH_DEFAULT for testing. Replace the bare 'none' keyword with encryption=none, which disables encryption only: the digest and the authentication policy are kept, so authenticated but unencrypted flows can be configured. Configs using bare 'none' are now rejected. Signed-off-by: Dimitri Staessens Signed-off-by: Sander Vrijders --- src/lib/crypt.c | 31 ++++++++++++++++++++++++++----- 1 file changed, 26 insertions(+), 5 deletions(-) (limited to 'src/lib/crypt.c') diff --git a/src/lib/crypt.c b/src/lib/crypt.c index 71197f6e..66d07131 100644 --- a/src/lib/crypt.c +++ b/src/lib/crypt.c @@ -162,6 +162,7 @@ int parse_sec_config(struct sec_config * cfg, char * equals; char * key; char * value; + bool no_enc = false; assert(cfg != NULL); assert(fp != NULL); @@ -172,6 +173,7 @@ int parse_sec_config(struct sec_config * cfg, SET_KEX_KDF_NID(cfg, NID_sha256); SET_KEX_CIPHER_NID(cfg, NID_aes_256_gcm); SET_KEX_DIGEST_NID(cfg, NID_sha256); + /* req_auth is seeded per-role by the caller; only auth= overrides it */ while (fgets(line, sizeof(line), fp) != NULL) { char * trimmed; @@ -180,12 +182,10 @@ int parse_sec_config(struct sec_config * cfg, if (line[0] == '#' || line[0] == '\n') continue; - /* Check for 'none' keyword */ + /* Bare 'none' keyword replaced by encryption=none */ trimmed = trim_whitespace(line); - if (strcmp(trimmed, "none") == 0) { - memset(cfg, 0, sizeof(*cfg)); - return 0; - } + if (strcmp(trimmed, "none") == 0) + return -EINVAL; /* Find the = separator */ equals = strchr(line, '='); @@ -221,9 +221,30 @@ int parse_sec_config(struct sec_config * cfg, } else { return -EINVAL; } + } else if (strcmp(key, "auth") == 0) { + if (strcmp(value, "required") == 0) { + cfg->req_auth = true; + } else if (strcmp(value, "optional") == 0) { + cfg->req_auth = false; + } else { + return -EINVAL; + } + } else if (strcmp(key, "encryption") == 0) { + if (strcmp(value, "none") != 0) + return -EINVAL; + no_enc = true; + } else { + return -EINVAL; } } + if (no_enc) { + /* Digest stays: it belongs to the auth axis */ + CLEAR_KEX_ALGO(cfg); + CLEAR_KEX_KDF(cfg); + CLEAR_KEX_CIPHER(cfg); + } + return 0; } -- cgit v1.2.3