Fedora Account System
Red Hat Associate
Red Hat Customer
AI_ONLY_REPORT package: libkcapi-1.5.0-3.el10 ------ Summary: IV Reuse in Symmetric Cipher Chunking: large one-shot symmetric cipher operations can resend the original IV for each internal chunk, restarting cipher state and breaking expected continuous-message behavior. Requirements to exploit: An attacker must be able to make an application using `libkcapi-1.5.0-3.el10` call the one-shot symmetric cipher APIs on data larger than `sysconf(_SC_PAGESIZE) * ALG_MAX_PAGES` (typically 64 KiB) in an affected stateful mode such as `ctr` or `cbc`, and observe the resulting ciphertext or decryption behavior. Reachability depends on the consuming application; the available evidence does not establish that every deployment exposes this path. Component affected: `libkcapi-1.5.0-3.el10`, `lib/kcapi-sym.c`, `lib/kcapi-kernel-if.c`, one-shot symmetric cipher path (`kcapi_cipher_encrypt`, `kcapi_cipher_decrypt`, `_kcapi_cipher_crypt_chunk`, `_kcapi_common_send_meta`) Version affected: `libkcapi-1.5.0-3.el10` Patch available: no released package fix established; proposed patch included below Version fixed: unknown Upstream coordination: Not notified. CVSS: CVSS:3.1/AV:N/AC:H/PR:N/UI:N/S:U/C:H/I:L/A:N - 6.8 (MEDIUM) AV:N - In the worst-case deployment, a remote caller can trigger the affected one-shot API through a network-facing application that uses this library for large-buffer encryption or decryption. AC:H - Exploitation depends on specific application behavior: the one-shot path must be used, the input must cross the internal chunk threshold, and the mode must be one whose security depends on continuous IV/chaining state. PR:N - No privileges are inherent to the flaw itself. UI:N - No user interaction is required once the application processes the crafted large input. S:U - The impact remains within the vulnerable cryptographic operation and does not cross a separate security boundary. C:H - For `ctr`, restarting the keystream at chunk boundaries can expose plaintext relationships and materially weaken confidentiality. I:L - Resetting state across chunk boundaries can cause applications to process data with different cryptographic semantics than a continuous message, which can affect integrity expectations in some uses. A:N - No direct availability impact is established from the available evidence. Impact: Moderate. Based on Red Hat severity guidance, this flaw can cause a meaningful confidentiality loss or cryptographic semantic break in applications that use the affected large-buffer one-shot path, but exploitation depends on specific API usage patterns and affected modes rather than presenting an easily exploitable default remote compromise path in this SRPM package. Embargo: no Reason: The currently supported impact is use-dependent, practical mitigations exist, and the available evidence does not show an easily weaponized default exposure that would normally justify embargo handling. Acknowledgement: Aisle Research Vulnerability Details: The one-shot symmetric cipher entry points store the caller-provided IV once and then pass the request into `_kcapi_cipher_crypt_chunk()`. For inputs larger than `handle->pagesize * ALG_MAX_PAGES`, `_kcapi_cipher_crypt_chunk()` splits the request into multiple chunks and calls `_kcapi_cipher_crypt()` for each chunk. Each `_kcapi_cipher_crypt()` call sends fresh operation metadata, and `_kcapi_common_send_meta()` copies `handle->cipher.iv` into `ALG_SET_IV` every time. No IV advancement is visible between chunks, so each chunk is processed as a new operation with the same IV instead of as a continuation of one message. ```c handle->cipher.iv = iv; return _kcapi_cipher_crypt_chunk(handle, in, inlen, out, outlen, access, ALG_OP_ENCRYPT /* or DECRYPT */); ``` ```c while (inlen && outlen) { ... ret = _kcapi_cipher_crypt(handle, in, inprocess, out, outprocess, access, enc); ... } ``` ```c if (handle->cipher.iv) { ... memcpy(alg_iv->iv, handle->cipher.iv, tfm->info.ivsize); } ``` For `ctr`, this restarts the keystream at each chunk boundary and can expose plaintext relationships across chunks. For `cbc`, the chaining value is reset at each boundary, so large one-shot processing no longer matches the behavior of one continuous CBC message. Based on the available evidence, this report is limited to the one-shot symmetric cipher path described above. Steps to reproduce: 1. Initialize a `ctr(aes)` handle and set the key. 2. Prepare `131072` bytes of plaintext, with block `0` identical to the block at offset `65536`. 3. Encrypt the buffer with the one-shot API `kcapi_cipher_encrypt()` using a fixed IV. 4. Encrypt the same plaintext as one continuous message using `kcapi_cipher_stream_init_enc()`, repeated `kcapi_cipher_stream_update()`, `kcapi_cipher_stream_update_last()`, and `kcapi_cipher_stream_op()`. 5. Compare the outputs. The observed condition is `out_oneshot != out_stream`, even though both operations are intended to represent the same continuous-message semantics. 6. For `ctr(aes)`, verify that `out_oneshot[0:16] == out_oneshot[65536:65552]` when the corresponding plaintext blocks are equal. This indicates keystream restart at the chunk boundary. 7. Repeat with `cbc(aes)` and observe a mismatch versus the continuous-stream result at the chunk boundary. Mitigation: Until a fix is available, avoid using the one-shot symmetric cipher APIs for inputs larger than `sysconf(_SC_PAGESIZE) * ALG_MAX_PAGES` when continuous-message semantics matter. Prefer the streaming interface for long messages, or keep one-shot inputs below the internal chunking threshold so the IV is applied only once per operation. Proposed Fix: Send operation metadata and IV only for the first internal chunk, then keep the AF_ALG operation open and send only data for subsequent chunks so cipher state is preserved across the full message. ```diff diff --git a/lib/kcapi-kernel-if.c b/lib/kcapi-kernel-if.c @@ ssize_t _kcapi_cipher_crypt_chunk(struct kcapi_handle *handle, const uint8_t *in, size_t inlen, uint8_t *out, size_t outlen, int access, unsigned int enc) { + bool first = true; ssize_t totallen = 0; @@ while (inlen && outlen) { size_t inprocess = inlen; size_t outprocess = outlen; + bool last; + struct iovec iov; @@ if (inlen > maxprocess) inprocess = maxprocess; if (outlen > maxprocess) outprocess = maxprocess; + last = (inlen <= maxprocess); ret = _kcapi_cipher_crypt(handle, in, inprocess, out, outprocess, access, enc); + if (first) { + if ((access == KCAPI_ACCESS_HEURISTIC && inprocess <= (1<<13)) || + access == KCAPI_ACCESS_SENDMSG) { + iov.iov_base = (void *)(uintptr_t)in; + iov.iov_len = inprocess; + ret = _kcapi_common_send_meta(handle, &iov, 1, enc, last ? 0 : MSG_MORE); + } else { + ret = _kcapi_common_send_meta(handle, NULL, 0, enc, MSG_MORE); + if (ret >= 0) + ret = _kcapi_common_vmsplice_chunk(handle, in, inprocess, + last ? 0 : SPLICE_F_MORE); + } + first = false; + } else { + if ((access == KCAPI_ACCESS_HEURISTIC && inprocess <= (1<<13)) || + access == KCAPI_ACCESS_SENDMSG) { + iov.iov_base = (void *)(uintptr_t)in; + iov.iov_len = inprocess; + ret = _kcapi_common_send_data(handle, &iov, 1, last ? 0 : MSG_MORE); + } else { + ret = _kcapi_common_vmsplice_chunk(handle, in, inprocess, + last ? 0 : SPLICE_F_MORE); + } + } if (ret < 0) return ret; + ret = _kcapi_common_read_data(handle, out, outprocess); + if (ret < 0) + return ret; @@ } return totallen; } ``` ------ This report was generated using AI technology. Always review AI-generated content prior to use