Script 'mail_helper' called by obssrc Hello community, here is the log from the commit of package mbedtls-2 for openSUSE:Factory checked in at 2026-09-15 12:49:00 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Comparing /work/SRC/openSUSE:Factory/mbedtls-2 (Old) and /work/SRC/openSUSE:Factory/.mbedtls-2.new.383539 (New) ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Package is "mbedtls-2" Tue Sep 15 12:49:00 2026 rev:13 rq:1378063 version:2.28.10 Changes: -------- --- /work/SRC/openSUSE:Factory/mbedtls-2/mbedtls-2.changes 2026-06-22 17:33:45.938840371 +0200 +++ /work/SRC/openSUSE:Factory/.mbedtls-2.new.383539/mbedtls-2.changes 2026-09-15 12:49:13.755955854 +0200 @@ -1,0 +2,15 @@ +Tue Sep 15 05:00:15 UTC 2026 - Martin Pluskal <[email protected]> + +- CVE-2025-52496: race condition in AESNI support detection, AES key + disclosure / GCM forgery in multithreaded programs (boo#1245810) + * Add mbedtls-fix-CVE-2025-52496.patch: backport upstream fix + +------------------------------------------------------------------- +Mon Sep 14 17:22:23 UTC 2026 - Martin Pluskal <[email protected]> + +- CVE-2025-59438: padding oracle through timing of cipher error + reporting (boo#1252454) + * Add mbedtls-fix-CVE-2025-59438.patch: backport upstream 3.6 fix +- Spec cleanup (spec-cleaner): drop obsolete Group tags + +------------------------------------------------------------------- New: ---- mbedtls-fix-CVE-2025-52496.patch mbedtls-fix-CVE-2025-59438.patch ----------(New B)---------- New: disclosure / GCM forgery in multithreaded programs (boo#1245810) * Add mbedtls-fix-CVE-2025-52496.patch: backport upstream fix New: reporting (boo#1252454) * Add mbedtls-fix-CVE-2025-59438.patch: backport upstream 3.6 fix - Spec cleanup (spec-cleaner): drop obsolete Group tags ----------(New E)---------- ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Other differences: ------------------ ++++++ mbedtls-2.spec ++++++ --- /var/tmp/diff_new_pack.YSYhPP/_old 2026-09-15 12:49:14.661993624 +0200 +++ /var/tmp/diff_new_pack.YSYhPP/_new 2026-09-15 12:49:14.663993707 +0200 @@ -25,18 +25,21 @@ Release: 0 Summary: Libraries for crypto and SSL/TLS protocols License: Apache-2.0 OR GPL-2.0-or-later -Group: Development/Libraries/C and C++ URL: https://tls.mbed.org Source: https://github.com/ARMmbed/mbedtls/archive/v%{version}.tar.gz#/%{_rname}-%{version}.tar.gz Source99: baselibs.conf +# PATCH-FIX-UPSTREAM: Fix build with gcc15 +Patch0: mbedtls-fix-build-with-gcc-15.patch +# PATCH-FIX-UPSTREAM: mbedtls-fix-CVE-2025-59438.patch boo#1252454 -- fix padding oracle through timing of cipher error reporting (CVE-2025-59438, upstream 3.6 commits 155de2ab/d179dc80/e74b4283/3b380dae/04dfd704/cc908ad0) +Patch1: mbedtls-fix-CVE-2025-59438.patch +# PATCH-FIX-UPSTREAM: mbedtls-fix-CVE-2025-52496.patch boo#1245810 -- fix race condition in AESNI support detection (CVE-2025-52496, upstream commit 8c67ac0f) +Patch2: mbedtls-fix-CVE-2025-52496.patch BuildRequires: cmake BuildRequires: ninja BuildRequires: pkgconfig BuildRequires: pkgconfig(libpkcs11-helper-1) BuildRequires: pkgconfig(zlib) %{?suse_build_hwcaps_libs} -# PATCH-FIX-UPSTREAM: Fix build with gcc15 -Patch0: mbedtls-fix-build-with-gcc-15.patch %description mbedtls implements the SSL3, TLS 1.0, 1.1 and 1.2 protocols. It @@ -49,7 +52,6 @@ %package -n %{lib_tls} Summary: Transport Layer Security protocol suite -Group: System/Libraries %description -n %{lib_tls} mbedtls implements the SSL 3.0, TLS 1.0, 1.1 and 1.2 protocols. It @@ -62,7 +64,6 @@ %package -n %{lib_crypto} Summary: Cryptographic base library for mbedtls -Group: System/Libraries %description -n %{lib_crypto} This subpackage of mbedtls contains a library that exposes @@ -71,7 +72,6 @@ %package -n %{lib_x509} Summary: Library to work with X.509 certificates -Group: System/Libraries %description -n %{lib_x509} This subpackage of mbedtls contains a library that can read, verify @@ -80,7 +80,6 @@ %package devel Summary: Development files for mbedtls, a SSL/TLS library -Group: Development/Libraries/C and C++ Requires: %{lib_crypto} = %{version} Requires: %{lib_tls} = %{version} Requires: %{lib_x509} = %{version} ++++++ mbedtls-fix-CVE-2025-52496.patch ++++++ Subject: Fix race condition in AESNI support detection (CVE-2025-52496) Patch-mainline: Backport of upstream commit 8c67ac0f7f8863e60714f16513b4d420c764c093 References: https://github.com/Mbed-TLS/mbedtls/commit/8c67ac0f7f8863e60714f16513b4d420c764c093 https://github.com/Mbed-TLS/mbedtls/issues/9840 Backport the upstream fix for CVE-2025-52496 (boo#1245810) to 2.28. mbedtls_aesni_has_support() cached the CPUID result in plain static variables, allowing the compiler to hoist `done = 1` above the store to `c`. Two threads racing at startup could then observe `done == 1` with `c == 0` and fall back to software AES even though AESNI is available, opening timing attacks (AES key disclosure / GCM forgery in multithreaded programs). Mark both statics volatile with the upstream comment so the stores are not reordered. CVE-2025-52496 boo#1245810 --- diff --git a/library/aesni.c b/library/aesni.c --- a/library/aesni.c +++ b/library/aesni.c @@ -42,8 +42,12 @@ */ int mbedtls_aesni_has_support(unsigned int what) { - static int done = 0; - static unsigned int c = 0; + /* To avoid a race condition, tell the compiler that the assignment + * `done = 1` and the assignment to `c` may not be reordered. + * https://github.com/Mbed-TLS/mbedtls/issues/9840 + */ + static volatile int done = 0; + static volatile unsigned int c = 0; if (!done) { #if MBEDTLS_AESNI_HAVE_CODE == 2 ++++++ mbedtls-fix-CVE-2025-59438.patch ++++++ Subject: Fix padding oracle through timing of cipher error reporting (CVE-2025-59438) Patch-mainline: Backport of upstream 3.6 fix References: https://github.com/Mbed-TLS/mbedtls/commit/155de2ab775e77ab6fa81bf2b1e6e63768123bc1 https://github.com/Mbed-TLS/mbedtls/commit/d179dc80a5b13189c79fe4531eacb28698a7a0e9 https://github.com/Mbed-TLS/mbedtls/commit/e74b42832e4af11606ef8aae2c9404b4acaa2c6d https://github.com/Mbed-TLS/mbedtls/commit/3b380daedbce9fae3e7ed7e84f18e97876e7e6f3 https://github.com/Mbed-TLS/mbedtls/commit/04dfd704325a6dbc2a13eb7f418eaca9ae9ca549 https://github.com/Mbed-TLS/mbedtls/commit/cc908ad04c388b50b81fa3b3a8b509cf62797fcf Backport the 3.6.x fix for CVE-2025-59438 (boo#1252454) to the 2.28 code base. Decryption with CBC-PKCS7 leaked the presence of padding errors through timing: mbedtls_psa_cipher_finish() translated mbedtls_cipher_finish() errors via mbedtls_to_psa_error(), and the callers branched on status and on the output length. Add mbedtls_cipher_finish_padded(), which reports invalid padding through a separate all-bits-one mask instead of an error code, use it in mbedtls_psa_cipher_finish(), copy a fixed amount and derive the PSA status (INVALID_PADDING vs BUFFER_TOO_SMALL) without branching on the sensitive values, and make psa_cipher_finish(), psa_cipher_decrypt() and mbedtls_psa_cipher_decrypt() avoid code paths that depend on the sensitive status/output length. 2.28 lacks the mbedtls_ct_condition_t framework the 3.6 fix uses, so the same operations are implemented here with plain branch-free size_t arithmetic (masks are 0 or all-bits-one). CVE-2025-59438 boo#1252454 --- diff -u -r a/include/mbedtls/cipher.h b/include/mbedtls/cipher.h --- a/include/mbedtls/cipher.h 2025-03-21 00:13:48.000000000 +0100 +++ b/include/mbedtls/cipher.h 2026-09-14 19:20:01.938914513 +0200 @@ -714,7 +714,7 @@ * 1. mbedtls_cipher_set_iv() if the mode uses an IV/nonce. * 2. mbedtls_cipher_reset() * 3. mbedtls_cipher_update() one or more times - * 4. mbedtls_cipher_finish() + * 4. mbedtls_cipher_finish() or mbedtls_cipher_finish_padded() * . * This sequence can be repeated to encrypt or decrypt multiple * messages with the same key. @@ -764,7 +764,8 @@ * many block-sized blocks of data as possible to output. * Any data that cannot be written immediately is either * added to the next block, or flushed when - * mbedtls_cipher_finish() is called. + * mbedtls_cipher_finish() or mbedtls_cipher_finish_padded() + * is called. * Exception: For MBEDTLS_MODE_ECB, expects a single block * in size. For example, 16 Bytes for AES. * @@ -803,6 +804,19 @@ * contained in it is padded to the size of * the last block, and written to the \p output buffer. * + * \warning This function reports invalid padding through an error + * code. Adversaries may be able to decrypt encrypted + * data if they can submit chosen ciphertexts and + * detect whether it has valid padding or not, + * either through direct observation or through a side + * channel such as timing. This is known as a + * padding oracle attack. + * Therefore applications that call this function for + * decryption with a cipher that involves padding + * should take care around error handling. Preferably, + * such applications should use + * mbedtls_cipher_finish_padded() instead of this function. + * * \param ctx The generic cipher context. This must be initialized and * bound to a key. * \param output The buffer to write data to. This needs to be a writable @@ -816,12 +830,56 @@ * \return #MBEDTLS_ERR_CIPHER_FULL_BLOCK_EXPECTED on decryption * expecting a full block but not receiving one. * \return #MBEDTLS_ERR_CIPHER_INVALID_PADDING on invalid padding - * while decrypting. + * while decrypting. Note that invalid-padding errors + * should be handled carefully; see the warning above. * \return A cipher-specific error code on failure. */ int mbedtls_cipher_finish(mbedtls_cipher_context_t *ctx, unsigned char *output, size_t *olen); +/** + * \brief The generic cipher finalization function. If data still + * needs to be flushed from an incomplete block, the data + * contained in it is padded to the size of + * the last block, and written to the \p output buffer. + * + * \note This function is similar to mbedtls_cipher_finish(). + * The only difference is that it reports invalid padding + * on decryption differently, through the \p invalid_padding + * parameter rather than an error code. + * For encryption, and in modes without padding (including + * all authenticated modes), this function is identical + * to mbedtls_cipher_finish(). + * + * \param ctx The generic cipher context. This must be initialized and + * bound to a key. + * \param output The buffer to write data to. This needs to be a writable + * buffer of at least block_size Bytes. + * \param olen The length of the data written to the \p output buffer. + * This may not be \c NULL. + * \param invalid_padding + * If this function returns \c 0 on decryption, + * \p *invalid_padding is \c 0 if the ciphertext was + * valid, and all-bits-one if the ciphertext had invalid + * padding. + * On encryption, or in a mode without padding (including + * all authenticated modes), \p *invalid_padding is \c 0 + * on success. + * The value in \p *invalid_padding is unspecified if + * this function returns a nonzero status. + * + * \return \c 0 on success. + * Also \c 0 for decryption with invalid padding. + * \return #MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA on + * parameter-verification failure. + * \return #MBEDTLS_ERR_CIPHER_FULL_BLOCK_EXPECTED on decryption + * expecting a full block but not receiving one. + * \return A cipher-specific error code on failure. + */ +int mbedtls_cipher_finish_padded(mbedtls_cipher_context_t *ctx, + unsigned char *output, size_t *olen, + size_t *invalid_padding); + #if defined(MBEDTLS_GCM_C) || defined(MBEDTLS_CHACHAPOLY_C) /** * \brief This function writes a tag for AEAD ciphers. diff -u -r a/library/cipher.c b/library/cipher.c --- a/library/cipher.c 2025-03-21 00:13:48.000000000 +0100 +++ b/library/cipher.c 2026-09-14 19:20:19.400877063 +0200 @@ -992,6 +992,23 @@ return MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE; } +int mbedtls_cipher_finish_padded(mbedtls_cipher_context_t *ctx, + unsigned char *output, size_t *olen, + size_t *invalid_padding) +{ + *invalid_padding = 0; + int ret = mbedtls_cipher_finish(ctx, output, olen); +#if defined(MBEDTLS_CIPHER_PADDING_PKCS7) || \ + defined(MBEDTLS_CIPHER_PADDING_ONE_AND_ZEROS) || \ + defined(MBEDTLS_CIPHER_PADDING_ZEROS_AND_LEN) + if (ret == MBEDTLS_ERR_CIPHER_INVALID_PADDING) { + ret = 0; + *invalid_padding = SIZE_MAX; + } +#endif + return ret; +} + #if defined(MBEDTLS_CIPHER_MODE_WITH_PADDING) int mbedtls_cipher_set_padding_mode(mbedtls_cipher_context_t *ctx, mbedtls_cipher_padding_t mode) diff -u -r a/library/psa_crypto.c b/library/psa_crypto.c --- a/library/psa_crypto.c 2025-03-21 00:13:48.000000000 +0100 +++ b/library/psa_crypto.c 2026-09-14 19:21:39.017825212 +0200 @@ -217,6 +217,15 @@ output_copy = NULL; #endif /* !MBEDTLS_PSA_ASSUME_EXCLUSIVE_BUFFERS */ +/* Branch-free mask for CVE-2025-59438 (padding oracle through timing of + * cipher error reporting). Returns SIZE_MAX if x != 0, 0 otherwise, without + * branching on x, so that callers can clear *output_length on failure + * without leaking whether the failure was PSA_ERROR_INVALID_PADDING. */ +static size_t psa_ct_mask_nonzero(size_t x) +{ + return (size_t) (0 - (((x | (size_t) (0 - x)) >> (sizeof(size_t) * 8 - 1)) & 1u)); +} + psa_status_t mbedtls_to_psa_error(int ret) { /* Mbed TLS error codes can combine a high-level error code and a @@ -3957,12 +3966,24 @@ output_length); exit: - if (status == PSA_SUCCESS) { - status = psa_cipher_abort(operation); - } else { - *output_length = 0; - (void) psa_cipher_abort(operation); - } + /* C99 doesn't allow a declaration to follow a label */; + psa_status_t abort_status = psa_cipher_abort(operation); + /* Normally abort shouldn't fail unless the operation is in a bad + * state, in which case we'd expect finish to fail with the same error. + * So it doesn't matter much which call's error code we pick when both + * fail. However, in unauthenticated decryption specifically, the + * distinction between PSA_SUCCESS and PSA_ERROR_INVALID_PADDING is + * security-sensitive (risk of a padding oracle attack), so here we + * must not have a code path that depends on the value of status. */ + if (abort_status != PSA_SUCCESS) { + status = abort_status; + } + + /* Set *output_length to 0 if status != PSA_SUCCESS, without + * leaking the value of status through a timing side channel + * (status == PSA_ERROR_INVALID_PADDING is sensitive when doing + * decryption with unpadding, due to the risk of padding oracle attack). */ + *output_length &= ~psa_ct_mask_nonzero((size_t) status); LOCAL_OUTPUT_FREE(output_external, output); @@ -4116,13 +4137,15 @@ exit: unlock_status = psa_unlock_key_slot(slot); - if (status == PSA_SUCCESS) { + if (unlock_status != PSA_SUCCESS) { status = unlock_status; } - if (status != PSA_SUCCESS) { - *output_length = 0; - } + /* Set *output_length to 0 if status != PSA_SUCCESS, without + * leaking the value of status through a timing side channel + * (status == PSA_ERROR_INVALID_PADDING is sensitive when doing + * decryption with unpadding, due to the risk of padding oracle attack). */ + *output_length &= ~psa_ct_mask_nonzero((size_t) status); LOCAL_INPUT_FREE(input_external, input); LOCAL_OUTPUT_FREE(output_external, output); diff -u -r a/library/psa_crypto_cipher.c b/library/psa_crypto_cipher.c --- a/library/psa_crypto_cipher.c 2025-03-21 00:13:48.000000000 +0100 +++ b/library/psa_crypto_cipher.c 2026-09-14 19:24:24.848462917 +0200 @@ -149,6 +149,31 @@ #if defined(MBEDTLS_PSA_BUILTIN_CIPHER) +/* Constant-time helpers for CVE-2025-59438 (padding oracle through timing + * of cipher error reporting). + * + * 2.28 lacks the mbedtls_ct_condition_t framework introduced for this fix + * in 3.6, so implement the same operations with plain branch-free size_t + * arithmetic. Masks are 0 or SIZE_MAX (all-bits-one); all helpers avoid + * data-dependent branches and memory accesses. + */ +static size_t psa_ct_mask_lt(size_t x, size_t y) +{ + const size_t msb_diff = ((x ^ y) >> (sizeof(size_t) * 8 - 1)) & 1u; + const size_t mask_msb_diff = (size_t) (0 - msb_diff); + const size_t diff = x - y; + const size_t sel = (mask_msb_diff & y) | (~mask_msb_diff & diff); + return (size_t) (0 - ((sel >> (sizeof(size_t) * 8 - 1)) & 1u)); +} + +static psa_status_t psa_ct_error_if(size_t cond, psa_status_t if1, psa_status_t if0) +{ + size_t u1 = (size_t) (0 - (int) if1); + size_t u0 = (size_t) (0 - (int) if0); + size_t sel = (cond & u1) | (~cond & u0); + return (psa_status_t) (0 - sel); +} + static psa_status_t psa_cipher_setup( mbedtls_psa_cipher_operation_t *operation, const psa_key_attributes_t *attributes, @@ -424,7 +449,19 @@ uint8_t *output, size_t output_size, size_t *output_length) { psa_status_t status = PSA_ERROR_GENERIC_ERROR; - uint8_t temp_output_buffer[MBEDTLS_MAX_BLOCK_LENGTH]; + size_t invalid_padding = 0; + + /* We will copy output_size bytes from temp_output_buffer to the + * output buffer. We can't use *output_length to determine how + * much to copy because we must not leak that value through timing + * when doing decryption with unpadding. But the underlying function + * is not guaranteed to write beyond *output_length. To ensure we don't + * leak the former content of the stack to the caller, wipe that + * former content. */ + uint8_t temp_output_buffer[MBEDTLS_MAX_BLOCK_LENGTH] = { 0 }; + if (output_size > sizeof(temp_output_buffer)) { + output_size = sizeof(temp_output_buffer); + } if (operation->ctx.cipher.unprocessed_len != 0) { if (operation->alg == PSA_ALG_ECB_NO_PADDING || @@ -435,21 +472,28 @@ } status = mbedtls_to_psa_error( - mbedtls_cipher_finish(&operation->ctx.cipher, - temp_output_buffer, - output_length)); + mbedtls_cipher_finish_padded(&operation->ctx.cipher, + temp_output_buffer, + output_length, + &invalid_padding)); if (status != PSA_SUCCESS) { goto exit; } - if (*output_length == 0) { + if (output_size == 0) { ; /* Nothing to copy. Note that output may be NULL in this case. */ - } else if (output_size >= *output_length) { - memcpy(output, temp_output_buffer, *output_length); } else { - status = PSA_ERROR_BUFFER_TOO_SMALL; + /* Do not use the value of *output_length to determine how much + * to copy. When decrypting a padded cipher, the output length is + * sensitive, and leaking it could allow a padding oracle attack. */ + memcpy(output, temp_output_buffer, output_size); } + status = psa_ct_error_if(invalid_padding, + PSA_ERROR_INVALID_PADDING, PSA_SUCCESS); + status = psa_ct_error_if(psa_ct_mask_lt(output_size, *output_length), + PSA_ERROR_BUFFER_TOO_SMALL, status); + exit: mbedtls_platform_zeroize(temp_output_buffer, sizeof(temp_output_buffer)); @@ -579,10 +623,17 @@ *output_length = accumulated_length + olength; exit: - if (status == PSA_SUCCESS) { - status = mbedtls_psa_cipher_abort(&operation); - } else { - mbedtls_psa_cipher_abort(&operation); + /* C99 doesn't allow a declaration to follow a label */; + psa_status_t abort_status = mbedtls_psa_cipher_abort(&operation); + /* Normally abort shouldn't fail unless the operation is in a bad + * state, in which case we'd expect finish to fail with the same error. + * So it doesn't matter much which call's error code we pick when both + * fail. However, in unauthenticated decryption specifically, the + * distinction between PSA_SUCCESS and PSA_ERROR_INVALID_PADDING is + * security-sensitive (risk of a padding oracle attack), so here we + * must not have a code path that depends on the value of status. */ + if (abort_status != PSA_SUCCESS) { + status = abort_status; } return status;
