Browse Source

Update to match 20160809.

 * Add the `torref` sampling variant controled by the global variable
  `TorSampling`.

Test vectors match the official code, assuming the official code is ran
on a little endian target.  I've contacted the original authors
regarding this, though I assume their behavior will match my
implementation on Big Endian hosts.
Yawning Angel 3 years ago
parent
commit
e1b0b04cac
6 changed files with 6118 additions and 24 deletions
  1. 929 0
      batcher.go
  2. 10 3
      newhope.go
  3. 44 4
      newhope_test.go
  4. 1 0
      newhope_testvectors_test.go
  5. 5065 0
      newhope_testvectors_tor_test.go
  6. 69 17
      poly.go

+ 929 - 0
batcher.go

@@ -0,0 +1,929 @@
+// batcher.go - Constant time polynomial sampler.
+//
+// To the extent possible under law, Yawning Angel has waived all copyright
+// and related or neighboring rights to newhope, using the Creative
+// Commons "CC0" public domain dedication. See LICENSE or
+// <http://creativecommons.org/publicdomain/zero/1.0/> for full details.
+
+package newhope
+
+func batcher84(x []uint16) {
+	// In theory this should probably be inlined.
+	compareAndSwap := func(x []uint16, i, j int) {
+		const _5q = 5 * paramQ
+		var c int32
+		var t uint16
+
+		c = _5q - 1 - int32(x[16*i])
+		c >>= 31
+		t = x[16*i] ^ x[16*j]
+		t &= uint16(c)
+		x[16*i] ^= t
+		x[16*j] ^= t
+	}
+
+	compareAndSwap(x, 0, 1)
+	compareAndSwap(x, 2, 3)
+	compareAndSwap(x, 0, 2)
+	compareAndSwap(x, 1, 3)
+	compareAndSwap(x, 1, 2)
+	compareAndSwap(x, 4, 5)
+	compareAndSwap(x, 6, 7)
+	compareAndSwap(x, 4, 6)
+	compareAndSwap(x, 5, 7)
+	compareAndSwap(x, 5, 6)
+	compareAndSwap(x, 0, 4)
+	compareAndSwap(x, 2, 6)
+	compareAndSwap(x, 2, 4)
+	compareAndSwap(x, 1, 5)
+	compareAndSwap(x, 3, 7)
+	compareAndSwap(x, 3, 5)
+	compareAndSwap(x, 1, 2)
+	compareAndSwap(x, 3, 4)
+	compareAndSwap(x, 5, 6)
+	compareAndSwap(x, 8, 9)
+	compareAndSwap(x, 10, 11)
+	compareAndSwap(x, 8, 10)
+	compareAndSwap(x, 9, 11)
+	compareAndSwap(x, 9, 10)
+	compareAndSwap(x, 12, 13)
+	compareAndSwap(x, 14, 15)
+	compareAndSwap(x, 12, 14)
+	compareAndSwap(x, 13, 15)
+	compareAndSwap(x, 13, 14)
+	compareAndSwap(x, 8, 12)
+	compareAndSwap(x, 10, 14)
+	compareAndSwap(x, 10, 12)
+	compareAndSwap(x, 9, 13)
+	compareAndSwap(x, 11, 15)
+	compareAndSwap(x, 11, 13)
+	compareAndSwap(x, 9, 10)
+	compareAndSwap(x, 11, 12)
+	compareAndSwap(x, 13, 14)
+	compareAndSwap(x, 0, 8)
+	compareAndSwap(x, 4, 12)
+	compareAndSwap(x, 4, 8)
+	compareAndSwap(x, 2, 10)
+	compareAndSwap(x, 6, 14)
+	compareAndSwap(x, 6, 10)
+	compareAndSwap(x, 2, 4)
+	compareAndSwap(x, 6, 8)
+	compareAndSwap(x, 10, 12)
+	compareAndSwap(x, 1, 9)
+	compareAndSwap(x, 5, 13)
+	compareAndSwap(x, 5, 9)
+	compareAndSwap(x, 3, 11)
+	compareAndSwap(x, 7, 15)
+	compareAndSwap(x, 7, 11)
+	compareAndSwap(x, 3, 5)
+	compareAndSwap(x, 7, 9)
+	compareAndSwap(x, 11, 13)
+	compareAndSwap(x, 1, 2)
+	compareAndSwap(x, 3, 4)
+	compareAndSwap(x, 5, 6)
+	compareAndSwap(x, 7, 8)
+	compareAndSwap(x, 9, 10)
+	compareAndSwap(x, 11, 12)
+	compareAndSwap(x, 13, 14)
+	compareAndSwap(x, 16, 17)
+	compareAndSwap(x, 18, 19)
+	compareAndSwap(x, 16, 18)
+	compareAndSwap(x, 17, 19)
+	compareAndSwap(x, 17, 18)
+	compareAndSwap(x, 20, 21)
+	compareAndSwap(x, 22, 23)
+	compareAndSwap(x, 20, 22)
+	compareAndSwap(x, 21, 23)
+	compareAndSwap(x, 21, 22)
+	compareAndSwap(x, 16, 20)
+	compareAndSwap(x, 18, 22)
+	compareAndSwap(x, 18, 20)
+	compareAndSwap(x, 17, 21)
+	compareAndSwap(x, 19, 23)
+	compareAndSwap(x, 19, 21)
+	compareAndSwap(x, 17, 18)
+	compareAndSwap(x, 19, 20)
+	compareAndSwap(x, 21, 22)
+	compareAndSwap(x, 24, 25)
+	compareAndSwap(x, 26, 27)
+	compareAndSwap(x, 24, 26)
+	compareAndSwap(x, 25, 27)
+	compareAndSwap(x, 25, 26)
+	compareAndSwap(x, 28, 29)
+	compareAndSwap(x, 30, 31)
+	compareAndSwap(x, 28, 30)
+	compareAndSwap(x, 29, 31)
+	compareAndSwap(x, 29, 30)
+	compareAndSwap(x, 24, 28)
+	compareAndSwap(x, 26, 30)
+	compareAndSwap(x, 26, 28)
+	compareAndSwap(x, 25, 29)
+	compareAndSwap(x, 27, 31)
+	compareAndSwap(x, 27, 29)
+	compareAndSwap(x, 25, 26)
+	compareAndSwap(x, 27, 28)
+	compareAndSwap(x, 29, 30)
+	compareAndSwap(x, 16, 24)
+	compareAndSwap(x, 20, 28)
+	compareAndSwap(x, 20, 24)
+	compareAndSwap(x, 18, 26)
+	compareAndSwap(x, 22, 30)
+	compareAndSwap(x, 22, 26)
+	compareAndSwap(x, 18, 20)
+	compareAndSwap(x, 22, 24)
+	compareAndSwap(x, 26, 28)
+	compareAndSwap(x, 17, 25)
+	compareAndSwap(x, 21, 29)
+	compareAndSwap(x, 21, 25)
+	compareAndSwap(x, 19, 27)
+	compareAndSwap(x, 23, 31)
+	compareAndSwap(x, 23, 27)
+	compareAndSwap(x, 19, 21)
+	compareAndSwap(x, 23, 25)
+	compareAndSwap(x, 27, 29)
+	compareAndSwap(x, 17, 18)
+	compareAndSwap(x, 19, 20)
+	compareAndSwap(x, 21, 22)
+	compareAndSwap(x, 23, 24)
+	compareAndSwap(x, 25, 26)
+	compareAndSwap(x, 27, 28)
+	compareAndSwap(x, 29, 30)
+	compareAndSwap(x, 0, 16)
+	compareAndSwap(x, 8, 24)
+	compareAndSwap(x, 8, 16)
+	compareAndSwap(x, 4, 20)
+	compareAndSwap(x, 12, 28)
+	compareAndSwap(x, 12, 20)
+	compareAndSwap(x, 4, 8)
+	compareAndSwap(x, 12, 16)
+	compareAndSwap(x, 20, 24)
+	compareAndSwap(x, 2, 18)
+	compareAndSwap(x, 10, 26)
+	compareAndSwap(x, 10, 18)
+	compareAndSwap(x, 6, 22)
+	compareAndSwap(x, 14, 30)
+	compareAndSwap(x, 14, 22)
+	compareAndSwap(x, 6, 10)
+	compareAndSwap(x, 14, 18)
+	compareAndSwap(x, 22, 26)
+	compareAndSwap(x, 2, 4)
+	compareAndSwap(x, 6, 8)
+	compareAndSwap(x, 10, 12)
+	compareAndSwap(x, 14, 16)
+	compareAndSwap(x, 18, 20)
+	compareAndSwap(x, 22, 24)
+	compareAndSwap(x, 26, 28)
+	compareAndSwap(x, 1, 17)
+	compareAndSwap(x, 9, 25)
+	compareAndSwap(x, 9, 17)
+	compareAndSwap(x, 5, 21)
+	compareAndSwap(x, 13, 29)
+	compareAndSwap(x, 13, 21)
+	compareAndSwap(x, 5, 9)
+	compareAndSwap(x, 13, 17)
+	compareAndSwap(x, 21, 25)
+	compareAndSwap(x, 3, 19)
+	compareAndSwap(x, 11, 27)
+	compareAndSwap(x, 11, 19)
+	compareAndSwap(x, 7, 23)
+	compareAndSwap(x, 15, 31)
+	compareAndSwap(x, 15, 23)
+	compareAndSwap(x, 7, 11)
+	compareAndSwap(x, 15, 19)
+	compareAndSwap(x, 23, 27)
+	compareAndSwap(x, 3, 5)
+	compareAndSwap(x, 7, 9)
+	compareAndSwap(x, 11, 13)
+	compareAndSwap(x, 15, 17)
+	compareAndSwap(x, 19, 21)
+	compareAndSwap(x, 23, 25)
+	compareAndSwap(x, 27, 29)
+	compareAndSwap(x, 1, 2)
+	compareAndSwap(x, 3, 4)
+	compareAndSwap(x, 5, 6)
+	compareAndSwap(x, 7, 8)
+	compareAndSwap(x, 9, 10)
+	compareAndSwap(x, 11, 12)
+	compareAndSwap(x, 13, 14)
+	compareAndSwap(x, 15, 16)
+	compareAndSwap(x, 17, 18)
+	compareAndSwap(x, 19, 20)
+	compareAndSwap(x, 21, 22)
+	compareAndSwap(x, 23, 24)
+	compareAndSwap(x, 25, 26)
+	compareAndSwap(x, 27, 28)
+	compareAndSwap(x, 29, 30)
+	compareAndSwap(x, 32, 33)
+	compareAndSwap(x, 34, 35)
+	compareAndSwap(x, 32, 34)
+	compareAndSwap(x, 33, 35)
+	compareAndSwap(x, 33, 34)
+	compareAndSwap(x, 36, 37)
+	compareAndSwap(x, 38, 39)
+	compareAndSwap(x, 36, 38)
+	compareAndSwap(x, 37, 39)
+	compareAndSwap(x, 37, 38)
+	compareAndSwap(x, 32, 36)
+	compareAndSwap(x, 34, 38)
+	compareAndSwap(x, 34, 36)
+	compareAndSwap(x, 33, 37)
+	compareAndSwap(x, 35, 39)
+	compareAndSwap(x, 35, 37)
+	compareAndSwap(x, 33, 34)
+	compareAndSwap(x, 35, 36)
+	compareAndSwap(x, 37, 38)
+	compareAndSwap(x, 40, 41)
+	compareAndSwap(x, 42, 43)
+	compareAndSwap(x, 40, 42)
+	compareAndSwap(x, 41, 43)
+	compareAndSwap(x, 41, 42)
+	compareAndSwap(x, 44, 45)
+	compareAndSwap(x, 46, 47)
+	compareAndSwap(x, 44, 46)
+	compareAndSwap(x, 45, 47)
+	compareAndSwap(x, 45, 46)
+	compareAndSwap(x, 40, 44)
+	compareAndSwap(x, 42, 46)
+	compareAndSwap(x, 42, 44)
+	compareAndSwap(x, 41, 45)
+	compareAndSwap(x, 43, 47)
+	compareAndSwap(x, 43, 45)
+	compareAndSwap(x, 41, 42)
+	compareAndSwap(x, 43, 44)
+	compareAndSwap(x, 45, 46)
+	compareAndSwap(x, 32, 40)
+	compareAndSwap(x, 36, 44)
+	compareAndSwap(x, 36, 40)
+	compareAndSwap(x, 34, 42)
+	compareAndSwap(x, 38, 46)
+	compareAndSwap(x, 38, 42)
+	compareAndSwap(x, 34, 36)
+	compareAndSwap(x, 38, 40)
+	compareAndSwap(x, 42, 44)
+	compareAndSwap(x, 33, 41)
+	compareAndSwap(x, 37, 45)
+	compareAndSwap(x, 37, 41)
+	compareAndSwap(x, 35, 43)
+	compareAndSwap(x, 39, 47)
+	compareAndSwap(x, 39, 43)
+	compareAndSwap(x, 35, 37)
+	compareAndSwap(x, 39, 41)
+	compareAndSwap(x, 43, 45)
+	compareAndSwap(x, 33, 34)
+	compareAndSwap(x, 35, 36)
+	compareAndSwap(x, 37, 38)
+	compareAndSwap(x, 39, 40)
+	compareAndSwap(x, 41, 42)
+	compareAndSwap(x, 43, 44)
+	compareAndSwap(x, 45, 46)
+	compareAndSwap(x, 48, 49)
+	compareAndSwap(x, 50, 51)
+	compareAndSwap(x, 48, 50)
+	compareAndSwap(x, 49, 51)
+	compareAndSwap(x, 49, 50)
+	compareAndSwap(x, 52, 53)
+	compareAndSwap(x, 54, 55)
+	compareAndSwap(x, 52, 54)
+	compareAndSwap(x, 53, 55)
+	compareAndSwap(x, 53, 54)
+	compareAndSwap(x, 48, 52)
+	compareAndSwap(x, 50, 54)
+	compareAndSwap(x, 50, 52)
+	compareAndSwap(x, 49, 53)
+	compareAndSwap(x, 51, 55)
+	compareAndSwap(x, 51, 53)
+	compareAndSwap(x, 49, 50)
+	compareAndSwap(x, 51, 52)
+	compareAndSwap(x, 53, 54)
+	compareAndSwap(x, 56, 57)
+	compareAndSwap(x, 58, 59)
+	compareAndSwap(x, 56, 58)
+	compareAndSwap(x, 57, 59)
+	compareAndSwap(x, 57, 58)
+	compareAndSwap(x, 60, 61)
+	compareAndSwap(x, 62, 63)
+	compareAndSwap(x, 60, 62)
+	compareAndSwap(x, 61, 63)
+	compareAndSwap(x, 61, 62)
+	compareAndSwap(x, 56, 60)
+	compareAndSwap(x, 58, 62)
+	compareAndSwap(x, 58, 60)
+	compareAndSwap(x, 57, 61)
+	compareAndSwap(x, 59, 63)
+	compareAndSwap(x, 59, 61)
+	compareAndSwap(x, 57, 58)
+	compareAndSwap(x, 59, 60)
+	compareAndSwap(x, 61, 62)
+	compareAndSwap(x, 48, 56)
+	compareAndSwap(x, 52, 60)
+	compareAndSwap(x, 52, 56)
+	compareAndSwap(x, 50, 58)
+	compareAndSwap(x, 54, 62)
+	compareAndSwap(x, 54, 58)
+	compareAndSwap(x, 50, 52)
+	compareAndSwap(x, 54, 56)
+	compareAndSwap(x, 58, 60)
+	compareAndSwap(x, 49, 57)
+	compareAndSwap(x, 53, 61)
+	compareAndSwap(x, 53, 57)
+	compareAndSwap(x, 51, 59)
+	compareAndSwap(x, 55, 63)
+	compareAndSwap(x, 55, 59)
+	compareAndSwap(x, 51, 53)
+	compareAndSwap(x, 55, 57)
+	compareAndSwap(x, 59, 61)
+	compareAndSwap(x, 49, 50)
+	compareAndSwap(x, 51, 52)
+	compareAndSwap(x, 53, 54)
+	compareAndSwap(x, 55, 56)
+	compareAndSwap(x, 57, 58)
+	compareAndSwap(x, 59, 60)
+	compareAndSwap(x, 61, 62)
+	compareAndSwap(x, 32, 48)
+	compareAndSwap(x, 40, 56)
+	compareAndSwap(x, 40, 48)
+	compareAndSwap(x, 36, 52)
+	compareAndSwap(x, 44, 60)
+	compareAndSwap(x, 44, 52)
+	compareAndSwap(x, 36, 40)
+	compareAndSwap(x, 44, 48)
+	compareAndSwap(x, 52, 56)
+	compareAndSwap(x, 34, 50)
+	compareAndSwap(x, 42, 58)
+	compareAndSwap(x, 42, 50)
+	compareAndSwap(x, 38, 54)
+	compareAndSwap(x, 46, 62)
+	compareAndSwap(x, 46, 54)
+	compareAndSwap(x, 38, 42)
+	compareAndSwap(x, 46, 50)
+	compareAndSwap(x, 54, 58)
+	compareAndSwap(x, 34, 36)
+	compareAndSwap(x, 38, 40)
+	compareAndSwap(x, 42, 44)
+	compareAndSwap(x, 46, 48)
+	compareAndSwap(x, 50, 52)
+	compareAndSwap(x, 54, 56)
+	compareAndSwap(x, 58, 60)
+	compareAndSwap(x, 33, 49)
+	compareAndSwap(x, 41, 57)
+	compareAndSwap(x, 41, 49)
+	compareAndSwap(x, 37, 53)
+	compareAndSwap(x, 45, 61)
+	compareAndSwap(x, 45, 53)
+	compareAndSwap(x, 37, 41)
+	compareAndSwap(x, 45, 49)
+	compareAndSwap(x, 53, 57)
+	compareAndSwap(x, 35, 51)
+	compareAndSwap(x, 43, 59)
+	compareAndSwap(x, 43, 51)
+	compareAndSwap(x, 39, 55)
+	compareAndSwap(x, 47, 63)
+	compareAndSwap(x, 47, 55)
+	compareAndSwap(x, 39, 43)
+	compareAndSwap(x, 47, 51)
+	compareAndSwap(x, 55, 59)
+	compareAndSwap(x, 35, 37)
+	compareAndSwap(x, 39, 41)
+	compareAndSwap(x, 43, 45)
+	compareAndSwap(x, 47, 49)
+	compareAndSwap(x, 51, 53)
+	compareAndSwap(x, 55, 57)
+	compareAndSwap(x, 59, 61)
+	compareAndSwap(x, 33, 34)
+	compareAndSwap(x, 35, 36)
+	compareAndSwap(x, 37, 38)
+	compareAndSwap(x, 39, 40)
+	compareAndSwap(x, 41, 42)
+	compareAndSwap(x, 43, 44)
+	compareAndSwap(x, 45, 46)
+	compareAndSwap(x, 47, 48)
+	compareAndSwap(x, 49, 50)
+	compareAndSwap(x, 51, 52)
+	compareAndSwap(x, 53, 54)
+	compareAndSwap(x, 55, 56)
+	compareAndSwap(x, 57, 58)
+	compareAndSwap(x, 59, 60)
+	compareAndSwap(x, 61, 62)
+	compareAndSwap(x, 0, 32)
+	compareAndSwap(x, 16, 48)
+	compareAndSwap(x, 16, 32)
+	compareAndSwap(x, 8, 40)
+	compareAndSwap(x, 24, 56)
+	compareAndSwap(x, 24, 40)
+	compareAndSwap(x, 8, 16)
+	compareAndSwap(x, 24, 32)
+	compareAndSwap(x, 40, 48)
+	compareAndSwap(x, 4, 36)
+	compareAndSwap(x, 20, 52)
+	compareAndSwap(x, 20, 36)
+	compareAndSwap(x, 12, 44)
+	compareAndSwap(x, 28, 60)
+	compareAndSwap(x, 28, 44)
+	compareAndSwap(x, 12, 20)
+	compareAndSwap(x, 28, 36)
+	compareAndSwap(x, 44, 52)
+	compareAndSwap(x, 4, 8)
+	compareAndSwap(x, 12, 16)
+	compareAndSwap(x, 20, 24)
+	compareAndSwap(x, 28, 32)
+	compareAndSwap(x, 36, 40)
+	compareAndSwap(x, 44, 48)
+	compareAndSwap(x, 52, 56)
+	compareAndSwap(x, 2, 34)
+	compareAndSwap(x, 18, 50)
+	compareAndSwap(x, 18, 34)
+	compareAndSwap(x, 10, 42)
+	compareAndSwap(x, 26, 58)
+	compareAndSwap(x, 26, 42)
+	compareAndSwap(x, 10, 18)
+	compareAndSwap(x, 26, 34)
+	compareAndSwap(x, 42, 50)
+	compareAndSwap(x, 6, 38)
+	compareAndSwap(x, 22, 54)
+	compareAndSwap(x, 22, 38)
+	compareAndSwap(x, 14, 46)
+	compareAndSwap(x, 30, 62)
+	compareAndSwap(x, 30, 46)
+	compareAndSwap(x, 14, 22)
+	compareAndSwap(x, 30, 38)
+	compareAndSwap(x, 46, 54)
+	compareAndSwap(x, 6, 10)
+	compareAndSwap(x, 14, 18)
+	compareAndSwap(x, 22, 26)
+	compareAndSwap(x, 30, 34)
+	compareAndSwap(x, 38, 42)
+	compareAndSwap(x, 46, 50)
+	compareAndSwap(x, 54, 58)
+	compareAndSwap(x, 2, 4)
+	compareAndSwap(x, 6, 8)
+	compareAndSwap(x, 10, 12)
+	compareAndSwap(x, 14, 16)
+	compareAndSwap(x, 18, 20)
+	compareAndSwap(x, 22, 24)
+	compareAndSwap(x, 26, 28)
+	compareAndSwap(x, 30, 32)
+	compareAndSwap(x, 34, 36)
+	compareAndSwap(x, 38, 40)
+	compareAndSwap(x, 42, 44)
+	compareAndSwap(x, 46, 48)
+	compareAndSwap(x, 50, 52)
+	compareAndSwap(x, 54, 56)
+	compareAndSwap(x, 58, 60)
+	compareAndSwap(x, 1, 33)
+	compareAndSwap(x, 17, 49)
+	compareAndSwap(x, 17, 33)
+	compareAndSwap(x, 9, 41)
+	compareAndSwap(x, 25, 57)
+	compareAndSwap(x, 25, 41)
+	compareAndSwap(x, 9, 17)
+	compareAndSwap(x, 25, 33)
+	compareAndSwap(x, 41, 49)
+	compareAndSwap(x, 5, 37)
+	compareAndSwap(x, 21, 53)
+	compareAndSwap(x, 21, 37)
+	compareAndSwap(x, 13, 45)
+	compareAndSwap(x, 29, 61)
+	compareAndSwap(x, 29, 45)
+	compareAndSwap(x, 13, 21)
+	compareAndSwap(x, 29, 37)
+	compareAndSwap(x, 45, 53)
+	compareAndSwap(x, 5, 9)
+	compareAndSwap(x, 13, 17)
+	compareAndSwap(x, 21, 25)
+	compareAndSwap(x, 29, 33)
+	compareAndSwap(x, 37, 41)
+	compareAndSwap(x, 45, 49)
+	compareAndSwap(x, 53, 57)
+	compareAndSwap(x, 3, 35)
+	compareAndSwap(x, 19, 51)
+	compareAndSwap(x, 19, 35)
+	compareAndSwap(x, 11, 43)
+	compareAndSwap(x, 27, 59)
+	compareAndSwap(x, 27, 43)
+	compareAndSwap(x, 11, 19)
+	compareAndSwap(x, 27, 35)
+	compareAndSwap(x, 43, 51)
+	compareAndSwap(x, 7, 39)
+	compareAndSwap(x, 23, 55)
+	compareAndSwap(x, 23, 39)
+	compareAndSwap(x, 15, 47)
+	compareAndSwap(x, 31, 63)
+	compareAndSwap(x, 31, 47)
+	compareAndSwap(x, 15, 23)
+	compareAndSwap(x, 31, 39)
+	compareAndSwap(x, 47, 55)
+	compareAndSwap(x, 7, 11)
+	compareAndSwap(x, 15, 19)
+	compareAndSwap(x, 23, 27)
+	compareAndSwap(x, 31, 35)
+	compareAndSwap(x, 39, 43)
+	compareAndSwap(x, 47, 51)
+	compareAndSwap(x, 55, 59)
+	compareAndSwap(x, 3, 5)
+	compareAndSwap(x, 7, 9)
+	compareAndSwap(x, 11, 13)
+	compareAndSwap(x, 15, 17)
+	compareAndSwap(x, 19, 21)
+	compareAndSwap(x, 23, 25)
+	compareAndSwap(x, 27, 29)
+	compareAndSwap(x, 31, 33)
+	compareAndSwap(x, 35, 37)
+	compareAndSwap(x, 39, 41)
+	compareAndSwap(x, 43, 45)
+	compareAndSwap(x, 47, 49)
+	compareAndSwap(x, 51, 53)
+	compareAndSwap(x, 55, 57)
+	compareAndSwap(x, 59, 61)
+	compareAndSwap(x, 1, 2)
+	compareAndSwap(x, 3, 4)
+	compareAndSwap(x, 5, 6)
+	compareAndSwap(x, 7, 8)
+	compareAndSwap(x, 9, 10)
+	compareAndSwap(x, 11, 12)
+	compareAndSwap(x, 13, 14)
+	compareAndSwap(x, 15, 16)
+	compareAndSwap(x, 17, 18)
+	compareAndSwap(x, 19, 20)
+	compareAndSwap(x, 21, 22)
+	compareAndSwap(x, 23, 24)
+	compareAndSwap(x, 25, 26)
+	compareAndSwap(x, 27, 28)
+	compareAndSwap(x, 29, 30)
+	compareAndSwap(x, 31, 32)
+	compareAndSwap(x, 33, 34)
+	compareAndSwap(x, 35, 36)
+	compareAndSwap(x, 37, 38)
+	compareAndSwap(x, 39, 40)
+	compareAndSwap(x, 41, 42)
+	compareAndSwap(x, 43, 44)
+	compareAndSwap(x, 45, 46)
+	compareAndSwap(x, 47, 48)
+	compareAndSwap(x, 49, 50)
+	compareAndSwap(x, 51, 52)
+	compareAndSwap(x, 53, 54)
+	compareAndSwap(x, 55, 56)
+	compareAndSwap(x, 57, 58)
+	compareAndSwap(x, 59, 60)
+	compareAndSwap(x, 61, 62)
+	compareAndSwap(x, 64, 65)
+	compareAndSwap(x, 66, 67)
+	compareAndSwap(x, 64, 66)
+	compareAndSwap(x, 65, 67)
+	compareAndSwap(x, 65, 66)
+	compareAndSwap(x, 68, 69)
+	compareAndSwap(x, 70, 71)
+	compareAndSwap(x, 68, 70)
+	compareAndSwap(x, 69, 71)
+	compareAndSwap(x, 69, 70)
+	compareAndSwap(x, 64, 68)
+	compareAndSwap(x, 66, 70)
+	compareAndSwap(x, 66, 68)
+	compareAndSwap(x, 65, 69)
+	compareAndSwap(x, 67, 71)
+	compareAndSwap(x, 67, 69)
+	compareAndSwap(x, 65, 66)
+	compareAndSwap(x, 67, 68)
+	compareAndSwap(x, 69, 70)
+	compareAndSwap(x, 72, 73)
+	compareAndSwap(x, 74, 75)
+	compareAndSwap(x, 72, 74)
+	compareAndSwap(x, 73, 75)
+	compareAndSwap(x, 73, 74)
+	compareAndSwap(x, 76, 77)
+	compareAndSwap(x, 78, 79)
+	compareAndSwap(x, 76, 78)
+	compareAndSwap(x, 77, 79)
+	compareAndSwap(x, 77, 78)
+	compareAndSwap(x, 72, 76)
+	compareAndSwap(x, 74, 78)
+	compareAndSwap(x, 74, 76)
+	compareAndSwap(x, 73, 77)
+	compareAndSwap(x, 75, 79)
+	compareAndSwap(x, 75, 77)
+	compareAndSwap(x, 73, 74)
+	compareAndSwap(x, 75, 76)
+	compareAndSwap(x, 77, 78)
+	compareAndSwap(x, 64, 72)
+	compareAndSwap(x, 68, 76)
+	compareAndSwap(x, 68, 72)
+	compareAndSwap(x, 66, 74)
+	compareAndSwap(x, 70, 78)
+	compareAndSwap(x, 70, 74)
+	compareAndSwap(x, 66, 68)
+	compareAndSwap(x, 70, 72)
+	compareAndSwap(x, 74, 76)
+	compareAndSwap(x, 65, 73)
+	compareAndSwap(x, 69, 77)
+	compareAndSwap(x, 69, 73)
+	compareAndSwap(x, 67, 75)
+	compareAndSwap(x, 71, 79)
+	compareAndSwap(x, 71, 75)
+	compareAndSwap(x, 67, 69)
+	compareAndSwap(x, 71, 73)
+	compareAndSwap(x, 75, 77)
+	compareAndSwap(x, 65, 66)
+	compareAndSwap(x, 67, 68)
+	compareAndSwap(x, 69, 70)
+	compareAndSwap(x, 71, 72)
+	compareAndSwap(x, 73, 74)
+	compareAndSwap(x, 75, 76)
+	compareAndSwap(x, 77, 78)
+	compareAndSwap(x, 80, 81)
+	compareAndSwap(x, 82, 83)
+	compareAndSwap(x, 80, 82)
+	compareAndSwap(x, 81, 83)
+	compareAndSwap(x, 81, 82)
+	compareAndSwap(x, 81, 82)
+	compareAndSwap(x, 81, 82)
+	compareAndSwap(x, 64, 80)
+	compareAndSwap(x, 72, 80)
+	compareAndSwap(x, 68, 72)
+	compareAndSwap(x, 76, 80)
+	compareAndSwap(x, 66, 82)
+	compareAndSwap(x, 74, 82)
+	compareAndSwap(x, 70, 74)
+	compareAndSwap(x, 78, 82)
+	compareAndSwap(x, 66, 68)
+	compareAndSwap(x, 70, 72)
+	compareAndSwap(x, 74, 76)
+	compareAndSwap(x, 78, 80)
+	compareAndSwap(x, 65, 81)
+	compareAndSwap(x, 73, 81)
+	compareAndSwap(x, 69, 73)
+	compareAndSwap(x, 77, 81)
+	compareAndSwap(x, 67, 83)
+	compareAndSwap(x, 75, 83)
+	compareAndSwap(x, 71, 75)
+	compareAndSwap(x, 79, 83)
+	compareAndSwap(x, 67, 69)
+	compareAndSwap(x, 71, 73)
+	compareAndSwap(x, 75, 77)
+	compareAndSwap(x, 79, 81)
+	compareAndSwap(x, 65, 66)
+	compareAndSwap(x, 67, 68)
+	compareAndSwap(x, 69, 70)
+	compareAndSwap(x, 71, 72)
+	compareAndSwap(x, 73, 74)
+	compareAndSwap(x, 75, 76)
+	compareAndSwap(x, 77, 78)
+	compareAndSwap(x, 79, 80)
+	compareAndSwap(x, 81, 82)
+	compareAndSwap(x, 72, 80)
+	compareAndSwap(x, 68, 72)
+	compareAndSwap(x, 76, 80)
+	compareAndSwap(x, 74, 82)
+	compareAndSwap(x, 70, 74)
+	compareAndSwap(x, 78, 82)
+	compareAndSwap(x, 66, 68)
+	compareAndSwap(x, 70, 72)
+	compareAndSwap(x, 74, 76)
+	compareAndSwap(x, 78, 80)
+	compareAndSwap(x, 73, 81)
+	compareAndSwap(x, 69, 73)
+	compareAndSwap(x, 77, 81)
+	compareAndSwap(x, 75, 83)
+	compareAndSwap(x, 71, 75)
+	compareAndSwap(x, 79, 83)
+	compareAndSwap(x, 67, 69)
+	compareAndSwap(x, 71, 73)
+	compareAndSwap(x, 75, 77)
+	compareAndSwap(x, 79, 81)
+	compareAndSwap(x, 65, 66)
+	compareAndSwap(x, 67, 68)
+	compareAndSwap(x, 69, 70)
+	compareAndSwap(x, 71, 72)
+	compareAndSwap(x, 73, 74)
+	compareAndSwap(x, 75, 76)
+	compareAndSwap(x, 77, 78)
+	compareAndSwap(x, 79, 80)
+	compareAndSwap(x, 81, 82)
+	compareAndSwap(x, 0, 64)
+	compareAndSwap(x, 32, 64)
+	compareAndSwap(x, 16, 80)
+	compareAndSwap(x, 48, 80)
+	compareAndSwap(x, 16, 32)
+	compareAndSwap(x, 48, 64)
+	compareAndSwap(x, 8, 72)
+	compareAndSwap(x, 40, 72)
+	compareAndSwap(x, 24, 40)
+	compareAndSwap(x, 56, 72)
+	compareAndSwap(x, 8, 16)
+	compareAndSwap(x, 24, 32)
+	compareAndSwap(x, 40, 48)
+	compareAndSwap(x, 56, 64)
+	compareAndSwap(x, 72, 80)
+	compareAndSwap(x, 4, 68)
+	compareAndSwap(x, 36, 68)
+	compareAndSwap(x, 20, 36)
+	compareAndSwap(x, 52, 68)
+	compareAndSwap(x, 12, 76)
+	compareAndSwap(x, 44, 76)
+	compareAndSwap(x, 28, 44)
+	compareAndSwap(x, 60, 76)
+	compareAndSwap(x, 12, 20)
+	compareAndSwap(x, 28, 36)
+	compareAndSwap(x, 44, 52)
+	compareAndSwap(x, 60, 68)
+	compareAndSwap(x, 4, 8)
+	compareAndSwap(x, 12, 16)
+	compareAndSwap(x, 20, 24)
+	compareAndSwap(x, 28, 32)
+	compareAndSwap(x, 36, 40)
+	compareAndSwap(x, 44, 48)
+	compareAndSwap(x, 52, 56)
+	compareAndSwap(x, 60, 64)
+	compareAndSwap(x, 68, 72)
+	compareAndSwap(x, 76, 80)
+	compareAndSwap(x, 2, 66)
+	compareAndSwap(x, 34, 66)
+	compareAndSwap(x, 18, 82)
+	compareAndSwap(x, 50, 82)
+	compareAndSwap(x, 18, 34)
+	compareAndSwap(x, 50, 66)
+	compareAndSwap(x, 10, 74)
+	compareAndSwap(x, 42, 74)
+	compareAndSwap(x, 26, 42)
+	compareAndSwap(x, 58, 74)
+	compareAndSwap(x, 10, 18)
+	compareAndSwap(x, 26, 34)
+	compareAndSwap(x, 42, 50)
+	compareAndSwap(x, 58, 66)
+	compareAndSwap(x, 74, 82)
+	compareAndSwap(x, 6, 70)
+	compareAndSwap(x, 38, 70)
+	compareAndSwap(x, 22, 38)
+	compareAndSwap(x, 54, 70)
+	compareAndSwap(x, 14, 78)
+	compareAndSwap(x, 46, 78)
+	compareAndSwap(x, 30, 46)
+	compareAndSwap(x, 62, 78)
+	compareAndSwap(x, 14, 22)
+	compareAndSwap(x, 30, 38)
+	compareAndSwap(x, 46, 54)
+	compareAndSwap(x, 62, 70)
+	compareAndSwap(x, 6, 10)
+	compareAndSwap(x, 14, 18)
+	compareAndSwap(x, 22, 26)
+	compareAndSwap(x, 30, 34)
+	compareAndSwap(x, 38, 42)
+	compareAndSwap(x, 46, 50)
+	compareAndSwap(x, 54, 58)
+	compareAndSwap(x, 62, 66)
+	compareAndSwap(x, 70, 74)
+	compareAndSwap(x, 78, 82)
+	compareAndSwap(x, 2, 4)
+	compareAndSwap(x, 6, 8)
+	compareAndSwap(x, 10, 12)
+	compareAndSwap(x, 14, 16)
+	compareAndSwap(x, 18, 20)
+	compareAndSwap(x, 22, 24)
+	compareAndSwap(x, 26, 28)
+	compareAndSwap(x, 30, 32)
+	compareAndSwap(x, 34, 36)
+	compareAndSwap(x, 38, 40)
+	compareAndSwap(x, 42, 44)
+	compareAndSwap(x, 46, 48)
+	compareAndSwap(x, 50, 52)
+	compareAndSwap(x, 54, 56)
+	compareAndSwap(x, 58, 60)
+	compareAndSwap(x, 62, 64)
+	compareAndSwap(x, 66, 68)
+	compareAndSwap(x, 70, 72)
+	compareAndSwap(x, 74, 76)
+	compareAndSwap(x, 78, 80)
+	compareAndSwap(x, 1, 65)
+	compareAndSwap(x, 33, 65)
+	compareAndSwap(x, 17, 81)
+	compareAndSwap(x, 49, 81)
+	compareAndSwap(x, 17, 33)
+	compareAndSwap(x, 49, 65)
+	compareAndSwap(x, 9, 73)
+	compareAndSwap(x, 41, 73)
+	compareAndSwap(x, 25, 41)
+	compareAndSwap(x, 57, 73)
+	compareAndSwap(x, 9, 17)
+	compareAndSwap(x, 25, 33)
+	compareAndSwap(x, 41, 49)
+	compareAndSwap(x, 57, 65)
+	compareAndSwap(x, 73, 81)
+	compareAndSwap(x, 5, 69)
+	compareAndSwap(x, 37, 69)
+	compareAndSwap(x, 21, 37)
+	compareAndSwap(x, 53, 69)
+	compareAndSwap(x, 13, 77)
+	compareAndSwap(x, 45, 77)
+	compareAndSwap(x, 29, 45)
+	compareAndSwap(x, 61, 77)
+	compareAndSwap(x, 13, 21)
+	compareAndSwap(x, 29, 37)
+	compareAndSwap(x, 45, 53)
+	compareAndSwap(x, 61, 69)
+	compareAndSwap(x, 5, 9)
+	compareAndSwap(x, 13, 17)
+	compareAndSwap(x, 21, 25)
+	compareAndSwap(x, 29, 33)
+	compareAndSwap(x, 37, 41)
+	compareAndSwap(x, 45, 49)
+	compareAndSwap(x, 53, 57)
+	compareAndSwap(x, 61, 65)
+	compareAndSwap(x, 69, 73)
+	compareAndSwap(x, 77, 81)
+	compareAndSwap(x, 3, 67)
+	compareAndSwap(x, 35, 67)
+	compareAndSwap(x, 19, 83)
+	compareAndSwap(x, 51, 83)
+	compareAndSwap(x, 19, 35)
+	compareAndSwap(x, 51, 67)
+	compareAndSwap(x, 11, 75)
+	compareAndSwap(x, 43, 75)
+	compareAndSwap(x, 27, 43)
+	compareAndSwap(x, 59, 75)
+	compareAndSwap(x, 11, 19)
+	compareAndSwap(x, 27, 35)
+	compareAndSwap(x, 43, 51)
+	compareAndSwap(x, 59, 67)
+	compareAndSwap(x, 75, 83)
+	compareAndSwap(x, 7, 71)
+	compareAndSwap(x, 39, 71)
+	compareAndSwap(x, 23, 39)
+	compareAndSwap(x, 55, 71)
+	compareAndSwap(x, 15, 79)
+	compareAndSwap(x, 47, 79)
+	compareAndSwap(x, 31, 47)
+	compareAndSwap(x, 63, 79)
+	compareAndSwap(x, 15, 23)
+	compareAndSwap(x, 31, 39)
+	compareAndSwap(x, 47, 55)
+	compareAndSwap(x, 63, 71)
+	compareAndSwap(x, 7, 11)
+	compareAndSwap(x, 15, 19)
+	compareAndSwap(x, 23, 27)
+	compareAndSwap(x, 31, 35)
+	compareAndSwap(x, 39, 43)
+	compareAndSwap(x, 47, 51)
+	compareAndSwap(x, 55, 59)
+	compareAndSwap(x, 63, 67)
+	compareAndSwap(x, 71, 75)
+	compareAndSwap(x, 79, 83)
+	compareAndSwap(x, 3, 5)
+	compareAndSwap(x, 7, 9)
+	compareAndSwap(x, 11, 13)
+	compareAndSwap(x, 15, 17)
+	compareAndSwap(x, 19, 21)
+	compareAndSwap(x, 23, 25)
+	compareAndSwap(x, 27, 29)
+	compareAndSwap(x, 31, 33)
+	compareAndSwap(x, 35, 37)
+	compareAndSwap(x, 39, 41)
+	compareAndSwap(x, 43, 45)
+	compareAndSwap(x, 47, 49)
+	compareAndSwap(x, 51, 53)
+	compareAndSwap(x, 55, 57)
+	compareAndSwap(x, 59, 61)
+	compareAndSwap(x, 63, 65)
+	compareAndSwap(x, 67, 69)
+	compareAndSwap(x, 71, 73)
+	compareAndSwap(x, 75, 77)
+	compareAndSwap(x, 79, 81)
+	compareAndSwap(x, 1, 2)
+	compareAndSwap(x, 3, 4)
+	compareAndSwap(x, 5, 6)
+	compareAndSwap(x, 7, 8)
+	compareAndSwap(x, 9, 10)
+	compareAndSwap(x, 11, 12)
+	compareAndSwap(x, 13, 14)
+	compareAndSwap(x, 15, 16)
+	compareAndSwap(x, 17, 18)
+	compareAndSwap(x, 19, 20)
+	compareAndSwap(x, 21, 22)
+	compareAndSwap(x, 23, 24)
+	compareAndSwap(x, 25, 26)
+	compareAndSwap(x, 27, 28)
+	compareAndSwap(x, 29, 30)
+	compareAndSwap(x, 31, 32)
+	compareAndSwap(x, 33, 34)
+	compareAndSwap(x, 35, 36)
+	compareAndSwap(x, 37, 38)
+	compareAndSwap(x, 39, 40)
+	compareAndSwap(x, 41, 42)
+	compareAndSwap(x, 43, 44)
+	compareAndSwap(x, 45, 46)
+	compareAndSwap(x, 47, 48)
+	compareAndSwap(x, 49, 50)
+	compareAndSwap(x, 51, 52)
+	compareAndSwap(x, 53, 54)
+	compareAndSwap(x, 55, 56)
+	compareAndSwap(x, 57, 58)
+	compareAndSwap(x, 59, 60)
+	compareAndSwap(x, 61, 62)
+	compareAndSwap(x, 63, 64)
+	compareAndSwap(x, 65, 66)
+	compareAndSwap(x, 67, 68)
+	compareAndSwap(x, 69, 70)
+	compareAndSwap(x, 71, 72)
+	compareAndSwap(x, 73, 74)
+	compareAndSwap(x, 75, 76)
+	compareAndSwap(x, 77, 78)
+	compareAndSwap(x, 79, 80)
+	compareAndSwap(x, 81, 82)
+}

