Add TLS 1.3 transport with PQC hybrid key exchange#526
Conversation
Add --enable-tls build option (OpenSSL >= 3.5), client-side TLS config parsing, and TLS transport to the audisp-remote plugin. The transport uses TLS 1.3 with X25519MLKEM768 hybrid key exchange for post-quantum confidentiality, with classical X25519 fallback when PQC groups are unavailable. The tls_require_pqc option enables fail-closed PQC enforcement via an allowlist in common/common.h. Both PSK and certificate-based authentication are supported. Server certificate verification is gated on tls_ca_file presence, with hostname/IP-aware SNI handling per RFC 6066. Session resumption and 0-RTT are disabled to force fresh key exchange per connection. Shared TLS helpers (is_pqc_group, tls_validate_key_file, tls_load_psk) are placed in common/common.h with a log callback to avoid code duplication with the server side. Assisted-by: Claude Opus 4.6 Signed-off-by: Sergio Correia <scorreia@redhat.com>
Add server-side TLS config parsing and transport to auditd for receiving audit events over encrypted connections. Mirrors the client-side TLS implementation with the same crypto defaults: TLS 1.3 minimum, X25519MLKEM768 hybrid key exchange, session resumption disabled. Adds tls_client_auth for optional or required mutual TLS with client certificates. PSK identity comparison uses CRYPTO_memcmp. Identity logging is sanitized to ASCII printable range. TLS config strings are freed during SIGHUP reconfigure to prevent leaks. Assisted-by: Claude Opus 4.6 Signed-off-by: Sergio Correia <scorreia@redhat.com>
Add test-tls.sh covering PSK and certificate handshakes, PQC key exchange negotiation, and binary linkage checks. Hardened with set -euo pipefail and dynamic port allocation. Document all TLS config options in both man pages, including PQC posture differences between PSK and certificate modes, certificate chain support, and SIGHUP reload limitations. Assisted-by: Claude Opus 4.6 Signed-off-by: Sergio Correia <scorreia@redhat.com>
The blocking SSL_accept held the single-threaded libev event loop for up to 5 seconds per connection, allowing a slow or malicious client to stall audit event processing for all connected clients. Replace it with a non-blocking state machine driven by ev_io and ev_timer callbacks. Pre-handshake clients live in a separate chain with a concurrency limit to prevent connection flooding. Per-address counting walks both chains so a single IP cannot exhaust the global handshake pool. Also fixes a config pointer scope bug where tls_require_pqc referenced an out-of-scope variable in the accept handler. Assisted-by: Claude Opus 4.6 Signed-off-by: Sergio Correia <scorreia@redhat.com>
|
Hello, thanks for taking this on. I have a road map for the audit project and this is on that roadmap in addition to requirements this needed to meet. This is also identified as the highest priority missing piece in the whole project. So, this is timely and needed. It will take a me a couple days to get to this. I don't know of anything in flight that would affect this area of the code. So, it should be stable to let this sit during review. What I'd like to do is mirror your PR branch and overlay that with the project requirements to see if there are any missing requirements and look for issues in the PR's implementation of the requirements. So...give me a couple days and I'll get back on this. |
|
Sure thing, thanks for looking into this. |
|
Hello, I think I am ready for the feedback. This is going to be a big dump of information. I am going to post our TLS specification to the other specifications. This is about a 7 phase project. This patch represents Phase 0. This is a summary of the technical requirements needed for Phase 0 (actual details to follow separately):
In terms of the code in this patch, here is the implementation cleanups needed: A. Configure Probes Are Too Weak
Add configure-time feature probes for the APIs actually used. Where provider configuration can change runtime availability, keep runtime failure paths too. This matters because vendors backport APIs unevenly and because the code currently advertises OpenSSL 1.1.1 support while using APIs that may not exist on every supported target. B. OpenSSL Return Values Are IgnoredExamples:
The code calls setters for protocol version, early data, tickets, and session cache behavior without checking whether the calls succeeded. At least the profile-critical settings should fail closed with a clear error if OpenSSL rejects them. C. PSK Secrets Can Survive Failed Context InitializationExamples:
Move cleanup into the error paths or build into temporary local state and only publish global pointers after the whole TLS context is valid. D. TLS Helper Code Needs Its Own Internal Library
This code is TLS-specific, not general common utility code. It is currently used by auditd and The better shape is a small internal TLS library, for example: with a non-installed libtool target: Then link Only role-neutral helpers belong in E. New Functions Need Kernel-Style Function CommentsThe project instructions require a comment before any new function describing the function, input variables, and return codes. Many new TLS functions have only short topic comments or no function header comment, for example:
Add concise function comments that explain purpose, inputs, and return values. OpenSSL callback signatures are allowed to exceed the "avoid more than four arguments" preference because the signature is externally defined. F. Add glibc function attributes to aid problem detectionWhere the shared int autls_validate_key_file(const char *path, autls_log_fn log_fn)
__nonnull((1, 2)) __wur;
int autls_load_psk(const char *path, unsigned char **key, size_t *key_len,
autls_log_fn log_fn)
__nonnull((1, 2, 3, 4)) __wur;
int autls_ssl_write(SSL *ssl, const void *buf, int len, int timeout_ms)
__nonnull((1, 2)) __attr_access ((__read_only__, 2, 3)) __wur;
int autls_identity_valid(const char *identity)
__nonnull((1)) __attribute_pure__ __wur;For allocation-style APIs, prefer a typed object and matching free routine so the compiler can check ownership: struct autls_psk *autls_psk_load_file(const char *path, autls_log_fn log_fn)
__nonnull((1, 2))
__attribute_malloc__
__attr_dealloc(autls_psk_free, 1)
__wur;
void autls_psk_free(struct autls_psk *psk);Use G. Non-ASCII Characters In CommentsThe branch introduces em dashes in comments:
Use ASCII comments. This matches the repository's C style expectations. I'll try to find another way to provide the actual details of the technical requirements. |
|
The full TLS requirements can be found here: The overall delivery plan broken down into phases: The details of phase 0, which represents a robust protoype, can be found here: |
Adds encrypted transport for remote audit logging using TLS 1.3 with X25519MLKEM768 hybrid key exchange (OpenSSL >= 3.5). Supports PSK and certificate authentication (mutually exclusive). Session resumption and 0-RTT disabled to force fresh PQC key exchange per connection.
New config options: tls_cert_file, tls_key_file, tls_ca_file, tls_psk_file, tls_psk_identity, tls_cipher_suites, tls_key_exchange, tls_require_pqc, tls_client_auth (server only).