| Copyright | (c) 2025 Jared Tobin |
|---|---|
| License | MIT |
| Maintainer | Jared Tobin <jared@ppad.tech> |
| Safe Haskell | None |
| Language | Haskell2010 |
Data.Choice
Description
Primitives for constant-time choice.
The Choice type encodes truthy and falsy values as unboxed Word#
bit masks.
Use the standard logical primitives (or, and, xor, not, eq')
to manipulate in-flight Choice values. Use one of the selection
functions to use a Choice to select a value in constant time,
or decide to reduce a Choice to a Bool at the end of a
sensitive computation.
Synopsis
- data Choice :: TYPE 'WordRep
- decide :: Choice -> Bool
- true# :: () -> Choice
- false# :: () -> Choice
- to_word# :: Choice -> Word#
- from_full_mask# :: Word# -> Choice
- from_bit# :: Word# -> Choice
- from_word_nonzero# :: Word# -> Choice
- from_word_eq# :: Word# -> Word# -> Choice
- from_word_le# :: Word# -> Word# -> Choice
- from_word_lt# :: Word# -> Word# -> Choice
- from_word_gt# :: Word# -> Word# -> Choice
- or :: Choice -> Choice -> Choice
- and :: Choice -> Choice -> Choice
- xor :: Choice -> Choice -> Choice
- not :: Choice -> Choice
- ne :: Choice -> Choice -> Choice
- eq :: Choice -> Choice -> Choice
- select_word# :: Word# -> Word# -> Choice -> Word#
- select_wide# :: Limb2 -> Limb2 -> Choice -> Limb2
- select_wider# :: Limb4 -> Limb4 -> Choice -> Limb4
- eq_word# :: Word# -> Word# -> Choice
- eq_wide# :: Limb2 -> Limb2 -> Choice
- eq_wider# :: Limb4 -> Limb4 -> Choice
Choice
data Choice :: TYPE 'WordRep Source #
Constant-time choice, encoded as a mask.
Note that Choice is defined as an unlifted newtype, and so a
Choice value cannot be bound at the top level. You should work
with it locally in the context of a computation.
Use one of the selection functions to select a Choice value in
constant time, or decide to reduce it to a Bool at the end of
a sensitive computation.
>>>decide (or# (false# ()) (true# ()))True
decide :: Choice -> Bool Source #
Decide a Choice by reducing it to a Bool.
The decide function itself runs in constant time, but once
it reduces a Choice to a Bool, any subsequent branching on
the result is liable to introduce variable-time behaviour.
You should decide only at the end of a computation, after all
security-sensitive computations have been carried out.
>>>decide (true# ())True
Construction
from_full_mask# :: Word# -> Choice Source #
Construct a Choice from an unboxed full-word mask.
The input is not checked to be a full-word mask.
>>>decide (from_full_mask# 0##)False>>>decide (from_full_mask# 0xFFFFFFFFF_FFFFFFFF##)True
from_bit# :: Word# -> Choice Source #
Construct a Choice from an unboxed word, which should be either
0## or 1##.
The input is not checked to be a bit.
>>>decide (from_bit# 1##)True
from_word_nonzero# :: Word# -> Choice Source #
Construct a Choice from a nonzero unboxed word.
The input is not checked to be nonzero.
>>>decide (from_word_nonzero# 2##)True
from_word_eq# :: Word# -> Word# -> Choice Source #
Construct a Choice from an equality comparison.
>>>decide (from_word_eq# 0## 1##)False decide (from_word_eq# 1## 1##) True
from_word_le# :: Word# -> Word# -> Choice Source #
Construct a 'Choice from an at-most comparison.
>>>decide (from_word_le# 0## 1##)True>>>decide (from_word_le# 1## 1##)True
from_word_lt# :: Word# -> Word# -> Choice Source #
Construct a Choice from a less-than comparison.
>>>decide (from_word_lt# 0## 1##)True>>>decide (from_word_lt# 1## 1##)False
from_word_gt# :: Word# -> Word# -> Choice Source #
Construct a Choice from a greater-than comparison.
>>>decide (from_word_gt# 0## 1##)False>>>decide (from_word_gt# 1## 1##)False
Manipulation
or :: Choice -> Choice -> Choice Source #
Logical disjunction on Choice values.
>>>decide (or (true# ()) (false# ()))True
and :: Choice -> Choice -> Choice Source #
Logical conjunction on Choice values.
>>>decide (and (true# ()) (false# ()))False
xor :: Choice -> Choice -> Choice Source #
Logical inequality on Choice values.
>>>decide (xor (true# ()) (false# ()))True
not :: Choice -> Choice Source #
Logically negate a Choice.
>>>decide (not (true# ()))False>>>decide (not (false# ()))True
ne :: Choice -> Choice -> Choice Source #
Logical inequality on Choice values.
>>>decide (ne (true# ()) (false# ()))True
eq :: Choice -> Choice -> Choice Source #
Logical equality on Choice values.
>>>decide (eq (true# ()) (false# ()))False
Constant-time Selection
select_word# :: Word# -> Word# -> Choice -> Word# Source #
Select an unboxed word without branching, given a Choice.
>>>let w = C.select_word# 0## 1## (C.true# ()) in GHC.Word.W# w1
select_wide# :: Limb2 -> Limb2 -> Choice -> Limb2 Source #
Select an unboxed two-limb word without branching, given a Choice.
select_wider# :: Limb4 -> Limb4 -> Choice -> Limb4 Source #
Select an unboxed four-limb word without branching, given a Choice.
Constant-time Equality
eq_word# :: Word# -> Word# -> Choice Source #
Compare unboxed words for equality in constant time.
>>>decide (eq_word# 0## 1##)False