From 56177c0cfe6b0c39321a197699c730ff61c56829 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mamy=20Andr=C3=A9-Ratsimbazafy?= Date: Sun, 16 Feb 2020 21:34:21 +0100 Subject: [PATCH] Use cmov name instead of mux to be in line with IETF spec on Hash to curve and Verifiable Random Functions --- constantine/math/bigints_raw.nim | 17 ++++++++++++----- constantine/primitives/constant_time.nim | 20 ++++++++++---------- tests/test_primitives.nim | 14 +++++++------- 3 files changed, 29 insertions(+), 22 deletions(-) diff --git a/constantine/math/bigints_raw.nim b/constantine/math/bigints_raw.nim index 1adaff8..f568be1 100644 --- a/constantine/math/bigints_raw.nim +++ b/constantine/math/bigints_raw.nim @@ -233,7 +233,7 @@ func add*(a: BigIntViewMut, b: BigIntViewAny, ctl: CTBool[Word]): CTBool[Word] = for i in 0 ..< a.numLimbs(): let new_a = a[i] + b[i] + Word(result) result = new_a.isMsbSet() - a[i] = ctl.mux(new_a and MaxWord, a[i]) + a[i] = ctl.cmov(new_a and MaxWord, a[i]) func sub*(a: BigIntViewMut, b: BigIntViewAny, ctl: CTBool[Word]): CTBool[Word] = ## Constant-time big integer in-place optional substraction @@ -247,7 +247,7 @@ func sub*(a: BigIntViewMut, b: BigIntViewAny, ctl: CTBool[Word]): CTBool[Word] = for i in 0 ..< a.numLimbs(): let new_a = a[i] - b[i] - Word(result) result = new_a.isMsbSet() - a[i] = ctl.mux(new_a and MaxWord, a[i]) + a[i] = ctl.cmov(new_a and MaxWord, a[i]) # ############################################################ # @@ -306,9 +306,9 @@ func shlAddMod(a: BigIntViewMut, c: Word, M: BigIntViewConst) = a_lo = (a0 shl WordBitSize) or a1 var q, r: Word unsafeDiv2n1n(q, r, a_hi, a_lo, m0) # Estimate quotient - q = mux( # If n_hi == divisor + q = cmov( # If n_hi == divisor a0 == m0, MaxWord, # Quotient == MaxWord (0b0111...1111) - mux( + cmov( q.isZero, Zero, # elif q == 0, true quotient = 0 q - One # else instead of being of by 0, 1 or 2 ) # we returning q-1 to be off by -1, 0 or 1 @@ -332,7 +332,7 @@ func shlAddMod(a: BigIntViewMut, c: Word, M: BigIntViewConst) = carry += Word(a[i].isMsbSet) # Adjust if borrow a[i] = a[i] and MaxWord # Normalize to u63 - over_p = mux( + over_p = cmov( a[i] == M[i], over_p, a[i] > M[i] ) @@ -393,6 +393,13 @@ func reduce*(r: BigIntViewMut, a: BigIntViewAny, M: BigIntViewConst) = # # ############################################################ +# TODO: when not optimizing for code-size we can benefit from +# specialized implementations of +# - Montgomery Multiplication by 1 (redc) +# - Montgomery squaring +# - Almost Montgomery Multiplication for Modular exponentiation: +# https://eprint.iacr.org/2011/239.pdf + template wordMul(a, b: Word): Word = (a * b) and MaxWord diff --git a/constantine/primitives/constant_time.nim b/constantine/primitives/constant_time.nim index 89372bb..67a967e 100644 --- a/constantine/primitives/constant_time.nim +++ b/constantine/primitives/constant_time.nim @@ -100,7 +100,7 @@ template `$`*(x: CTBool): string = # Note that templates duplicate their input parameters. # If a param is used multiple times, it **must** be `let` assigned first # to avoid duplicate computation or duplicate side-effect. -# We append a mnemonic like `mux` or `LT` to help inspecting the C code +# We append a mnemonic like `cmov` or `LT` to help inspecting the C code template fmap[T: Ct](x: T, op: untyped, y: T): T = ## Unwrap x and y from their distinct type @@ -208,8 +208,8 @@ template `<=`*[T: Ct](x, y: T): CTBool[T] = template `xor`*[T: Ct](x, y: CTBool[T]): CTBool[T] = CTBool[T](noteq(T(x), T(y))) -template mux*[T: Ct](ctl: CTBool[T], x, y: T): T = - ## Multiplexer / selector +template cmov*[T: Ct](ctl: CTBool[T], x, y: T): T = + ## Conditional Move / Multiplexer / selector / ## Returns x if ctl is true ## else returns y ## So equivalent to ctl? x: y @@ -222,19 +222,19 @@ template mux*[T: Ct](ctl: CTBool[T], x, y: T): T = # # TODO: assembly fastpath for conditional mov let # Templates duplicate input params code - x_Mux = x - y_Mux = y - y_Mux xor (-T(ctl) and (x_Mux xor y_Mux)) + x_cmov = x + y_cmov = y + y_cmov xor (-T(ctl) and (x_cmov xor y_cmov)) -template mux*[T: CTBool](ctl: CTBool, x, y: T): T = +template cmov*[T: CTBool](ctl: CTBool, x, y: T): T = ## Multiplexer / selector ## Returns x if ctl is true ## else returns y ## So equivalent to ctl? x: y let # Templates duplicate input params code - x_Mux = x - y_Mux = y - T(T.T(y_Mux) xor (-T.T(ctl) and T.T(x_Mux xor y_Mux))) + x_cmov = x + y_cmov = y + T(T.T(y_cmov) xor (-T.T(ctl) and T.T(x_cmov xor y_cmov))) # ############################################################ # diff --git a/tests/test_primitives.nim b/tests/test_primitives.nim index ee8ef31..9ece21c 100644 --- a/tests/test_primitives.nim +++ b/tests/test_primitives.nim @@ -169,7 +169,7 @@ proc main() = bool(ct(10'u32) >= ct(5'u32)) == true bool(ct(10'u32) >= ct(0xFFFFFFFF'u32)) == false - test "Multiplexer/selector - mux(ctl, x, y) <=> ctl? x: y": + test "Multiplexer/selector - cmov(ctl, x, y) <=> ctl? x: y": let u = 10'u32.ct let v = 20'u32.ct let w = 5'u32.ct @@ -178,13 +178,13 @@ proc main() = let n = cfalse(uint32) check: - bool(mux(y, u, v) == u) - bool(mux(n, u, v) == v) + bool(cmov(y, u, v) == u) + bool(cmov(n, u, v) == v) - bool(mux(y, u, w) == u) - bool(mux(n, u, w) == w) + bool(cmov(y, u, w) == u) + bool(cmov(n, u, w) == w) - bool(mux(y, v, w) == v) - bool(mux(n, v, w) == w) + bool(cmov(y, v, w) == v) + bool(cmov(n, v, w) == w) main()