+ 10 - 3
newhope.go

@@ -25,7 +25,7 @@ const (
 
 	// UpstreamVersion is the version of the upstream package this
 	// implementation is compatible with.
-	UpstreamVersion = "20160803"
+	UpstreamVersion = "20160809"
 
 	// RecBytes is the length of the reconciliation data in bytes.
 	RecBytes = 256
@@ -37,6 +37,13 @@ const (
 	SendBSize = PolyBytes + RecBytes
 )
 
+// TorSampling enables the constant time generation of the `a` parameter,
+// where every successful `a` generation will take the same amount of time.
+// Most users will probably not want to enable this as it does come with a
+// performance penalty.  Alice and Bob *MUST* agree on the sampling method,
+// or the key exchange will fail.
+var TorSampling = false
+
 func encodeA(r []byte, pk *poly, seed *[SeedBytes]byte) {
 	pk.toBytes(r)
 	for i := 0; i < SeedBytes; i++ {
@@ -104,7 +111,7 @@ func GenerateKeyPair(rand io.Reader) (*PrivateKeyAlice, *PublicKeyAlice, error)
 	}
 	seed = sha3.Sum256(seed[:]) // Don't send output of system RNG.
 	// a <- Parse(SHAKE-128(seed))
-	a.uniform(&seed)
+	a.uniform(&seed, TorSampling)
 
 	// s, e <- Sample(psi(n, 12))
 	if _, err := io.ReadFull(rand, noiseSeed[:]); err != nil {
@@ -145,7 +152,7 @@ func KeyExchangeBob(rand io.Reader, alicePk *PublicKeyAlice) (*PublicKeyBob, []b
 
 	// a <- Parse(SHAKE-128(seed))
 	decodeA(&pka, &seed, alicePk.Send[:])
-	a.uniform(&seed)
+	a.uniform(&seed, TorSampling)
 
 	// s', e', e'' <- Sample(psi(n, 12))
 	sp.getNoise(&noiseSeed, 0)

+ 44 - 4
newhope_test.go

@@ -13,13 +13,23 @@ import (
 	"testing"
 )
 
-func BenchmarkKeyGen(b *testing.B) {
+func benchmarkKeyGen(b *testing.B) {
 	for i := 0; i < b.N; i++ {
 		GenerateKeyPair(rand.Reader)
 	}
 }
 
-func BenchmarkAlice(b *testing.B) {
+func BenchmarkKeyGen(b *testing.B) {
+	TorSampling = false
+	benchmarkKeyGen(b)
+}
+
+func BenchmarkKeyGenTor(b *testing.B) {
+	TorSampling = true
+	benchmarkKeyGen(b)
+}
+
+func benchmarkAlice(b *testing.B) {
 	for i := 0; i < b.N; i++ {
 		// Generate Alice's key's.
 		alicePriv, alicePub, err := GenerateKeyPair(rand.Reader)
@@ -49,7 +59,17 @@ func BenchmarkAlice(b *testing.B) {
 	}
 }
 
-func BenchmarkBob(b *testing.B) {
+func BenchmarkAlice(b *testing.B) {
+	TorSampling = false
+	benchmarkAlice(b)
+}
+
+func BenchmarkAliceTor(b *testing.B) {
+	TorSampling = true
+	benchmarkAlice(b)
+}
+
+func benchmarkBob(b *testing.B) {
 	for i := 0; i < b.N; i++ {
 		b.StopTimer()
 
@@ -79,7 +99,17 @@ func BenchmarkBob(b *testing.B) {
 	}
 }
 
-func TestIntegration(t *testing.T) {
+func BenchmarkBob(b *testing.B) {
+	TorSampling = false
+	benchmarkBob(b)
+}
+
+func BenchmarkBobTor(b *testing.B) {
+	TorSampling = true
+	benchmarkBob(b)
+}
+
+func testIntegration(t *testing.T) {
 	for i := 0; i < 1024; i++ {
 		// Generate Alice's key's.
 		alicePriv, alicePub, err := GenerateKeyPair(rand.Reader)
@@ -105,3 +135,13 @@ func TestIntegration(t *testing.T) {
 
 	}
 }
+
+func TestIntegration(t *testing.T) {
+	TorSampling = false
+	testIntegration(t)
+}
+
+func TestIntegrationTor(t *testing.T) {
+	TorSampling = true
+	testIntegration(t)
+}

+ 1 - 0
newhope_testvectors_test.go

@@ -106,6 +106,7 @@ func (r *testRng) Read(x []byte) (n int, err error) {
 }
 
 func TestNewHopeTestVectors(t *testing.T) {
+	TorSampling = false
 	r := newTestRng()
 
 	for i, v := range testVectors {

File diff suppressed because it is too large
+ 5065 - 0
newhope_testvectors_tor_test.go


+ 69 - 17
poly.go

@@ -80,28 +80,80 @@ func (p *poly) toBytes(r []byte) {
 	}
 }
 
-func (p *poly) uniform(seed *[SeedBytes]byte) {
-	nBlocks := 14
-	var buf [shake128Rate * 14]byte
+func (p *poly) discardTo(xbuf []byte) bool {
+	// At least as of newhope-20160809, the upstream version of
+	// `discardToPoly()` and `uniform()` will break if byteorder between each
+	// side is different.
+	var x [shake128Rate * 16 / 2]uint16
+	for i := range x {
+		// Assume little endian, because that's the most common, and probably
+		// what upstream will settle on.
+		x[i] = binary.LittleEndian.Uint16(xbuf[i*2:])
+	}
+
+	for i := 0; i < 16; i++ {
+		batcher84(x[i:])
+	}
+
+	// Check whether we're safe:
+	r := uint16(0)
+	for i := 1000; i < 1024; i++ {
+		r |= 61444 - x[i]
+	}
+	if r>>31 != 0 {
+		return true
+	}
 
-	// h and buf are left unscrubbed because the output is public.
-	h := sha3.NewShake128()
-	h.Write(seed[:])
-	h.Read(buf[:])
+	// If we are, copy coefficients to polynomial:
+	for i := range p.coeffs {
+		p.coeffs[i] = x[i]
+	}
 
-	for ctr, pos := 0, 0; ctr < paramN; {
-		val := binary.LittleEndian.Uint16(buf[pos:])
+	return false
+}
 
-		if val < 5*paramQ {
-			p.coeffs[ctr] = val
-			ctr++
+func (p *poly) uniform(seed *[SeedBytes]byte, torSampling bool) {
+	if !torSampling {
+		// Reference version, vartime.
+		nBlocks := 14
+		var buf [shake128Rate * 14]byte
+
+		// h and buf are left unscrubbed because the output is public.
+		h := sha3.NewShake128()
+		h.Write(seed[:])
+		h.Read(buf[:])
+
+		for ctr, pos := 0, 0; ctr < paramN; {
+			val := binary.LittleEndian.Uint16(buf[pos:])
+
+			if val < 5*paramQ {
+				p.coeffs[ctr] = val
+				ctr++
+			}
+			pos += 2
+			if pos > shake128Rate*nBlocks-2 {
+				nBlocks = 1
+				h.Read(buf[:shake128Rate])
+				pos = 0
+			}
 		}
-		pos += 2
-		if pos > shake128Rate*nBlocks-2 {
-			nBlocks = 1
-			h.Read(buf[:shake128Rate])
-			pos = 0
+	} else {
+		// `torref` version, every valid `a` is generate in constant time,
+		// though the number of attempts varies.
+		const nBlocks = 16
+		var buf [shake128Rate * nBlocks]byte
+
+		// h and buf are left unscrubbed because the output is public.
+		h := sha3.NewShake128()
+		h.Write(seed[:])
+
+		for {
+			h.Read(buf[:])
+			if !p.discardTo(buf[:]) {
+				break
+			}
 		}
+
 	}
 }