summaryrefslogtreecommitdiff
path: root/src
Commit message (Collapse)AuthorAgeFilesLines
* ipcpd: Fix DHT bootstrap re-seedingDimitri Staessens2 days1-1/+45
| | | | | | | | | | The bootstrap seeder reported success as soon as the query was sent. Only skip seeding once the peer is in a bucket, and return -EAGAIN until it actually appears so the caller keeps retrying rather than assuming bootstrap completed. Signed-off-by: Dimitri Staessens <dimitri@ouroboros.rocks> Signed-off-by: Sander Vrijders <sander@ouroboros.rocks>
* ipcpd: Report eth socket egress queue in RIBDimitri Staessens2 days1-1/+7
| | | | | | | | Add the raw socket's SIOCOUTQ egress backlog to the eth RIB and relabel the existing FIONREAD RIB entry as ingress. Signed-off-by: Dimitri Staessens <dimitri@ouroboros.rocks> Signed-off-by: Sander Vrijders <sander@ouroboros.rocks>
* ipcpd: Minimize ipcpd-eth send bufferDimitri Staessens2 days1-6/+13
| | | | | | | | The eth send buffer needs to block quickly so we can mark congestion correctly in the upper layer buffers. Signed-off-by: Dimitri Staessens <dimitri@ouroboros.rocks> Signed-off-by: Sander Vrijders <sander@ouroboros.rocks>
* lib: Fix locking on flow readDimitri Staessens2 days1-9/+13
| | | | | | | | | | Reading a deallocated flow could cause an assert on a negative id. The raw-flow path now holds proc.lock across flow_rx_spb rather than dropping it first, and the FRCT loop no longer releases and reacquires the lock on every iteration. Signed-off-by: Dimitri Staessens <dimitri@ouroboros.rocks> Signed-off-by: Sander Vrijders <sander@ouroboros.rocks>
* lib: Prefer writers on the proc flow lockDimitri Staessens2 days1-4/+18
| | | | | | | | | | FRCT readers hold proc.lock in a rdlock loop and could starve a pending flow accept waiting for the wrlock. Initialise the lock with the writer-nonrecursive kind on Linux with glibc, so writers are not indefinitely delayed. Signed-off-by: Dimitri Staessens <dimitri@ouroboros.rocks> Signed-off-by: Sander Vrijders <sander@ouroboros.rocks>
* lib: Clean up on cancelled blocking readDimitri Staessens2 days2-4/+20
| | | | | | | | | Cancelling a thread that was blocked in ssm_rbuff_read_b/write_b didn't clean up the n_users reference. If it was in flow_rx_one it didn't unlock the process lock. Signed-off-by: Dimitri Staessens <dimitri@ouroboros.rocks> Signed-off-by: Sander Vrijders <sander@ouroboros.rocks>
* lib: Separate rekey replay from epoch conflictDimitri Staessens2 days3-16/+42
| | | | | | | | | | | | | keyrot_rekey() treated any re-key attempt against a live epoch (current or previous) the same way, whether the offered root key matched the live one (a replay) or was genuinely different (a conflict). Compare the offered key against the live batch's root and return -EREPLAY for a match, keeping -1/-ECRYPT for an actual conflict, so callers can handle replayed re-keys distinctly from real ones. Signed-off-by: Dimitri Staessens <dimitri@ouroboros.rocks> Signed-off-by: Sander Vrijders <sander@ouroboros.rocks>
* irmd: Move AUTH test macros to OAP common.hDimitri Staessens2 days3-25/+23
| | | | | | | | | | The ML-DSA OAP test defined CLI_AUTH/NO_CLI_AUTH and passed them for the srv_auth parameters of the re-key tests. Rename to the neutral AUTH/NO_AUTH already used by oap_test.c and move the pair to the shared common.h. Signed-off-by: Dimitri Staessens <dimitri@ouroboros.rocks> Signed-off-by: Sander Vrijders <sander@ouroboros.rocks>
* irmd: Test OAP KEM re-key floorDimitri Staessens2 days1-0/+126
| | | | | | | | | Add tests for two client-encap KEM properties the server enforces: reject a client KDF below the server floor, and confirm a re-key forces ephemeral server-encap. Signed-off-by: Dimitri Staessens <dimitri@ouroboros.rocks> Signed-off-by: Sander Vrijders <sander@ouroboros.rocks>
* irmd: Expand and parametrize OAP testsDimitri Staessens2 days4-182/+554
| | | | | | | | | | Parametrize the re-key roundtrips over the full (srv_auth, cli_auth) matrix. Add a KEM re-key axis, request-ID and cleartext-echo tamper tests, and an unsupported cipher/kdf/digest NID cluster guarded by an assertion. Signed-off-by: Dimitri Staessens <dimitri@ouroboros.rocks> Signed-off-by: Sander Vrijders <sander@ouroboros.rocks>
* lib: Harden crypto unit testsDimitri Staessens2 days3-5/+103
| | | | | | | | | | | | | | Stop the non-OpenSSL runners from masking a real failure as SKIP by only downgrading to SKIP if they passed. Fix a stray call that ran test_kex_dhe_wrong_algo in the skip branch. Fix double free + free of an uninitialised pointer in test_store_add. Test that a KDF- less derive must fail. Signed-off-by: Dimitri Staessens <dimitri@ouroboros.rocks> Signed-off-by: Sander Vrijders <sander@ouroboros.rocks>
* irmd: Fix OAP re-key header encodeDimitri Staessens2 days4-9/+27
| | | | | | | | | | | | | The oap_hdr_encode() function validated its own output by re-decoding with rekey hardcoded false. The case where the client signs a re-key failed its own self-check because the cert is not sent again. Now uses a flag on the encode() to signal the signed re-key without certificate. Also fixes a double free after a failed self-decode check. Signed-off-by: Dimitri Staessens <dimitri@ouroboros.rocks> Signed-off-by: Sander Vrijders <sander@ouroboros.rocks>
* lib: Reject re-key to a live epochDimitri Staessens2 days2-12/+177
| | | | | | | | A re-key epoch arrives from the peer, so we need to reject duplicates to avoid two batches sharing a wire epoch with different keys. Signed-off-by: Dimitri Staessens <dimitri@ouroboros.rocks> Signed-off-by: Sander Vrijders <sander@ouroboros.rocks>
* build: Fix OpenSSL version check for PQCDimitri Staessens2 days9-12/+10
| | | | | | | | | ML-KEM, ML-DSA and SLH-DSA all landed in OpenSSL 3.5.0, not 3.4.0. ML-KEM+ML-DSA and SLH-DSA can be disabled by DISABLE_ML / DISABLE_SLH. Signed-off-by: Dimitri Staessens <dimitri@ouroboros.rocks> Signed-off-by: Sander Vrijders <sander@ouroboros.rocks>
* build: Make re-key watermark configurableDimitri Staessens12 days2-51/+8
| | | | | | | | | | KEY_REKEY_WM_CHECK_BITS now controls the watermark check, once per 2^n flow writes (FLOW_WM_CHECK in dev.c). Now the configuration check (check watermark < outstanding packets) is contained in lib.cmake instead of assuming the value of FLOW_WM_CHECK. Signed-off-by: Dimitri Staessens <dimitri@ouroboros.rocks> Signed-off-by: Sander Vrijders <sander@ouroboros.rocks>
* lib: Wipe unpacked session key after copyDimitri Staessens12 days1-0/+4
| | | | | | | | | | Zeroize the symmetric key in the unpacked IRM message once it has been copied into the crypt context, in both flow__irm_result_des and flow_rekey__irm_result_des, so key material does not linger in the protobuf buffer until it is freed. Signed-off-by: Dimitri Staessens <dimitri@ouroboros.rocks> Signed-off-by: Sander Vrijders <sander@ouroboros.rocks>
* oap: Rename kex_config loaders to sec_configDimitri Staessens12 days8-130/+130
| | | | | | | | | | Leftover from the kex_config->enc_config->sec_config rename. Finished by renames load_kex_config and the cli/srv variants to load_sec_config, the kcfg variables to scfg, and fixes the "KEX config"/"encryption config" comments. Signed-off-by: Dimitri Staessens <dimitri@ouroboros.rocks> Signed-off-by: Sander Vrijders <sander@ouroboros.rocks>
* irmd: Harden OAP handshake and add cert-less re-keyDimitri Staessens12 days11-239/+1334
| | | | | | | | | | | | | | | | | | | | | | Adds support for: Server key confirmation: the session key is bound to the negotiated algorithm via the HKDF info. The server returns a key-confirmation tag (rsp_tag, replacing the bare request-hash echo), so a cipher downgrade or key desync is detected. The cleartext path keeps a request echo, compared in constant time. Sealed server identity: AEAD-seal the certificate, signature and piggybacked data in the encrypted response (kex and rsp_tag move ahead as AAD), hiding the server identity and response sizes. Cert-less re-key: let the client omit its certificate, verifying the peer against the cached certificate. On PQC flows, ephemeral server-encap KEX (preserving forward secrecy) is used, even if the original flow allocation was client-encap. Signed-off-by: Dimitri Staessens <dimitri@ouroboros.rocks> Signed-off-by: Sander Vrijders <sander@ouroboros.rocks>
* irmd: Reject unsupported OAP kex and cipherDimitri Staessens12 days1-2/+7
| | | | | | | | | Validate the configured key exchange and cipher against the supported ranks (returning ENOTSUP) instead of only rejecting an undefined cipher NID, so an unsupported algorithm is caught at config load. Signed-off-by: Dimitri Staessens <dimitri@ouroboros.rocks> Signed-off-by: Sander Vrijders <sander@ouroboros.rocks>
* lib: Bound crc_check against short packetsDimitri Staessens12 days1-2/+8
| | | | | | | | | Reject a packet shorter than head_skip + CRCLEN before computing the CRC, instead of hashing over an underflowed length when the buffer is too small to hold the trailer. Signed-off-by: Dimitri Staessens <dimitri@ouroboros.rocks> Signed-off-by: Sander Vrijders <sander@ouroboros.rocks>
* irmd: Complete bidirectional flow re-keyingDimitri Staessens12 days9-261/+1111
| | | | | | | | | | | | | | | | | | Extend re-key delivery beyond the locally-initiated watermark path: Handle peer-initiated re-key requests, allowing one request and one response per flow at a time. The client side wins if both ends try to re-key at the same time. Caches the peer certificate to support cert-less authenticated/signed re-keys. After a rekey, the initiator promotes first (timer) and starts sending under the new key. The responder observes the new key (peer_synced) and then the responder promotes. The responder will self-decide to use the new keys if it exhausted the older set in the case where it never sees the peer (unidirectional flow). Signed-off-by: Dimitri Staessens <dimitri@ouroboros.rocks> Signed-off-by: Sander Vrijders <sander@ouroboros.rocks>
* lib: Add constant-time comparison helperDimitri Staessens12 days1-0/+19
| | | | | | | | | Add a function crypt_ct_cmp() that wraps CRYPTO_memcmp (OpenSSL) with a volatile-loop fallback, for comparing authentication tags without leaking timing. Signed-off-by: Dimitri Staessens <dimitri@ouroboros.rocks> Signed-off-by: Sander Vrijders <sander@ouroboros.rocks>
* lib: Group sec_config authentication fieldsDimitri Staessens12 days6-26/+26
| | | | | | | | | Nest the flat req_auth and cacert members of struct sec_config into a sub-struct a { req; cacert; }, keeping the authentication settings together. Signed-off-by: Dimitri Staessens <dimitri@ouroboros.rocks> Signed-off-by: Sander Vrijders <sander@ouroboros.rocks>
* config: Rename enc.conf to sec.confDimitri Staessens12 days6-27/+27
| | | | | | | | | 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 <dimitri@ouroboros.rocks> Signed-off-by: Sander Vrijders <sander@ouroboros.rocks>
* lib: Harden OpenSSL crypto backendDimitri Staessens12 days2-69/+99
| | | | | | | | | | | | | | | This contains a few improvements and fixes in the OpenSSL backed. We now zeroize shared secrets with OPENSSL_clear_free. The i2d_PUBKEY output is bound against CRYPT_KEY_BUFSZ. We now return NULL rather than silently falling back to SHA-256 when a digest is unknown. FILE handles are now closed via pthread cleanup so a cancelled thread cannot leak them. The DHE kex tests now set the KDF NID explicitly, since the SHA-256 fallback is gone. Also refactors the PEM string loaders to clean up some code duplication. Signed-off-by: Dimitri Staessens <dimitri@ouroboros.rocks> Signed-off-by: Sander Vrijders <sander@ouroboros.rocks>
* lib: Loop getrandom on short reads and EINTRDimitri Staessens12 days1-1/+17
| | | | | | | | | The getrandom() function may return fewer bytes than requested or fail with EINTR. Loop until the buffer is filled, retrying on EINTR, instead of trusting a single call to fill the buffer completely. Signed-off-by: Dimitri Staessens <dimitri@ouroboros.rocks> Signed-off-by: Sander Vrijders <sander@ouroboros.rocks>
* ipcpd: Use hash_mix64 for pft keysDimitri Staessens12 days6-32/+7
| | | | | | | | | Drops the per-table hash_key flag and the local MD5 hash() helper. The calc_key function now folds the key with hash_mix64 unconditionally. Simplifies pft_create, which no longer takes a bool. Signed-off-by: Dimitri Staessens <dimitri@ouroboros.rocks> Signed-off-by: Sander Vrijders <sander@ouroboros.rocks>
* lib: Add MurmurHash3 hash_mix64 for hash tablesDimitri Staessens12 days2-0/+50
| | | | | | | | | Adds a (non-cryptographic) MurmurHash3 fmix64 finalizer for hashing an integer key to a table index, replacing the MD5-based bucket hashing in the pft. Signed-off-by: Dimitri Staessens <dimitri@ouroboros.rocks> Signed-off-by: Sander Vrijders <sander@ouroboros.rocks>
* irmd: Deliver flow re-keyingDimitri Staessens12 days11-106/+1269
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | Re-key each encrypted flow's batch root periodically so a long-lived flow never exhausts or over-uses a single root. The IRMd re-runs the OAP exchange with the peer IRMd over the flow-update relay. The per-flow re-keying state is tracked in the registry (reg_flow). A re-key delivers one root seed from the OAP exchange. keyrot immediately HKDF-expands it into 128 node keys (KR_NODES_SZ = 128 × 32 B) and wipes the root. Then each of the 128 node keys is itself a root → HKDF-expanded into 64 (2^KEY_NODE_BITS) leaf keys, forked per direction; each leaf key is the actual AEAD key, good for 2^20 packets (the low counter bits are its nonce/seq). If the number of keys runs low, a re-key will be triggered (KEY_REKEY_WATERMARK). The rekey is signalled out of band to the application. The rbuff ACL is generalized into a flags word, so an RB_REKEY bit rides alongside the access RB_RD/RB_WR and FLOWDOWN/FLOWPEER bits. The RD and WR bits are revised ditching the fcntl historical weirdness. The seed is pulled via flow_read/flow_write, installed with crypt_rekey(). TX holds the old epoch until the peer is observed on the new one (or a grace deadline elapses), promoted from both the read and write paths so a recv-mostly flow still advances. Also fix the FLOW_ACCEPT and FLOW_ALLOC handlers, which on a key-buffer allocation failure returned from inside the cleanup-push region: that leaked the reply message and skipped both the stack-key scrub and the cleanup pop. Signed-off-by: Dimitri Staessens <dimitri@ouroboros.rocks> Signed-off-by: Sander Vrijders <sander@ouroboros.rocks>
* ipcpd: Add flow-update relayDimitri Staessens12 days14-7/+483
| | | | | | | | | | | | This adds an ipcp_flow_update() call to relay opaque messages between the two IRMds (carried by FLOW_IRM_UPDATE messages), which passes it back up to the peer IRMd via ipcp_flow_update_arr(). The broadcast layer does not implement this. Needed for periodic re-keying of encrypted flows via OAP. Signed-off-by: Dimitri Staessens <dimitri@ouroboros.rocks> Signed-off-by: Sander Vrijders <sander@ouroboros.rocks>
* lib: Harden symmetric-key rotationDimitri Staessens12 days12-523/+2752
| | | | | | | | | | | | | | | | | | Flow crypto signalled rotation with a single phase-parity bit, so a loss burst that hid an even number of rotations went unnoticed and wedged the flow for good. Each packet now carries a small cleartext selector naming its key directly, so a receiver that falls behind recovers on the next packet instead of getting stuck. The selector also serves as the AEAD nonce and is authenticated as associated data (AAD). Key rotation moves into a new backend-agnostic keyrot module that rotates sub-keys to bound AEAD usage while preserving forward secrecy. Signed-off-by: Dimitri Staessens <dimitri@ouroboros.rocks> Signed-off-by: Sander Vrijders <sander@ouroboros.rocks>
* irmd: Fail OAP config load on read errorsDimitri Staessens12 days2-4/+15
| | | | | | | | | | | load_sec_config_file() treated any fopen() failure as an absent config and silently disabled encryption. file_exists() similarly lumped non-ENOENT stat() errors in with "present". Signed-off-by: Dimitri Staessens <dimitri@ouroboros.rocks> Signed-off-by: Sander Vrijders <sander@ouroboros.rocks>
* irmd: Bound the OAP replay cacheDimitri Staessens12 days3-54/+263
| | | | | | | | | | | | | | | | | Replace the linked-list cache with three timestamp-generation hash buckets, each capped at OAP_REPLAY_MAX entries. A bucket is an open-addressed hash set whose slots count as live only while slot.gen equals the bucket generation, so a stale bucket clears in O(1) by bumping its generation instead of being scanned and pruned. On overflow the cache fails closed - it rejects the header rather than evicting the oldest entry. Under flood, dropping a genuine entry would let that header be replayed, so refusing new entries is the safer degradation than evict-oldest (fail-open) behaviour. Signed-off-by: Dimitri Staessens <dimitri@ouroboros.rocks> Signed-off-by: Sander Vrijders <sander@ouroboros.rocks>
* irmd: Reject OAP peer crt with unusable CNDimitri Staessens12 days4-43/+100
| | | | | | | Added checks for CN > NAME_SIZE. Signed-off-by: Dimitri Staessens <dimitri@ouroboros.rocks> Signed-off-by: Sander Vrijders <sander@ouroboros.rocks>
* irmd: Add issuer and digest pinning to OAPDimitri Staessens12 days16-45/+654
| | | | | | | | | | | | | | | | | | | A peer certificate that verifies against the CA store could have been issued by any trusted CA, and a peer could pick any supported digest for its signature. Tighten the authentication contract with two local policies. cacert= pins the issuing CA: a peer certificate, if presented, must chain through the pinned CA. Whether a certificate is mandatory at all remains controlled by auth= alone. digest= now also pins the signature digest: a classical peer must sign with the locally configured digest, and may not omit the digest NID to fall back to the key's default digest. PQC signatures (ML-DSA, SLH-DSA) have an intrinsic digest and may be NID_undef. Signed-off-by: Dimitri Staessens <dimitri@ouroboros.rocks> Signed-off-by: Sander Vrijders <sander@ouroboros.rocks>
* irmd: Specify peer authentication contractDimitri Staessens12 days9-12/+449
| | | | | | | | | | | | | | | | | | | | | | 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 <dimitri@ouroboros.rocks> Signed-off-by: Sander Vrijders <sander@ouroboros.rocks>
* lib: Fix SSM reclaim-orphans testDimitri Staessens12 days1-1/+9
| | | | | | | | Age the simulated-leaked blocks via alloc_ts so the aged-reclaim triggers in the test. Signed-off-by: Dimitri Staessens <dimitri@ouroboros.rocks> Signed-off-by: Sander Vrijders <sander@ouroboros.rocks>
* ipcpd: Refactor dt statsDimitri Staessens2026-06-031-104/+47
| | | | | | | | Use relaxed atomics in hot path to bump stats via dt_stat_inc/dt_stat_load. Signed-off-by: Dimitri Staessens <dimitri@ouroboros.rocks> Signed-off-by: Sander Vrijders <sander@ouroboros.rocks>
* lib: Reclaim aged leaked ssm pool blocksDimitri Staessens2026-06-032-8/+34
| | | | | | | | | | | The reclaim_pid_from_sc() function reaped any block allocated with refcount from a dead PID, but cross-process hand-offs can leave a block briefly allocated by the producer while a live consumer still holds it. This skips reclaim within SSM_POOL_RECLAIM_AGE_S (default 60s) so in-flight hand-offs survive a producer crash. Signed-off-by: Dimitri Staessens <dimitri@ouroboros.rocks> Signed-off-by: Sander Vrijders <sander@ouroboros.rocks>
* lib: Fix overflow in ssm_flow_set_notifyDimitri Staessens2026-06-031-5/+13
| | | | | | | | | | ssm_flow_set_notify wrote past the fqueue because of a missing bound check, corrupting adjacent memory under burst. Drop redundant FLOW_PKT when full and reserve the last slot for control events so they aren't starved by data-plane traffic. Signed-off-by: Dimitri Staessens <dimitri@ouroboros.rocks> Signed-off-by: Sander Vrijders <sander@ouroboros.rocks>
* lib: Send stream FIN in the windowDimitri Staessens2026-06-011-0/+16
| | | | | | | | The stream FIN was not gated on the flow control window, potentially causing a seqno overrun if the windows was full. Signed-off-by: Dimitri Staessens <dimitri@ouroboros.rocks> Signed-off-by: Sander Vrijders <sander@ouroboros.rocks>
* lib: Fix missing newlines in hash.cDimitri Staessens2026-06-011-0/+2
| | | | | Signed-off-by: Dimitri Staessens <dimitri@ouroboros.rocks> Signed-off-by: Sander Vrijders <sander@ouroboros.rocks>
* lib: Fix FRCT seqno leak on rxm alloc failureDimitri Staessens2026-06-011-41/+50
| | | | | | | | | | | | | | The seqno was committed before calling rxm_arm, whose malloc could fail and silently leave the seqno without a retransmission entry. None of the recovery paths (RTO timer, RACK, SACK-driven, NACK-driven) can repair a slot with NULL rxm, so the gap persists until the receiver's keepalive marks the flow dead. This fix splits rxm_arm into rxm_alloc plus rxm_arm (post-state install). sack_rxm_snd follows the same alloc-then-arm shape. Signed-off-by: Dimitri Staessens <dimitri@ouroboros.rocks> Signed-off-by: Sander Vrijders <sander@ouroboros.rocks>
* lib: Fix double pool_remove on tx-path failureDimitri Staessens2026-06-011-6/+10
| | | | | | | | | | | | | | | | The flow_tx_spb function consumed the spb on every failure path via ssm_pool_remove, while its caller ipcp_flow_write left the spb to its caller on early outs, causing ssm_pool_remove to be called twice. In Debug builds this aborts at the old_ref == 0 check. This aligns flow_tx_spb with np1_flow_write and dt_write_packet: spb consumed on success, retained on failure. External callers already release on failure, so no caller-side changes outside of dev.c are needed. Signed-off-by: Dimitri Staessens <dimitri@ouroboros.rocks> Signed-off-by: Sander Vrijders <sander@ouroboros.rocks>
* ipcpd: Fully gate fa/dt RIB ops on IPCP_FLOW_STATStestingDimitri Staessens2026-05-272-38/+20
| | | | | | | | | | | | | The previous shape registered no-op _rib_read / _rib_readdir / _rib_getattr handlers when IPCP_FLOW_STATS was off, and there was a bug where *buf was not set in the no-op causing free on an uninitialized pointer. IPCP_FLOW_STATS was referenced by config.h.in but the declaration was lost during the CMake refactor. Signed-off-by: Dimitri Staessens <dimitri@ouroboros.rocks> Signed-off-by: Sander Vrijders <sander@ouroboros.rocks>
* ipcpd: Drain mainloop before component shutdownDimitri Staessens2026-05-272-3/+4
| | | | | | | | Worker mid fa_dealloc could still try to read from fa.psched because stop_components() ran before ipcp_stop()/tpm_stop(). Signed-off-by: Dimitri Staessens <dimitri@ouroboros.rocks> Signed-off-by: Sander Vrijders <sander@ouroboros.rocks>
* ipcpd: Close dt stat_used race vs rib readdirDimitri Staessens2026-05-271-4/+8
| | | | | | | | | | The stat_used function updated dt.stat[fd].stamp under the per-stat mutex, released it, then took dt.lock wrlock to bump dt.n_flows. A concurrent dt_rib_readdir holding dt.lock rdlock between those two critical sections saw the new stamp but the old n_flows. Signed-off-by: Dimitri Staessens <dimitri@ouroboros.rocks> Signed-off-by: Sander Vrijders <sander@ouroboros.rocks>
* irmd: Reorder init/finiDimitri Staessens2026-05-271-10/+19
| | | | | | | | | Application-level OpenSSL objects (X509_STORE held by irm/OAP) must be released before OPENSSL_cleanup() tears down libcrypto's globals, otherwise their destructors run against half-finalised state. Signed-off-by: Dimitri Staessens <dimitri@ouroboros.rocks> Signed-off-by: Sander Vrijders <sander@ouroboros.rocks>
* ipcpd: Fix eth double-release in MGMT rx pathDimitri Staessens2026-05-271-2/+2
| | | | | | | | The MGMT-frame branch in eth_ipcp_packet_reader releases the spb at the top of the loop iteration; two error exits released a second time. Signed-off-by: Dimitri Staessens <dimitri@ouroboros.rocks> Signed-off-by: Sander Vrijders <sander@ouroboros.rocks>
* lib: Fix mixed declarations in hash.cDimitri Staessens2026-05-271-3/+4
| | | | | | | | The contexts are not declared at the top of the function anymore after addition of the CRC8/CRC16 variants (no implementation in libgcrypt). Signed-off-by: Dimitri Staessens <dimitri@ouroboros.rocks> Signed-off-by: Sander Vrijders <sander@ouroboros.rocks>