From: Norbert Pocs Date: Thu, 8 Jan 2026 14:04:54 +0000 (+0100) Subject: Fix OCB AES-NI/HW stream path unauthenticated/unencrypted trailing bytes X-Git-Tag: openssl-3.0.19~7 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=52d23c86a54adab5ee9f80e48b242b52c4cc2347;p=thirdparty%2Fopenssl.git Fix OCB AES-NI/HW stream path unauthenticated/unencrypted trailing bytes When ctx->stream (e.g., AES‑NI or ARMv8 CE) is available, the fast path encrypts/decrypts full blocks but does not advance in/out pointers. The tail-handling code then operates on the base pointers, effectively reprocessing the beginning of the buffer while leaving the actual trailing bytes unencrypted (encryption) or using the wrong plaintext (decryption). The authentication checksum excludes the true tail. CVE-2025-69418 Fixes: https://github.com/openssl/srt/issues/58 Signed-off-by: Norbert Pocs Reviewed-by: Saša Nedvědický Reviewed-by: Eugene Syromiatnikov Reviewed-by: Tomas Mraz MergeDate: Mon Jan 26 19:48:35 2026 (cherry picked from commit be9375d5d45dfaf897b56ef148a0b58402491fcb) --- diff --git a/crypto/modes/ocb128.c b/crypto/modes/ocb128.c index 9d2d3a22781..2194a892325 100644 --- a/crypto/modes/ocb128.c +++ b/crypto/modes/ocb128.c @@ -341,7 +341,7 @@ int CRYPTO_ocb128_encrypt(OCB128_CONTEXT *ctx, if (num_blocks && all_num_blocks == (size_t)all_num_blocks && ctx->stream != NULL) { - size_t max_idx = 0, top = (size_t)all_num_blocks; + size_t max_idx = 0, top = (size_t)all_num_blocks, processed_bytes = 0; /* * See how many L_{i} entries we need to process data at hand @@ -355,6 +355,9 @@ int CRYPTO_ocb128_encrypt(OCB128_CONTEXT *ctx, ctx->stream(in, out, num_blocks, ctx->keyenc, (size_t)ctx->sess.blocks_processed + 1, ctx->sess.offset.c, (const unsigned char (*)[16])ctx->l, ctx->sess.checksum.c); + processed_bytes = num_blocks * 16; + in += processed_bytes; + out += processed_bytes; } else { /* Loop through all full blocks to be encrypted */ for (i = ctx->sess.blocks_processed + 1; i <= all_num_blocks; i++) { @@ -433,7 +436,7 @@ int CRYPTO_ocb128_decrypt(OCB128_CONTEXT *ctx, if (num_blocks && all_num_blocks == (size_t)all_num_blocks && ctx->stream != NULL) { - size_t max_idx = 0, top = (size_t)all_num_blocks; + size_t max_idx = 0, top = (size_t)all_num_blocks, processed_bytes = 0; /* * See how many L_{i} entries we need to process data at hand @@ -447,6 +450,9 @@ int CRYPTO_ocb128_decrypt(OCB128_CONTEXT *ctx, ctx->stream(in, out, num_blocks, ctx->keydec, (size_t)ctx->sess.blocks_processed + 1, ctx->sess.offset.c, (const unsigned char (*)[16])ctx->l, ctx->sess.checksum.c); + processed_bytes = num_blocks * 16; + in += processed_bytes; + out += processed_bytes; } else { OCB_BLOCK tmp;