authorgravatar for 124872+jedisct1@users.noreply.github.comFrank Denis <124872+jedisct1@users.noreply.github.com> 2026-09-07 21:03:22+02:00
committergravatar for 124872+jedisct1@users.noreply.github.comFrank Denis <124872+jedisct1@users.noreply.github.com> 2026-10-04 16:56:00+02:00
logebc1c263b44d084052ec1d7610f25632a19baee3
treec97f0ef5805c67b2c038628bafa44c37e1846b37
parente38b151e614eecf572f791b5712d2e6edd33dd84

crypto.ff: hide constant-time selection masks from optimizer

Hide the selection mask so LLVM can't replace it with a branch around the calling loop. Fixes #37023

1 files changed, 9 insertions(+), 1 deletions(-)

lib/std/crypto/ff.zig+9-1
......@@ -1083,12 +1083,20 @@ pub fn Modulus(comptime max_bits: comptime_int) type {
10831083 };
10841084}
10851085
1086fn valueBarrier(x: Limb) Limb {
1087 if (@inComptime() or builtin.zig_backend == .stage2_c) return x;
1088 return asm (""
1089 : [ret] "=r" (-> Limb),
1090 : [x] "0" (x),
1091 );
1092}
1093
10861094const ct = if (std.options.side_channels_mitigations == .none) ct_unprotected else ct_protected;
10871095
10881096const ct_protected = struct {
10891097 // Returns x if on is true, otherwise y.
10901098 fn select(on: bool, x: Limb, y: Limb) Limb {
1091 const mask = @as(Limb, 0) -% @intFromBool(on);
1099 const mask = valueBarrier(@as(Limb, 0) -% @intFromBool(on));
10921100 return y ^ (mask & (y ^ x));
10931101 }
10941102