commit c701ecb51224ffc087ce43c11f5d97cc3f11b22e
parent 5d08aaad84792e263e78d7fa8eccaeaedb0bc840
Author: Jared Tobin <jared@jtobin.io>
Date: Fri, 21 Nov 2025 17:13:42 +0400
lib: constant-time equality
Diffstat:
1 file changed, 36 insertions(+), 0 deletions(-)
diff --git a/lib/Data/Choice.hs b/lib/Data/Choice.hs
@@ -45,6 +45,11 @@ module Data.Choice (
-- * Constant-time Selection
, ct_select_word#
, ct_select_wide#
+
+ -- * Constant-time Equality
+ , ct_eq_word#
+ , ct_eq_wide#
+ , ct_eq_wider#
) where
import qualified Data.Bits as B
@@ -269,3 +274,34 @@ ct_select_wide# a b (Choice w) =
in xor_w# a (and_w# mask (xor_w# a b))
{-# INLINE ct_select_wide# #-}
+ct_eq_word# :: Word# -> Word# -> Choice
+ct_eq_word# a b =
+ let !s = case B.finiteBitSize (0 :: Word) of I# m -> m -# 1#
+ !x = xor# a b
+ !y = uncheckedShiftRL# (or# x (wrapping_neg# x)) s
+ in Choice (xor# y 1##)
+{-# INLINE ct_eq_word# #-}
+
+ct_eq_wide#
+ :: (# Word#, Word# #)
+ -> (# Word#, Word# #)
+ -> Choice
+ct_eq_wide# (# a0, a1 #) (# b0, b1 #) =
+ let !s = case B.finiteBitSize (0 :: Word) of I# m -> m -# 1#
+ !x = or# (xor# a0 b0) (xor# a1 b1)
+ !y = uncheckedShiftRL# (or# x (wrapping_neg# x)) s
+ in Choice (xor# y 1##)
+{-# INLINE ct_eq_wide# #-}
+
+ct_eq_wider#
+ :: (# Word#, Word#, Word#, Word# #)
+ -> (# Word#, Word#, Word#, Word# #)
+ -> Choice
+ct_eq_wider# (# a0, a1, a2, a3 #) (# b0, b1, b2, b3 #) =
+ let !s = case B.finiteBitSize (0 :: Word) of I# m -> m -# 1#
+ !x = or# (or# (xor# a0 b0) (xor# a1 b1))
+ (or# (xor# a2 b2) (xor# a3 b3))
+ !y = uncheckedShiftRL# (or# x (wrapping_neg# x)) s
+ in Choice (xor# y 1##)
+{-# INLINE ct_eq_wider# #-}
+