From 47034834790e778f28b082842b3ed1c7bd44f29a Mon Sep 17 00:00:00 2001 From: Dimitri Staessens Date: Sun, 21 Jun 2026 13:03:36 +0200 Subject: config: Rename enc.conf to sec.conf The per-name config file holds more than encryption settings (KEX, cipher, KDF, peer authentication), so renamed it from enc.conf to sec.conf and the code internals to match. Signed-off-by: Dimitri Staessens Signed-off-by: Sander Vrijders --- enc.conf.in | 182 ---------------------------------------- include/ouroboros/name.h | 6 +- irmd.conf.in | 4 +- sec.conf.in | 177 ++++++++++++++++++++++++++++++++++++++ src/irmd/CMakeLists.txt | 6 +- src/irmd/configfile.c | 12 +-- src/irmd/main.c | 8 +- src/irmd/oap/cli.c | 2 +- src/irmd/oap/srv.c | 2 +- src/tools/irm/irm_name_create.c | 24 +++--- 10 files changed, 209 insertions(+), 214 deletions(-) delete mode 100644 enc.conf.in create mode 100644 sec.conf.in diff --git a/enc.conf.in b/enc.conf.in deleted file mode 100644 index 980cfb2e..00000000 --- a/enc.conf.in +++ /dev/null @@ -1,182 +0,0 @@ -### Example Ouroboros encryption configuration file -# -# This file specifies the key exchange (KEX) algorithm and cipher to use -# for encrypted flows. -# -# File Locations: -# --------------- -# -# This file should be placed at one of: -# @OUROBOROS_CONFIG_DIR@/security/server//enc.conf (server-side config) -# @OUROBOROS_CONFIG_DIR@/security/client//enc.conf (client-side config) -# -# Where is the service name registered with 'irm name create'. -# -# You can override the default paths using: -# irm name create sencpath cencpath -# -# Configuration Options: -# ---------------------- -# -# kex= Key exchange/encapsulation algorithm -# cipher= Symmetric cipher algorithm -# kdf= Key derivation function hash algorithm -# kem_mode= KEM encapsulation mode (server or client) -# auth= Peer authentication policy (required or optional) -# encryption=none Explicitly disable encryption -# -# Supported KEX algorithms (kex=): -# -------------------------------- -# -# ECDH Curves: -# prime256v1 NIST P-256 (default) -# secp384r1 NIST P-384 -# secp521r1 NIST P-521 -# X25519 Curve25519 -# X448 Curve448 -# -# Finite Field Diffie-Hellman (RFC 7919): -# ffdhe2048 2048-bit MODP Group -# ffdhe3072 3072-bit MODP Group -# ffdhe4096 4096-bit MODP Group -# -# ML-KEM (FIPS 203): -# ML-KEM-512 CRYSTALS-Kyber-512 -# ML-KEM-768 CRYSTALS-Kyber-768 -# ML-KEM-1024 CRYSTALS-Kyber-1024 -# -# Hybrid KEMs: -# X25519MLKEM768 X25519 + ML-KEM-768 -# X448MLKEM1024 X448 + ML-KEM-1024 -# -# Supported cipher algorithms (cipher=): -# -------------------------------------- -# -# Authenticated encryption: -# aes-128-gcm AES-128 in GCM mode -# aes-192-gcm AES-192 in GCM mode -# aes-256-gcm AES-256 in GCM mode (default) -# chacha20-poly1305 ChaCha20-Poly1305 -# -# Stream ciphers (not recommended): -# aes-128-ctr AES-128 in CTR mode -# aes-192-ctr AES-192 in CTR mode -# aes-256-ctr AES-256 in CTR mode -# -# Key Derivation Functions (kdf=): -# --------------------------------- -# -# Hash algorithms for key derivation in KEX operations: -# -# sha256 SHA-256 (default) -# sha384 SHA-384 -# sha512 SHA-512 -# sha3-256 SHA3-256 -# sha3-384 SHA3-384 -# sha3-512 SHA3-512 -# blake2b512 BLAKE2b-512 -# blake2s256 BLAKE2s-256 -# -# Peer Authentication (auth=): -# ---------------------------- -# -# optional Accept unauthenticated peers -# required Reject peers that do not present a valid certificate -# -# This setting applies to the *peer*: in a client config it requires -# the server to authenticate; in a server config it requires the -# client. The defaults mirror the web: a client config defaults to -# required (the server must authenticate), a server config defaults -# to optional (client authentication is opt-in). Set auth=required on -# the server too for mutual authentication. Combine encryption=none -# with auth=required for authenticated but unencrypted flows. -# -# Issuer Pinning (cacert=): -# ------------------------- -# -# cacert= Path to a CA certificate that must be part of the -# peer certificate's verified chain -# -# The peer certificate is always validated against the trusted CA -# store; cacert= further restricts which CA must have issued it: a -# certificate, if presented, must chain through the pinned CA. Whether -# a certificate is mandatory is controlled by auth= alone: under -# auth=optional a peer may still connect without one. The pinned CA -# must load when the config is read, otherwise flow allocation fails. -# -# KEM Mode (kem_mode=): -# --------------------- -# -# For KEM algorithms (ML-KEM-* and hybrid KEMs), specify which side -# performs the encapsulation operation: -# -# server Server encapsulates to client's ephemeral public key (default, matches TLS 1.3) -# - Client generates ephemeral keypair, sends public key in request -# - Server encapsulates and sends ciphertext in response -# - Client decapsulates with ephemeral private key -# - Standard approach, no pre-shared keys needed -# -# client Client encapsulates to server's static public key (alternative) -# - Requires cached server public key at: -# @OUROBOROS_CONFIG_DIR@/security/client//kex.srv.pub.[pem|raw] -# - Client encapsulates and sends ciphertext in initial request -# - Server decapsulates with its static private key from: -# @OUROBOROS_CONFIG_DIR@/security/server/kex.key.pem -# - More efficient (0 round-trip) but requires key distribution -# and forfeits forward secrecy -# -# Note: Both sides must use the same kem_mode setting. -# This option is ignored for ECDH/DH key exchange algorithms. -# -# Key Management for Client Mode: -# -------------------------------- -# -# For client encapsulation mode, you must: -# 1. Generate server KEM keypair: -# openssl genpkey -algorithm ML-KEM-768 \ -# -out @OUROBOROS_CONFIG_DIR@/security/server/kex.key.pem -# 2. Extract and distribute server public key: -# openssl pkey -in kex.key.pem -pubout -out kex.srv.pub.pem -# 3. Cache on clients at: -# @OUROBOROS_CONFIG_DIR@/security/client//kex.srv.pub.pem -# -# File formats: -# - Pure ML-KEM: PEM format (.pem extension) -# - Hybrid KEMs: Raw bytes (.raw extension) -# -# Examples: -# --------- -# -# Default configuration (NIST P-256 ECDH + AES-256-GCM): -kex=prime256v1 -cipher=aes-256-gcm -kdf=sha256 -# -# Post-quantum KEX with server encapsulation (default, like TLS 1.3): -# kex=ML-KEM-768 -# cipher=chacha20-poly1305 -# kdf=sha256 -# kem_mode=server -# -# Post-quantum KEX with client encapsulation (requires key distribution): -# kex=ML-KEM-768 -# cipher=chacha20-poly1305 -# kdf=sha256 -# kem_mode=client -# -# Hybrid KEX (quantum-resistant): -# kex=X25519MLKEM768 -# cipher=aes-256-gcm -# kdf=sha256 -# -# High security configuration: -# kex=secp521r1 -# cipher=aes-256-gcm -# kdf=sha512 -# -# Disable encryption: -# encryption=none -# -# Authentication required, no encryption: -# encryption=none -# auth=required diff --git a/include/ouroboros/name.h b/include/ouroboros/name.h index a9393820..a3aac8c4 100644 --- a/include/ouroboros/name.h +++ b/include/ouroboros/name.h @@ -34,9 +34,9 @@ enum pol_balance { }; struct name_sec_paths { - char enc[NAME_PATH_SIZE + 1]; /* path to crypt for this name */ - char key[NAME_PATH_SIZE + 1]; /* path to key for this name */ - char crt[NAME_PATH_SIZE + 1]; /* path to crt for this name */ + char sec[NAME_PATH_SIZE + 1]; /* path to sec.conf for this name */ + char key[NAME_PATH_SIZE + 1]; /* path to key for this name */ + char crt[NAME_PATH_SIZE + 1]; /* path to crt for this name */ }; struct name_info { diff --git a/irmd.conf.in b/irmd.conf.in index dee88392..b9b79782 100644 --- a/irmd.conf.in +++ b/irmd.conf.in @@ -56,10 +56,10 @@ prog=["@INSTALL_DIR@/ovpn"] # Defaults to []. prog=["@INSTALL_DIR@/oping"] # Defaults to []. args=["--listen"] # Defaults to disabled. Autostart server with these args. lb="round-robin" # Defaults to spill (load-balancing options: spill, round-robin). -# server_enc_file=/path/to/enc.conf Default: @OUROBOROS_SRV_CRT_DIR@//enc.conf +# server_sec_file=/path/to/sec.conf Default: @OUROBOROS_SRV_CRT_DIR@//sec.conf # server_crt_file=/path/to/crt.pem Default: @OUROBOROS_SRV_CRT_DIR@//crt.pem # server_key_file=/path/to/key.pem Default: @OUROBOROS_SRV_CRT_DIR@//key.pem -# client_enc_file=/path/to/enc.conf Default: @OUROBOROS_CLI_CRT_DIR@//enc.conf +# client_sec_file=/path/to/sec.conf Default: @OUROBOROS_CLI_CRT_DIR@//sec.conf # client_crt_file=/path/to/crt.pem Default: @OUROBOROS_CLI_CRT_DIR@//crt.pem # client_key_file=/path/to/key.pem Default: @OUROBOROS_CLI_CRT_DIR@//key.pem diff --git a/sec.conf.in b/sec.conf.in new file mode 100644 index 00000000..4796b72d --- /dev/null +++ b/sec.conf.in @@ -0,0 +1,177 @@ +### Example Ouroboros security configuration file +# +# This file specifies the security parameters for a service: the key +# exchange (KEX) algorithm, cipher, key derivation, and peer authentication. +# +# File Locations: +# --------------- +# +# This file should be placed at one of: +# @OUROBOROS_CONFIG_DIR@/security/server//sec.conf (server-side config) +# @OUROBOROS_CONFIG_DIR@/security/client//sec.conf (client-side config) +# +# Where is the service name registered with 'irm name create'. +# +# You can override the default paths using: +# irm name create ssecpath csecpath +# +# Configuration Options: +# ---------------------- +# +# kex= Key exchange/encapsulation algorithm +# cipher= Symmetric cipher algorithm +# kdf= Key derivation function hash algorithm +# kem_mode= KEM encapsulation mode (server or client) +# auth= Peer authentication policy (required or optional) +# encryption=none Explicitly disable encryption +# +# Supported KEX algorithms (kex=): +# -------------------------------- +# +# ECDH Curves: +# prime256v1 NIST P-256 (default) +# secp384r1 NIST P-384 +# secp521r1 NIST P-521 +# X25519 Curve25519 +# X448 Curve448 +# +# Finite Field Diffie-Hellman (RFC 7919): +# ffdhe2048 2048-bit MODP Group +# ffdhe3072 3072-bit MODP Group +# ffdhe4096 4096-bit MODP Group +# +# ML-KEM (FIPS 203): +# ML-KEM-512 CRYSTALS-Kyber-512 +# ML-KEM-768 CRYSTALS-Kyber-768 +# ML-KEM-1024 CRYSTALS-Kyber-1024 +# +# Hybrid KEMs: +# X25519MLKEM768 X25519 + ML-KEM-768 +# X448MLKEM1024 X448 + ML-KEM-1024 +# +# Supported cipher algorithms (cipher=): +# -------------------------------------- +# +# Authenticated encryption: +# aes-128-gcm AES-128 in GCM mode +# aes-192-gcm AES-192 in GCM mode +# aes-256-gcm AES-256 in GCM mode (default) +# chacha20-poly1305 ChaCha20-Poly1305 +# +# Key Derivation Functions (kdf=): +# --------------------------------- +# +# Hash algorithms for key derivation in KEX operations: +# +# sha256 SHA-256 (default) +# sha384 SHA-384 +# sha512 SHA-512 +# sha3-256 SHA3-256 +# sha3-384 SHA3-384 +# sha3-512 SHA3-512 +# blake2b512 BLAKE2b-512 +# blake2s256 BLAKE2s-256 +# +# Peer Authentication (auth=): +# ---------------------------- +# +# optional Accept unauthenticated peers +# required Reject peers that do not present a valid certificate +# +# This setting applies to the *peer*: in a client config it requires +# the server to authenticate; in a server config it requires the +# client. The defaults mirror the web: a client config defaults to +# required (the server must authenticate), a server config defaults +# to optional (client authentication is opt-in). Set auth=required on +# the server too for mutual authentication. Combine encryption=none +# with auth=required for authenticated but unencrypted flows. +# +# Issuer Pinning (cacert=): +# ------------------------- +# +# cacert= Path to a CA certificate that must be part of the +# peer certificate's verified chain +# +# The peer certificate is always validated against the trusted CA +# store; cacert= further restricts which CA must have issued it: a +# certificate, if presented, must chain through the pinned CA. Whether +# a certificate is mandatory is controlled by auth= alone: under +# auth=optional a peer may still connect without one. The pinned CA +# must load when the config is read, otherwise flow allocation fails. +# +# KEM Mode (kem_mode=): +# --------------------- +# +# For KEM algorithms (ML-KEM-* and hybrid KEMs), specify which side +# performs the encapsulation operation: +# +# server Server encapsulates to client's ephemeral public key (default, matches TLS 1.3) +# - Client generates ephemeral keypair, sends public key in request +# - Server encapsulates and sends ciphertext in response +# - Client decapsulates with ephemeral private key +# - Standard approach, no pre-shared keys needed +# +# client Client encapsulates to server's static public key (alternative) +# - Requires cached server public key at: +# @OUROBOROS_CONFIG_DIR@/security/client//kex.srv.pub.[pem|raw] +# - Client encapsulates and sends ciphertext in initial request +# - Server decapsulates with its static private key from: +# @OUROBOROS_CONFIG_DIR@/security/server/kex.key.pem +# - More efficient (0 round-trip) but requires key distribution +# and forfeits forward secrecy +# +# Note: Both sides must use the same kem_mode setting. +# This option is ignored for ECDH/DH key exchange algorithms. +# +# Key Management for Client Mode: +# -------------------------------- +# +# For client encapsulation mode, you must: +# 1. Generate server KEM keypair: +# openssl genpkey -algorithm ML-KEM-768 \ +# -out @OUROBOROS_CONFIG_DIR@/security/server/kex.key.pem +# 2. Extract and distribute server public key: +# openssl pkey -in kex.key.pem -pubout -out kex.srv.pub.pem +# 3. Cache on clients at: +# @OUROBOROS_CONFIG_DIR@/security/client//kex.srv.pub.pem +# +# File formats: +# - Pure ML-KEM: PEM format (.pem extension) +# - Hybrid KEMs: Raw bytes (.raw extension) +# +# Examples: +# --------- +# +# Default configuration (NIST P-256 ECDH + AES-256-GCM): +kex=prime256v1 +cipher=aes-256-gcm +kdf=sha256 +# +# Post-quantum KEX with server encapsulation (default, like TLS 1.3): +# kex=ML-KEM-768 +# cipher=chacha20-poly1305 +# kdf=sha256 +# kem_mode=server +# +# Post-quantum KEX with client encapsulation (requires key distribution): +# kex=ML-KEM-768 +# cipher=chacha20-poly1305 +# kdf=sha256 +# kem_mode=client +# +# Hybrid KEX (quantum-resistant): +# kex=X25519MLKEM768 +# cipher=aes-256-gcm +# kdf=sha256 +# +# High security configuration: +# kex=secp521r1 +# cipher=aes-256-gcm +# kdf=sha512 +# +# Disable encryption: +# encryption=none +# +# Authentication required, no encryption: +# encryption=none +# auth=required diff --git a/src/irmd/CMakeLists.txt b/src/irmd/CMakeLists.txt index 9aa747ca..5aa457ff 100644 --- a/src/irmd/CMakeLists.txt +++ b/src/irmd/CMakeLists.txt @@ -7,11 +7,11 @@ if(HAVE_TOML) set(INSTALL_DIR "${CMAKE_INSTALL_PREFIX}/${CMAKE_INSTALL_BINDIR}") configure_file("${CMAKE_SOURCE_DIR}/irmd.conf.in" "${CMAKE_BINARY_DIR}/${OUROBOROS_CONFIG_FILE}.example" @ONLY) - configure_file("${CMAKE_SOURCE_DIR}/enc.conf.in" - "${CMAKE_BINARY_DIR}/enc.conf.example" @ONLY) + configure_file("${CMAKE_SOURCE_DIR}/sec.conf.in" + "${CMAKE_BINARY_DIR}/sec.conf.example" @ONLY) install(FILES "${CMAKE_BINARY_DIR}/${OUROBOROS_CONFIG_FILE}.example" DESTINATION "${OUROBOROS_CONFIG_DIR}") - install(FILES "${CMAKE_BINARY_DIR}/enc.conf.example" + install(FILES "${CMAKE_BINARY_DIR}/sec.conf.example" DESTINATION "${OUROBOROS_CONFIG_DIR}") install(CODE " if(NOT EXISTS \"${OUROBOROS_CONFIG_DIR}/${OUROBOROS_CONFIG_FILE}\") diff --git a/src/irmd/configfile.c b/src/irmd/configfile.c index 53608eee..35cf4292 100644 --- a/src/irmd/configfile.c +++ b/src/irmd/configfile.c @@ -922,10 +922,10 @@ static int toml_name(toml_table_t * table, toml_array_t * progs; toml_array_t * args; toml_datum_t lb; - toml_datum_t senc; + toml_datum_t ssec; toml_datum_t scrt; toml_datum_t skey; - toml_datum_t cenc; + toml_datum_t csec; toml_datum_t ccrt; toml_datum_t ckey; @@ -957,8 +957,8 @@ static int toml_name(toml_table_t * table, log_err("Invalid load-balancing policy for %s.", name); return -1; } - senc = toml_string_in(table, "server_enc_file"); - if (senc.ok && cp_chk_path(info.s.enc, senc.u.s) < 0) + ssec = toml_string_in(table, "server_sec_file"); + if (ssec.ok && cp_chk_path(info.s.sec, ssec.u.s) < 0) return -1; scrt = toml_string_in(table, "server_crt_file"); @@ -969,8 +969,8 @@ static int toml_name(toml_table_t * table, if (skey.ok && cp_chk_path(info.s.key, skey.u.s) < 0) return -1; - cenc = toml_string_in(table, "client_enc_file"); - if (cenc.ok && cp_chk_path(info.c.enc, cenc.u.s) < 0) + csec = toml_string_in(table, "client_sec_file"); + if (csec.ok && cp_chk_path(info.c.sec, csec.u.s) < 0) return -1; ccrt = toml_string_in(table, "client_crt_file"); diff --git a/src/irmd/main.c b/src/irmd/main.c index 3519e079..c77355e7 100644 --- a/src/irmd/main.c +++ b/src/irmd/main.c @@ -488,8 +488,8 @@ static void name_update_sec_paths(struct name_info * info) assert(info != NULL); - if (strlen(info->s.enc) == 0) - sprintf(info->s.enc, "%s/%s/enc.conf", srv_dir, info->name); + if (strlen(info->s.sec) == 0) + sprintf(info->s.sec, "%s/%s/sec.conf", srv_dir, info->name); if (strlen(info->s.crt) == 0) sprintf(info->s.crt, "%s/%s/crt.pem", srv_dir, info->name); @@ -497,8 +497,8 @@ static void name_update_sec_paths(struct name_info * info) if (strlen(info->s.key) == 0) sprintf(info->s.key, "%s/%s/key.pem", srv_dir, info->name); - if (strlen(info->c.enc) == 0) - sprintf(info->c.enc, "%s/%s/enc.conf", cli_dir, info->name); + if (strlen(info->c.sec) == 0) + sprintf(info->c.sec, "%s/%s/sec.conf", cli_dir, info->name); if (strlen(info->c.crt) == 0) sprintf(info->c.crt, "%s/%s/crt.pem", cli_dir, info->name); diff --git a/src/irmd/oap/cli.c b/src/irmd/oap/cli.c index 113abc4c..b3d6d586 100644 --- a/src/irmd/oap/cli.c +++ b/src/irmd/oap/cli.c @@ -98,7 +98,7 @@ int load_cli_kex_config(const struct name_info * info, /* A client authenticates the server by default, like an https client */ cfg->req_auth = OAP_CLIENT_AUTH_DEFAULT; - return load_kex_config(info->name, info->c.enc, cfg); + return load_kex_config(info->name, info->c.sec, cfg); } int load_server_kem_pk(const char * name, diff --git a/src/irmd/oap/srv.c b/src/irmd/oap/srv.c index b92c1946..9ace8ed1 100644 --- a/src/irmd/oap/srv.c +++ b/src/irmd/oap/srv.c @@ -76,7 +76,7 @@ int load_srv_kex_config(const struct name_info * info, memset(cfg, 0, sizeof(*cfg)); /* Client auth stays opt-in (mTLS); enable with auth=required */ - return load_kex_config(info->name, info->s.enc, cfg); + return load_kex_config(info->name, info->s.sec, cfg); } int load_server_kem_keypair(const char * name, diff --git a/src/tools/irm/irm_name_create.c b/src/tools/irm/irm_name_create.c index 1055700c..40a51193 100644 --- a/src/tools/irm/irm_name_create.c +++ b/src/tools/irm/irm_name_create.c @@ -51,10 +51,10 @@ #define RR "round-robin" #define SPILL "spillover" -#define SENC "/server//enc.conf" +#define SSEC "/server//sec.conf" #define SCRT "/server//crt.pem" #define SKEY "/server//key.pem" -#define CENC "/client//enc.conf" +#define CSEC "/client//sec.conf" #define CCRT "/client//crt.pem" #define CKEY "/client//key.pem" @@ -63,10 +63,10 @@ static void usage(void) printf("Usage: irm name create\n" " . max %d chars.\n" " [lb LB_POLICY], default: %s\n" - " [sencpath , default: " SENC "]\n" + " [ssecpath , default: " SSEC "]\n" " [scrtpath , default: " SCRT "]\n" " [skeypath , default: " SKEY "]\n" - " [cencpath , default: " CENC "]\n" + " [csecpath , default: " CSEC "]\n" " [ccrtpath , default: " CCRT "]\n" " [ckeypath , default: " CKEY "]\n" "\n" @@ -105,10 +105,10 @@ int do_create_name(int argc, { struct name_info info = {}; char * name = NULL; - char * sencpath = NULL; + char * ssecpath = NULL; char * scrtpath = NULL; char * skeypath = NULL; - char * cencpath = NULL; + char * csecpath = NULL; char * ccrtpath = NULL; char * ckeypath = NULL; char * lb_pol = RR; @@ -119,14 +119,14 @@ int do_create_name(int argc, while (argc > 0) { if (matches(*argv, "lb") == 0) { lb_pol = *(argv + 1); - } else if (matches(*argv, "sencpath") == 0) { - sencpath = *(argv + 1); + } else if (matches(*argv, "ssecpath") == 0) { + ssecpath = *(argv + 1); } else if (matches(*argv, "scrtpath") == 0) { scrtpath = *(argv + 1); } else if (matches(*argv, "skeypath") == 0) { skeypath = *(argv + 1); - } else if (matches(*argv, "cencpath") == 0) { - cencpath = *(argv + 1); + } else if (matches(*argv, "csecpath") == 0) { + csecpath = *(argv + 1); } else if (matches(*argv, "ccrtpath") == 0) { ccrtpath = *(argv + 1); } else if (matches(*argv, "ckeypath") == 0) { @@ -151,7 +151,7 @@ int do_create_name(int argc, strcpy(info.name, name); - if (sencpath != NULL && cp_chk_path(info.s.enc, sencpath) < 0) + if (ssecpath != NULL && cp_chk_path(info.s.sec, ssecpath) < 0) goto fail; if (scrtpath != NULL && cp_chk_path(info.s.crt, scrtpath) < 0) @@ -160,7 +160,7 @@ int do_create_name(int argc, if (skeypath != NULL && cp_chk_path(info.s.key, skeypath) < 0) goto fail; - if (cencpath != NULL && cp_chk_path(info.c.enc, cencpath) < 0) + if (csecpath != NULL && cp_chk_path(info.c.sec, csecpath) < 0) goto fail; if (ccrtpath != NULL && cp_chk_path(info.c.crt, ccrtpath) < 0) -- cgit v1.2.3