* [PATCH] lib/crypto: gf128mul: Hide selection mask values from compilers
@ 2026-10-31 5:21 Eric Biggers
2026-11-02 9:12 ` Ard Biesheuvel
2026-11-03 23:27 ` Eric Biggers
0 siblings, 2 replies; 3+ messages in thread
From: Eric Biggers @ 2026-10-31 5:21 UTC (permalink / raw)
To: linux-crypto
Cc: Ard Biesheuvel, Jason A . Donenfeld, Herbert Xu, Eric Biggers
Hide selection mask values from compilers, so that they cannot see that
they are used to select between two values and potentially generate a
secret-dependent branch. This is not known to be happening here, but we
might as well be extra careful.
For the cases where the selected values are only 0x87 and 0, change the
type of the mask to 'unsigned long' so that the compiler is not forced
to materialize it in a register pair on 32-bit architectures.
Signed-off-by: Eric Biggers <ebiggers@kernel.org>
---
include/crypto/gf128mul.h | 25 +++++++++----------------
1 file changed, 9 insertions(+), 16 deletions(-)
diff --git a/include/crypto/gf128mul.h b/include/crypto/gf128mul.h
index 6ed2a8351902..8fb6f8dbbfa9 100644
--- a/include/crypto/gf128mul.h
+++ b/include/crypto/gf128mul.h
@@ -171,35 +171,28 @@ void gf128mul_lle(be128 *a, const be128 *b);
* They are defined here for performance.
*/
-static inline u64 gf128mul_mask_from_bit(u64 x, int which)
-{
- /* a constant-time version of 'x & ((u64)1 << which) ? (u64)-1 : 0' */
- return ((s64)(x << (63 - which)) >> 63);
-}
-
static inline void gf128mul_x_lle(be128 *r, const be128 *x)
{
u64 a = be64_to_cpu(x->a);
u64 b = be64_to_cpu(x->b);
+ u64 mask = -(b & 1);
- /* equivalent to gf128mul_table_le[(b << 7) & 0xff] << 48
- * (see crypto/gf128mul.c): */
- u64 _tt = gf128mul_mask_from_bit(b, 0) & ((u64)0xe1 << 56);
+ OPTIMIZER_HIDE_VAR(mask);
r->b = cpu_to_be64((b >> 1) | (a << 63));
- r->a = cpu_to_be64((a >> 1) ^ _tt);
+ r->a = cpu_to_be64((a >> 1) ^ (mask & ((u64)0xe1 << 56)));
}
static inline void gf128mul_x_bbe(be128 *r, const be128 *x)
{
u64 a = be64_to_cpu(x->a);
u64 b = be64_to_cpu(x->b);
+ unsigned long mask = (s64)a >> 63;
- /* equivalent to gf128mul_table_be[a >> 63] (see crypto/gf128mul.c): */
- u64 _tt = gf128mul_mask_from_bit(a, 63) & 0x87;
+ OPTIMIZER_HIDE_VAR(mask);
r->a = cpu_to_be64((a << 1) | (b >> 63));
- r->b = cpu_to_be64((b << 1) ^ _tt);
+ r->b = cpu_to_be64((b << 1) ^ (mask & 0x87));
}
/* needed by XTS */
@@ -207,12 +200,12 @@ static inline void gf128mul_x_ble(le128 *r, const le128 *x)
{
u64 a = le64_to_cpu(x->a);
u64 b = le64_to_cpu(x->b);
+ unsigned long mask = (s64)a >> 63;
- /* equivalent to gf128mul_table_be[b >> 63] (see crypto/gf128mul.c): */
- u64 _tt = gf128mul_mask_from_bit(a, 63) & 0x87;
+ OPTIMIZER_HIDE_VAR(mask);
r->a = cpu_to_le64((a << 1) | (b >> 63));
- r->b = cpu_to_le64((b << 1) ^ _tt);
+ r->b = cpu_to_le64((b << 1) ^ (mask & 0x87));
}
void gf128mul_x8_ble(le128 *r, const le128 *x);
base-commit: 2a500a04d6f969318c05f46aedb6e73fc1963a00
--
2.56.0
^ permalink raw reply related [flat|nested] 3+ messages in thread
* Re: [PATCH] lib/crypto: gf128mul: Hide selection mask values from compilers
2026-10-31 5:21 [PATCH] lib/crypto: gf128mul: Hide selection mask values from compilers Eric Biggers
@ 2026-11-02 9:12 ` Ard Biesheuvel
2026-11-03 23:27 ` Eric Biggers
1 sibling, 0 replies; 3+ messages in thread
From: Ard Biesheuvel @ 2026-11-02 9:12 UTC (permalink / raw)
To: Eric Biggers, linux-crypto; +Cc: Jason A . Donenfeld, Herbert Xu
On Sat, 31 Oct 2026, at 06:21, Eric Biggers wrote:
> Hide selection mask values from compilers, so that they cannot see that
> they are used to select between two values and potentially generate a
> secret-dependent branch. This is not known to be happening here, but we
> might as well be extra careful.
>
> For the cases where the selected values are only 0x87 and 0, change the
> type of the mask to 'unsigned long' so that the compiler is not forced
> to materialize it in a register pair on 32-bit architectures.
>
> Signed-off-by: Eric Biggers <ebiggers@kernel.org>
> ---
> include/crypto/gf128mul.h | 25 +++++++++----------------
> 1 file changed, 9 insertions(+), 16 deletions(-)
>
Reviewed-by: Ard Biesheuvel <ardb@kernel.org>
> diff --git a/include/crypto/gf128mul.h b/include/crypto/gf128mul.h
> index 6ed2a8351902..8fb6f8dbbfa9 100644
> --- a/include/crypto/gf128mul.h
> +++ b/include/crypto/gf128mul.h
> @@ -171,35 +171,28 @@ void gf128mul_lle(be128 *a, const be128 *b);
> * They are defined here for performance.
> */
>
> -static inline u64 gf128mul_mask_from_bit(u64 x, int which)
> -{
> - /* a constant-time version of 'x & ((u64)1 << which) ? (u64)-1 : 0' */
> - return ((s64)(x << (63 - which)) >> 63);
> -}
> -
> static inline void gf128mul_x_lle(be128 *r, const be128 *x)
> {
> u64 a = be64_to_cpu(x->a);
> u64 b = be64_to_cpu(x->b);
> + u64 mask = -(b & 1);
>
> - /* equivalent to gf128mul_table_le[(b << 7) & 0xff] << 48
> - * (see crypto/gf128mul.c): */
> - u64 _tt = gf128mul_mask_from_bit(b, 0) & ((u64)0xe1 << 56);
> + OPTIMIZER_HIDE_VAR(mask);
>
> r->b = cpu_to_be64((b >> 1) | (a << 63));
> - r->a = cpu_to_be64((a >> 1) ^ _tt);
> + r->a = cpu_to_be64((a >> 1) ^ (mask & ((u64)0xe1 << 56)));
> }
>
> static inline void gf128mul_x_bbe(be128 *r, const be128 *x)
> {
> u64 a = be64_to_cpu(x->a);
> u64 b = be64_to_cpu(x->b);
> + unsigned long mask = (s64)a >> 63;
>
> - /* equivalent to gf128mul_table_be[a >> 63] (see crypto/gf128mul.c): */
> - u64 _tt = gf128mul_mask_from_bit(a, 63) & 0x87;
> + OPTIMIZER_HIDE_VAR(mask);
>
> r->a = cpu_to_be64((a << 1) | (b >> 63));
> - r->b = cpu_to_be64((b << 1) ^ _tt);
> + r->b = cpu_to_be64((b << 1) ^ (mask & 0x87));
> }
>
> /* needed by XTS */
> @@ -207,12 +200,12 @@ static inline void gf128mul_x_ble(le128 *r, const
> le128 *x)
> {
> u64 a = le64_to_cpu(x->a);
> u64 b = le64_to_cpu(x->b);
> + unsigned long mask = (s64)a >> 63;
>
> - /* equivalent to gf128mul_table_be[b >> 63] (see crypto/gf128mul.c): */
> - u64 _tt = gf128mul_mask_from_bit(a, 63) & 0x87;
> + OPTIMIZER_HIDE_VAR(mask);
>
> r->a = cpu_to_le64((a << 1) | (b >> 63));
> - r->b = cpu_to_le64((b << 1) ^ _tt);
> + r->b = cpu_to_le64((b << 1) ^ (mask & 0x87));
> }
>
> void gf128mul_x8_ble(le128 *r, const le128 *x);
>
> base-commit: 2a500a04d6f969318c05f46aedb6e73fc1963a00
> --
> 2.56.0
^ permalink raw reply [flat|nested] 3+ messages in thread
* Re: [PATCH] lib/crypto: gf128mul: Hide selection mask values from compilers
2026-10-31 5:21 [PATCH] lib/crypto: gf128mul: Hide selection mask values from compilers Eric Biggers
2026-11-02 9:12 ` Ard Biesheuvel
@ 2026-11-03 23:27 ` Eric Biggers
1 sibling, 0 replies; 3+ messages in thread
From: Eric Biggers @ 2026-11-03 23:27 UTC (permalink / raw)
To: linux-crypto; +Cc: Ard Biesheuvel, Jason A . Donenfeld, Herbert Xu
On Fri, Oct 30, 2026 at 10:21:54PM -0700, Eric Biggers wrote:
> Hide selection mask values from compilers, so that they cannot see that
> they are used to select between two values and potentially generate a
> secret-dependent branch. This is not known to be happening here, but we
> might as well be extra careful.
>
> For the cases where the selected values are only 0x87 and 0, change the
> type of the mask to 'unsigned long' so that the compiler is not forced
> to materialize it in a register pair on 32-bit architectures.
>
> Signed-off-by: Eric Biggers <ebiggers@kernel.org>
> ---
> include/crypto/gf128mul.h | 25 +++++++++----------------
> 1 file changed, 9 insertions(+), 16 deletions(-)
Applied to https://git.kernel.org/pub/scm/linux/kernel/git/ebiggers/linux.git/log/?h=libcrypto-next
- Eric
^ permalink raw reply [flat|nested] 3+ messages in thread
end of thread, other threads:[~2026-11-03 23:27 UTC | newest]
Thread overview: 3+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-10-31 5:21 [PATCH] lib/crypto: gf128mul: Hide selection mask values from compilers Eric Biggers
2026-11-02 9:12 ` Ard Biesheuvel
2026-11-03 23:27 ` Eric Biggers
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox