From 153e8982630016518cd7a7ef537e662ad5750a68 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mamy=20Andr=C3=A9-Ratsimbazafy?= Date: Sun, 9 Feb 2020 16:22:55 +0100 Subject: [PATCH] word_types -> primitives + delete the "config" file / debug template --- constantine.nimble | 2 +- constantine/bigints.nim | 2 +- constantine/config.nim | 17 ---- constantine/field_fp.nim | 96 +------------------ constantine/io.nim | 10 +- constantine/montgomery.nim | 2 +- constantine/montgomery_magic.nim | 2 +- .../{word_types.nim => primitives.nim} | 6 ++ ...s_internal.nim => primitives_internal.nim} | 2 +- tests/test_bigints.nim | 2 +- tests/test_field_fp.nim | 2 +- ...est_word_types.nim => test_primitives.nim} | 2 +- 12 files changed, 22 insertions(+), 123 deletions(-) delete mode 100644 constantine/config.nim rename constantine/{word_types.nim => primitives.nim} (97%) rename constantine/private/{word_types_internal.nim => primitives_internal.nim} (99%) rename tests/{test_word_types.nim => test_primitives.nim} (99%) diff --git a/constantine.nimble b/constantine.nimble index 99a4882..41985d2 100644 --- a/constantine.nimble +++ b/constantine.nimble @@ -16,7 +16,7 @@ proc test(fakeCurves: string, path: string, lang = "c") = ### tasks task test, "Run all tests": - test "", "tests/test_word_types.nim" + test "", "tests/test_primitives.nim" test "", "tests/test_io.nim" test "", "tests/test_bigints.nim" test " -d:testingCurves", "tests/test_field_fp.nim" diff --git a/constantine/bigints.nim b/constantine/bigints.nim index fde379f..bc39a4e 100644 --- a/constantine/bigints.nim +++ b/constantine/bigints.nim @@ -37,7 +37,7 @@ # So the least significant limb is limb[0] # This is independent from the base type endianness. -import ./word_types, ./config +import ./primitives, ./config type Word* = Ct[uint64] type BaseType* = uint64 # Exported type for conversion in "normal integers" diff --git a/constantine/config.nim b/constantine/config.nim deleted file mode 100644 index dbe30ff..0000000 --- a/constantine/config.nim +++ /dev/null @@ -1,17 +0,0 @@ -# Constantine -# Copyright (c) 2018-2019 Status Research & Development GmbH -# Copyright (c) 2020-Present Mamy André-Ratsimbazafy -# Licensed and distributed under either of -# * MIT license (license terms in the root directory or at http://opensource.org/licenses/MIT). -# * Apache v2 license (license terms in the root directory or at http://www.apache.org/licenses/LICENSE-2.0). -# at your option. This file may not be copied, modified, or distributed except according to those terms. - -# ############################################################ -# -# Common configuration -# -# ############################################################ - -template debug*(body: untyped): untyped = - when defined(debugConstantine): - body diff --git a/constantine/field_fp.nim b/constantine/field_fp.nim index 4d4498c..30a59e5 100644 --- a/constantine/field_fp.nim +++ b/constantine/field_fp.nim @@ -14,8 +14,7 @@ # We assume that p is prime known at compile-time -import ./word_types, ./bigints, ./curves_config -from ./private/word_types_internal import unsafe_div2n1n +import ./primitives, ./bigints, ./curves_config type Fp*[C: static Curve] = object @@ -71,96 +70,3 @@ func `+`*(a, b: Fp): Fp {.noInit.}= var ctl = add(result, b, CtTrue) ctl = ctl or not sub(result, Fp.C.Mod, CtFalse) sub(result, Fp.C.Mod, ctl) - -func shiftAdd*(a: var Fp, c: Word) = - ## Shift-accumulate - ## Shift input `a` by a word and add `c`. - ## - ## With a word W = 2^WordBitSize and a field Fp - ## Does a <- a * W + c (mod p) - const len = a.value.limbs.len - - when Fp.C.Mod.bits <= WordBitSize: - # If the prime fits in a single limb - var q: Word - - # (hi, lo) = a * 2^63 + c - let hi = a[0] shr 1 # 64 - 63 = 1 - let lo = (a[0] shl WordBitSize) or c # Assumes most-significant bit in c is not set - unsafeDiv2n1n(q, a[0], hi, lo, Fp.C.Mod.limbs[0]) # (hi, lo) mod P - return - - else: - ## Multiple limbs - let hi = a[^1] # Save the high word to detect carries - const R = Fp.C.Mod.bits and WordBitSize # R = bits mod 64 - - when R == 0: # If the number of bits is a multiple of 64 - let a1 = a[^2] # - let a0 = a[^1] # - moveMem(a[1], a[0], (len-1) * Word.sizeof) # we can just shift words - a[0] = c # and replace the first one by c - const p0 = Fp.C.Mod[^1] - else: # Need to deal with partial word shifts at the edge. - let a1 = ((a[^2] shl (WordBitSize-R)) or (a[^3] shr R)) and MaxWord - let a0 = ((a[^1] shl (WordBitSize-R)) or (a[^2] shr R)) and MaxWord - moveMem(a[1], a[0], (len-1) * Word.sizeof) - a[0] = c - const p0 = ((Fp.C.Mod[^1] shl (WordBitSize-R)) or (Fp.C.Mod[^2] shr R)) and MaxWord - - # p0 has its high bit set. (a0, a1)/p0 fits in a limb. - # Get a quotient q, at most we will be 2 iterations off - # from the true quotient - - let - a_hi = a0 shr 1 # 64 - 63 = 1 - a_lo = (a0 shl WordBitSize) or a1 - var q, r: Word - q = unsafeDiv2n1n(q, r, a_hi, a_lo, p0) # Estimate quotient - q = mux( # If n_hi == divisor - a0 == b0, MaxWord, # Quotient == MaxWord (0b0111...1111) - mux( - q == 0, 0, # elif q == 0, true quotient = 0 - q - 1 # else instead of being of by 0, 1 or 2 - ) # we returning q-1 to be off by -1, 0 or 1 - ) - - # Now substract a*2^63 - q*p - var carry = Word(0) - var over_p = Word(1) # Track if quotient than the modulus - - for i in static(0 ..< Fp.C.Mod.limbs.len): - var qp_lo: Word - - block: # q*p - qp_hi: Word - unsafeExtendedPrecMul(qp_hi, qp_lo, q, Fp.C.Mod[i]) # q * p - assert qp_lo.isMsbSet.not - assert carry.isMsbSet.not - qp_lo += carry # Add carry from previous limb - let qp_carry = qp_lo.isMsbSet - carry = mux(qp_carry, qp_hi + Word(1), qp_hi) # New carry - - qp_lo = qp_lo and MaxWord # Normalize to u63 - - block: # a*2^63 - q*p - a[i] -= qp_lo - carry += Word(a[i].isMsbSet) # Adjust if borrow - a[i] = a[i] and MaxWord # Normalize to u63 - - over_p = mux( - a[i] == Fp.C.Mod[i], over_p, - a[i] > Fp.C.Mod[i] - ) - - # Fix quotient, the true quotient is either q-1, q or q+1 - # - # if carry < q or carry == q and over_p we must do "a -= p" - # if carry > hi (negative result) we must do "a+= p" - - let neg = carry < hi - let tooBig = not neg and (over_p or (carry < hi)) - - add(a, Fp.C.Mod, neg) - sub(a, Fp.C.Mod, tooBig) - return diff --git a/constantine/io.nim b/constantine/io.nim index e02ad15..9a511ec 100644 --- a/constantine/io.nim +++ b/constantine/io.nim @@ -12,7 +12,7 @@ import endians, - ./word_types, ./bigints + ./primitives, ./bigints # ############################################################ # @@ -20,6 +20,8 @@ import # # ############################################################ +# TODO: tag/remove exceptions raised. + func fromRawUintLE( T: type BigInt, src: openarray[byte]): T = @@ -73,6 +75,9 @@ func fromUint*( src: SomeUnsignedInt): T = ## Parse a regular unsigned integer ## and store it into a BigInt of size `bits` + static: + doAssert T.bits >= sizeof(src) * 8, "The BigInt bitsize (" & $T.bits & + ") must be greater or equal the source integer bitsize (" & $(sizeof(src) * 8) & ')' fromRawUint(T, cast[array[sizeof(src), byte]](src), cpuEndian) # ############################################################ @@ -154,8 +159,7 @@ func dumpRawUint*( ## or zero-padded right for little-endian. ## I.e least significant bit is aligned to buffer boundary - if dst.len < static(BigInt.bits div 8): - raise newException(ValueError, "BigInt -> Raw int conversion: destination buffer is too small") + assert dst.len >= static(BigInt.bits div 8), "BigInt -> Raw int conversion: destination buffer is too small" when BigInt.bits == 0: zeroMem(dst, dst.len) diff --git a/constantine/montgomery.nim b/constantine/montgomery.nim index ca7f9d1..a3451c7 100644 --- a/constantine/montgomery.nim +++ b/constantine/montgomery.nim @@ -13,7 +13,7 @@ # ############################################################ import - ./word_types, ./bigints, ./field_fp, ./curves_config + ./primitives, ./bigints, ./field_fp, ./curves_config # No exceptions allowed {.push raises: [].} diff --git a/constantine/montgomery_magic.nim b/constantine/montgomery_magic.nim index ae53ab5..a5f161a 100644 --- a/constantine/montgomery_magic.nim +++ b/constantine/montgomery_magic.nim @@ -13,7 +13,7 @@ # ############################################################ import - ./word_types, ./bigints + ./primitives, ./bigints from bitops import fastLog2 # This will only be used at compile-time diff --git a/constantine/word_types.nim b/constantine/primitives.nim similarity index 97% rename from constantine/word_types.nim rename to constantine/primitives.nim index ea85c6f..9d672ef 100644 --- a/constantine/word_types.nim +++ b/constantine/primitives.nim @@ -6,6 +6,12 @@ # * Apache v2 license (license terms in the root directory or at http://www.apache.org/licenses/LICENSE-2.0). # at your option. This file may not be copied, modified, or distributed except according to those terms. +# ############################################################ +# +# Constant-time primitives +# +# ############################################################ + type BaseUint* = SomeUnsignedInt or byte diff --git a/constantine/private/word_types_internal.nim b/constantine/private/primitives_internal.nim similarity index 99% rename from constantine/private/word_types_internal.nim rename to constantine/private/primitives_internal.nim index bd294a1..ccc9f31 100644 --- a/constantine/private/word_types_internal.nim +++ b/constantine/private/primitives_internal.nim @@ -12,7 +12,7 @@ # # ############################################################ -import ../word_types +import ../primitives func asm_x86_64_extMul(hi, lo: var uint64, a, b: uint64) {.inline.}= ## Extended precision multiplication uint64 * uint64 --> uint128 diff --git a/tests/test_bigints.nim b/tests/test_bigints.nim index d56fb48..e698169 100644 --- a/tests/test_bigints.nim +++ b/tests/test_bigints.nim @@ -7,7 +7,7 @@ # at your option. This file may not be copied, modified, or distributed except according to those terms. import unittest, random, - ../constantine/[io, bigints, word_types] + ../constantine/[io, bigints, primitives] suite "isZero": test "isZero for zero": diff --git a/tests/test_field_fp.nim b/tests/test_field_fp.nim index 702e1e7..50f8cd4 100644 --- a/tests/test_field_fp.nim +++ b/tests/test_field_fp.nim @@ -7,4 +7,4 @@ # at your option. This file may not be copied, modified, or distributed except according to those terms. import unittest, random, - ../constantine/[io, bigints, word_types, field_fp] + ../constantine/[io, bigints, primitives, field_fp] diff --git a/tests/test_word_types.nim b/tests/test_primitives.nim similarity index 99% rename from tests/test_word_types.nim rename to tests/test_primitives.nim index 65af987..8606b03 100644 --- a/tests/test_word_types.nim +++ b/tests/test_primitives.nim @@ -7,7 +7,7 @@ # at your option. This file may not be copied, modified, or distributed except according to those terms. import unittest, random, math, - ../constantine/word_types + ../constantine/primitives # Random seed for reproducibility randomize(0xDEADBEEF)