Use distinct range for Hardened booleans + first select test

This commit is contained in:
mratsim 2018-12-01 18:01:41 +01:00
parent 8d6e328397
commit d545147b0b
3 changed files with 23 additions and 7 deletions

View File

@ -73,20 +73,24 @@ func isMsbSet*[T: HardBase](x: T): HardBool[T] {.inline.} =
# #
# ############################################################ # ############################################################
template undistinct[T: HardBase](x: HardBool[T]): T =
T(x)
func `not`*(ctl: HardBool): HardBool {.inline.}= func `not`*(ctl: HardBool): HardBool {.inline.}=
## Negate a constant-time boolean ## Negate a constant-time boolean
ctl xor 1 (type result)(ctl.undistinct xor (type ctl.undistinct)(1))
func select*[T: HardBase](ctl: HardBool[T], x, y: T): T {.inline.}= template select*[T: HardBase](ctl: HardBool[T], x, y: T): T =
## Multiplexer / selector ## Multiplexer / selector
## Returns x if ctl == 1 ## Returns x if ctl == 1
## else returns y ## else returns y
## So equivalent to ctl? x: y ## So equivalent to ctl? x: y
y xor (-T(ctl) and (x xor y))
# TODO verify assembly generated # TODO verify assembly generated
# as mentionned in https://cryptocoding.net/index.php/Coding_rules # as mentionned in https://cryptocoding.net/index.php/Coding_rules
# the alternative `(x and ctl) or (y and -m)` # the alternative `(x and ctl) or (y and -ctl)`
# is optimized into a branch by Clang :/ # is optimized into a branch by Clang :/
y xor (-ctl.T and (x xor y))
func noteq[T: HardBase](x, y: T): HardBool[T] {.inline.}= func noteq[T: HardBase](x, y: T): HardBool[T] {.inline.}=
const msb = T.sizeof * 8 - 1 const msb = T.sizeof * 8 - 1
@ -104,7 +108,7 @@ func `<`*[T: HardBase](x, y: T): HardBool[T] {.inline.}=
) )
func `<=`*[T: HardBase](x, y: T): HardBool[T] {.inline.}= func `<=`*[T: HardBase](x, y: T): HardBool[T] {.inline.}=
(y < x) xor 1 not(y < x)
# ############################################################ # ############################################################
# #

View File

@ -10,7 +10,7 @@ type
HardBase*[T: BaseUint] = distinct T HardBase*[T: BaseUint] = distinct T
HardBool*[T: HardBase] = range[T(0)..T(1)] HardBool*[T: HardBase] = distinct range[T(0)..T(1)]
## To avoid the compiler replacing bitwise boolean operations ## To avoid the compiler replacing bitwise boolean operations
## by conditional branches, we don't use booleans. ## by conditional branches, we don't use booleans.
## We use an int to prevent compiler "optimization" and introduction of branches ## We use an int to prevent compiler "optimization" and introduction of branches

View File

@ -50,7 +50,7 @@ suite "Hardened unsigned integers":
not(hard(0'u32)).undistinct == not 0'u32 not(hard(0'u32)).undistinct == not 0'u32
not(hard(1'u32)).undistinct == not 1'u32 not(hard(1'u32)).undistinct == not 1'u32
not(hard(1234'u64)).undistinct == not 1234'u64 not(hard(1234'u64)).undistinct == not 1234'u64
not(hard(5678'u64)).undistinct == not 5678'u32 not(hard(5678'u64)).undistinct == not 5678'u64
not(hard(x1)).undistinct == not x1 not(hard(x1)).undistinct == not x1
not(hard(x2)).undistinct == not x2 not(hard(x2)).undistinct == not x2
not(hard(x3)).undistinct == not x3 not(hard(x3)).undistinct == not x3
@ -166,3 +166,15 @@ suite "Hardened booleans":
bool(hard(10'u32) >= hard(20'u32)) == false bool(hard(10'u32) >= hard(20'u32)) == false
bool(hard(10'u32) >= hard(5'u32)) == true bool(hard(10'u32) >= hard(5'u32)) == true
bool(hard(10'u32) >= hard(0xFFFFFFFF'u32)) == false bool(hard(10'u32) >= hard(0xFFFFFFFF'u32)) == false
test "Multiplexer/selector - select(ctl, x, y) <=> ctl? x: y":
let u = 10'u32.hard
let v = 20'u32.hard
let w = 5'u32.hard
let y = htrue(uint32)
let n = hfalse(uint32)
check:
bool(select(y, u, v) == u)