Browse Source

Initial import.

Yawning Angel 4 years ago
commit
79f438502d
12 changed files with 7028 additions and 0 deletions
  1. 122 0
      LICENSE
  2. 373 0
      chacha20/chacha20.go
  3. 323 0
      chacha20/chacha20_test.go
  4. 131 0
      error_correction.go
  5. 197 0
      newhope.go
  6. 107 0
      newhope_test.go
  7. 5156 0
      newhope_testvectors_test.go
  8. 131 0
      ntt.go
  9. 15 0
      params.go
  10. 158 0
      poly.go
  11. 287 0
      precomp.go
  12. 28 0
      reduce.go

+ 122 - 0
LICENSE

@@ -0,0 +1,122 @@
+Creative Commons Legal Code
+
+CC0 1.0 Universal
+
+    CREATIVE COMMONS CORPORATION IS NOT A LAW FIRM AND DOES NOT PROVIDE
+    LEGAL SERVICES. DISTRIBUTION OF THIS DOCUMENT DOES NOT CREATE AN
+    ATTORNEY-CLIENT RELATIONSHIP. CREATIVE COMMONS PROVIDES THIS
+    INFORMATION ON AN "AS-IS" BASIS. CREATIVE COMMONS MAKES NO WARRANTIES
+    REGARDING THE USE OF THIS DOCUMENT OR THE INFORMATION OR WORKS
+    PROVIDED HEREUNDER, AND DISCLAIMS LIABILITY FOR DAMAGES RESULTING FROM
+    THE USE OF THIS DOCUMENT OR THE INFORMATION OR WORKS PROVIDED
+    HEREUNDER.
+
+Statement of Purpose
+
+The laws of most jurisdictions throughout the world automatically confer
+exclusive Copyright and Related Rights (defined below) upon the creator
+and subsequent owner(s) (each and all, an "owner") of an original work of
+authorship and/or a database (each, a "Work").
+
+Certain owners wish to permanently relinquish those rights to a Work for
+the purpose of contributing to a commons of creative, cultural and
+scientific works ("Commons") that the public can reliably and without fear
+of later claims of infringement build upon, modify, incorporate in other
+works, reuse and redistribute as freely as possible in any form whatsoever
+and for any purposes, including without limitation commercial purposes.
+These owners may contribute to the Commons to promote the ideal of a free
+culture and the further production of creative, cultural and scientific
+works, or to gain reputation or greater distribution for their Work in
+part through the use and efforts of others.
+
+For these and/or other purposes and motivations, and without any
+expectation of additional consideration or compensation, the person
+associating CC0 with a Work (the "Affirmer"), to the extent that he or she
+is an owner of Copyright and Related Rights in the Work, voluntarily
+elects to apply CC0 to the Work and publicly distribute the Work under its
+terms, with knowledge of his or her Copyright and Related Rights in the
+Work and the meaning and intended legal effect of CC0 on those rights.
+
+1. Copyright and Related Rights. A Work made available under CC0 may be
+protected by copyright and related or neighboring rights ("Copyright and
+Related Rights"). Copyright and Related Rights include, but are not
+limited to, the following:
+
+  i. the right to reproduce, adapt, distribute, perform, display,
+     communicate, and translate a Work;
+ ii. moral rights retained by the original author(s) and/or performer(s);
+iii. publicity and privacy rights pertaining to a person's image or
+     likeness depicted in a Work;
+ iv. rights protecting against unfair competition in regards to a Work,
+     subject to the limitations in paragraph 4(a), below;
+  v. rights protecting the extraction, dissemination, use and reuse of data
+     in a Work;
+ vi. database rights (such as those arising under Directive 96/9/EC of the
+     European Parliament and of the Council of 11 March 1996 on the legal
+     protection of databases, and under any national implementation
+     thereof, including any amended or successor version of such
+     directive); and
+vii. other similar, equivalent or corresponding rights throughout the
+     world based on applicable law or treaty, and any national
+     implementations thereof.
+
+2. Waiver. To the greatest extent permitted by, but not in contravention
+of, applicable law, Affirmer hereby overtly, fully, permanently,
+irrevocably and unconditionally waives, abandons, and surrenders all of
+Affirmer's Copyright and Related Rights and associated claims and causes
+of action, whether now known or unknown (including existing as well as
+future claims and causes of action), in the Work (i) in all territories
+worldwide, (ii) for the maximum duration provided by applicable law or
+treaty (including future time extensions), (iii) in any current or future
+medium and for any number of copies, and (iv) for any purpose whatsoever,
+including without limitation commercial, advertising or promotional
+purposes (the "Waiver"). Affirmer makes the Waiver for the benefit of each
+member of the public at large and to the detriment of Affirmer's heirs and
+successors, fully intending that such Waiver shall not be subject to
+revocation, rescission, cancellation, termination, or any other legal or
+equitable action to disrupt the quiet enjoyment of the Work by the public
+as contemplated by Affirmer's express Statement of Purpose.
+
+3. Public License Fallback. Should any part of the Waiver for any reason
+be judged legally invalid or ineffective under applicable law, then the
+Waiver shall be preserved to the maximum extent permitted taking into
+account Affirmer's express Statement of Purpose. In addition, to the
+extent the Waiver is so judged Affirmer hereby grants to each affected
+person a royalty-free, non transferable, non sublicensable, non exclusive,
+irrevocable and unconditional license to exercise Affirmer's Copyright and
+Related Rights in the Work (i) in all territories worldwide, (ii) for the
+maximum duration provided by applicable law or treaty (including future
+time extensions), (iii) in any current or future medium and for any number
+of copies, and (iv) for any purpose whatsoever, including without
+limitation commercial, advertising or promotional purposes (the
+"License"). The License shall be deemed effective as of the date CC0 was
+applied by Affirmer to the Work. Should any part of the License for any
+reason be judged legally invalid or ineffective under applicable law, such
+partial invalidity or ineffectiveness shall not invalidate the remainder
+of the License, and in such case Affirmer hereby affirms that he or she
+will not (i) exercise any of his or her remaining Copyright and Related
+Rights in the Work or (ii) assert any associated claims and causes of
+action with respect to the Work, in either case contrary to Affirmer's
+express Statement of Purpose.
+
+4. Limitations and Disclaimers.
+
+ a. No trademark or patent rights held by Affirmer are waived, abandoned,
+    surrendered, licensed or otherwise affected by this document.
+ b. Affirmer offers the Work as-is and makes no representations or
+    warranties of any kind concerning the Work, express, implied,
+    statutory or otherwise, including without limitation warranties of
+    title, merchantability, fitness for a particular purpose, non
+    infringement, or the absence of latent or other defects, accuracy, or
+    the present or absence of errors, whether or not discoverable, all to
+    the greatest extent permissible under applicable law.
+ c. Affirmer disclaims responsibility for clearing rights of other persons
+    that may apply to the Work or any use thereof, including without
+    limitation any person's Copyright and Related Rights in the Work.
+    Further, Affirmer disclaims responsibility for obtaining any necessary
+    consents, permissions or other rights required for any use of the
+    Work.
+ d. Affirmer understands and acknowledges that Creative Commons is not a
+    party to this document and has no duty or obligation with respect to
+    this CC0 or use of the Work.
+

+ 373 - 0
chacha20/chacha20.go

@@ -0,0 +1,373 @@
+// chacha20.go - A ChaCha stream cipher implementation.
+//
+// To the extent possible under law, Yawning Angel has waived all copyright
+// and related or neighboring rights to chacha20, using the Creative
+// Commons "CC0" public domain dedication. See LICENSE or
+// <http://creativecommons.org/publicdomain/zero/1.0/> for full details.
+
+package chacha20
+
+import (
+	"crypto/cipher"
+	"encoding/binary"
+	"errors"
+	"runtime"
+	"unsafe"
+)
+
+const (
+	// KeySize is the ChaCha20 key size in bytes.
+	KeySize = 32
+
+	// NonceSize is the ChaCha20 nonce size in bytes.
+	NonceSize = 8
+
+	// XNonceSize is the XChaCha20 nonce size in bytes.
+	XNonceSize = 24
+
+	// HNonceSize is the HChaCha20 nonce size in bytes.
+	HNonceSize = 16
+
+	// BlockSize is the ChaCha20 block size in bytes.
+	BlockSize = 64
+
+	stateSize    = 16 - 4
+	chachaRounds = 20
+
+	// The constant "expand 32-byte k" as little endian uint32s.
+	sigma0 = uint32(0x61707865)
+	sigma1 = uint32(0x3320646e)
+	sigma2 = uint32(0x79622d32)
+	sigma3 = uint32(0x6b206574)
+)
+
+var (
+	// ErrInvalidKey is the error returned when the key is invalid.
+	ErrInvalidKey = errors.New("key length must be KeySize bytes")
+
+	// ErrInvalidNonce is the error returned when the nonce is invalid.
+	ErrInvalidNonce = errors.New("nonce length must be NonceSize/XNonceSize bytes")
+
+	useUnsafe = false
+)
+
+// A Cipher is an instance of ChaCha20/XChaCha20 using a particular key and
+// nonce.
+type Cipher struct {
+	state [stateSize]uint32
+
+	buf [BlockSize]byte
+	off int
+}
+
+// Reset zeros the key data so that it will no longer appear in the process's
+// memory.
+func (c *Cipher) Reset() {
+	for i := range c.state {
+		c.state[i] = 0
+	}
+	for i := range c.buf {
+		c.buf[i] = 0
+	}
+}
+
+// XORKeyStream sets dst to the result of XORing src with the key stream.  Dst
+// and src may be the same slice but otherwise should not overlap.
+func (c *Cipher) XORKeyStream(dst, src []byte) {
+	if len(dst) < len(src) {
+		src = src[:len(dst)]
+	}
+
+	for processed, remaining := 0, len(src); remaining > 0; {
+		if c.off == BlockSize {
+			roundsRef(&c.state, c.buf[:], false)
+			c.off = 0
+		}
+
+		toXor := BlockSize - c.off
+		if remaining < toXor {
+			toXor = remaining
+		}
+		for i, v := range src[:toXor] {
+			dst[i] = v ^ c.buf[c.off+i]
+		}
+		dst = dst[toXor:]
+		src = src[toXor:]
+
+		processed += toXor
+		remaining -= toXor
+		c.off += toXor
+	}
+}
+
+// NewCipher returns a new ChaCha20/XChaCha20 instance.
+func NewCipher(key, nonce []byte) (*Cipher, error) {
+	if len(key) != KeySize {
+		return nil, ErrInvalidKey
+	}
+
+	switch len(nonce) {
+	case NonceSize:
+	case XNonceSize:
+		var subkey [KeySize]byte
+		var subnonce [HNonceSize]byte
+		copy(subnonce[:], nonce[0:16])
+		HChaCha(key, &subnonce, &subkey)
+		key = subkey[:]
+		nonce = nonce[16:24]
+		defer func() {
+			for i := range subkey {
+				subkey[i] = 0
+			}
+		}()
+	default:
+		return nil, ErrInvalidNonce
+	}
+
+	c := new(Cipher)
+	c.state[0] = binary.LittleEndian.Uint32(key[0:4])
+	c.state[1] = binary.LittleEndian.Uint32(key[4:8])
+	c.state[2] = binary.LittleEndian.Uint32(key[8:12])
+	c.state[3] = binary.LittleEndian.Uint32(key[12:16])
+	c.state[4] = binary.LittleEndian.Uint32(key[16:20])
+	c.state[5] = binary.LittleEndian.Uint32(key[20:24])
+	c.state[6] = binary.LittleEndian.Uint32(key[24:28])
+	c.state[7] = binary.LittleEndian.Uint32(key[28:32])
+	c.state[8] = 0
+	c.state[9] = 0
+	c.state[10] = binary.LittleEndian.Uint32(nonce[0:4])
+	c.state[11] = binary.LittleEndian.Uint32(nonce[4:8])
+	c.off = BlockSize
+	return c, nil
+}
+
+// HChaCha is the HChaCha20 hash function used to make XChaCha.
+func HChaCha(key []byte, nonce *[HNonceSize]byte, out *[32]byte) {
+	var x [stateSize]uint32
+	x[0] = binary.LittleEndian.Uint32(key[0:4])
+	x[1] = binary.LittleEndian.Uint32(key[4:8])
+	x[2] = binary.LittleEndian.Uint32(key[8:12])
+	x[3] = binary.LittleEndian.Uint32(key[12:16])
+	x[4] = binary.LittleEndian.Uint32(key[16:20])
+	x[5] = binary.LittleEndian.Uint32(key[20:24])
+	x[6] = binary.LittleEndian.Uint32(key[24:28])
+	x[7] = binary.LittleEndian.Uint32(key[28:32])
+	x[8] = binary.LittleEndian.Uint32(nonce[0:4])
+	x[9] = binary.LittleEndian.Uint32(nonce[4:8])
+	x[10] = binary.LittleEndian.Uint32(nonce[8:12])
+	x[11] = binary.LittleEndian.Uint32(nonce[12:16])
+	roundsRef(&x, out[:], true)
+}
+
+func roundsRef(x *[stateSize]uint32, out []byte, isHChaCha bool) {
+	x0, x1, x2, x3 := sigma0, sigma1, sigma2, sigma3
+	x4, x5, x6, x7, x8, x9, x10, x11, x12, x13, x14, x15 := x[0], x[1], x[2], x[3], x[4], x[5], x[6], x[7], x[8], x[9], x[10], x[11]
+
+	for i := chachaRounds; i > 0; i -= 2 {
+		// quarterround(x, 0, 4, 8, 12)
+		x0 += x4
+		x12 ^= x0
+		x12 = (x12 << 16) | (x12 >> 16)
+		x8 += x12
+		x4 ^= x8
+		x4 = (x4 << 12) | (x4 >> 20)
+		x0 += x4
+		x12 ^= x0
+		x12 = (x12 << 8) | (x12 >> 24)
+		x8 += x12
+		x4 ^= x8
+		x4 = (x4 << 7) | (x4 >> 25)
+
+		// quarterround(x, 1, 5, 9, 13)
+		x1 += x5
+		x13 ^= x1
+		x13 = (x13 << 16) | (x13 >> 16)
+		x9 += x13
+		x5 ^= x9
+		x5 = (x5 << 12) | (x5 >> 20)
+		x1 += x5
+		x13 ^= x1
+		x13 = (x13 << 8) | (x13 >> 24)
+		x9 += x13
+		x5 ^= x9
+		x5 = (x5 << 7) | (x5 >> 25)
+
+		// quarterround(x, 2, 6, 10, 14)
+		x2 += x6
+		x14 ^= x2
+		x14 = (x14 << 16) | (x14 >> 16)
+		x10 += x14
+		x6 ^= x10
+		x6 = (x6 << 12) | (x6 >> 20)
+		x2 += x6
+		x14 ^= x2
+		x14 = (x14 << 8) | (x14 >> 24)
+		x10 += x14
+		x6 ^= x10
+		x6 = (x6 << 7) | (x6 >> 25)
+
+		// quarterround(x, 3, 7, 11, 15)
+		x3 += x7
+		x15 ^= x3
+		x15 = (x15 << 16) | (x15 >> 16)
+		x11 += x15
+		x7 ^= x11
+		x7 = (x7 << 12) | (x7 >> 20)
+		x3 += x7
+		x15 ^= x3
+		x15 = (x15 << 8) | (x15 >> 24)
+		x11 += x15
+		x7 ^= x11
+		x7 = (x7 << 7) | (x7 >> 25)
+
+		// quarterround(x, 0, 5, 10, 15)
+		x0 += x5
+		x15 ^= x0
+		x15 = (x15 << 16) | (x15 >> 16)
+		x10 += x15
+		x5 ^= x10
+		x5 = (x5 << 12) | (x5 >> 20)
+		x0 += x5
+		x15 ^= x0
+		x15 = (x15 << 8) | (x15 >> 24)
+		x10 += x15
+		x5 ^= x10
+		x5 = (x5 << 7) | (x5 >> 25)
+
+		// quarterround(x, 1, 6, 11, 12)
+		x1 += x6
+		x12 ^= x1
+		x12 = (x12 << 16) | (x12 >> 16)
+		x11 += x12
+		x6 ^= x11
+		x6 = (x6 << 12) | (x6 >> 20)
+		x1 += x6
+		x12 ^= x1
+		x12 = (x12 << 8) | (x12 >> 24)
+		x11 += x12
+		x6 ^= x11
+		x6 = (x6 << 7) | (x6 >> 25)
+
+		// quarterround(x, 2, 7, 8, 13)
+		x2 += x7
+		x13 ^= x2
+		x13 = (x13 << 16) | (x13 >> 16)
+		x8 += x13
+		x7 ^= x8
+		x7 = (x7 << 12) | (x7 >> 20)
+		x2 += x7
+		x13 ^= x2
+		x13 = (x13 << 8) | (x13 >> 24)
+		x8 += x13
+		x7 ^= x8
+		x7 = (x7 << 7) | (x7 >> 25)
+
+		// quarterround(x, 3, 4, 9, 14)
+		x3 += x4
+		x14 ^= x3
+		x14 = (x14 << 16) | (x14 >> 16)
+		x9 += x14
+		x4 ^= x9
+		x4 = (x4 << 12) | (x4 >> 20)
+		x3 += x4
+		x14 ^= x3
+		x14 = (x14 << 8) | (x14 >> 24)
+		x9 += x14
+		x4 ^= x9
+		x4 = (x4 << 7) | (x4 >> 25)
+	}
+
+	if isHChaCha {
+		// HChaCha returns x0...x3 | x12...x15, which corresponds to the
+		// indexes of the ChaCha constant and the indexes of the IV.
+		binary.LittleEndian.PutUint32(out[0:4], x0)
+		binary.LittleEndian.PutUint32(out[4:8], x1)
+		binary.LittleEndian.PutUint32(out[8:12], x2)
+		binary.LittleEndian.PutUint32(out[12:16], x3)
+		binary.LittleEndian.PutUint32(out[16:20], x12)
+		binary.LittleEndian.PutUint32(out[20:24], x13)
+		binary.LittleEndian.PutUint32(out[24:28], x14)
+		binary.LittleEndian.PutUint32(out[28:32], x15)
+		return
+	}
+
+	x0 += sigma0
+	x1 += sigma1
+	x2 += sigma2
+	x3 += sigma3
+	x4 += x[0]
+	x5 += x[1]
+	x6 += x[2]
+	x7 += x[3]
+	x8 += x[4]
+	x9 += x[5]
+	x10 += x[6]
+	x11 += x[7]
+	x12 += x[8]
+	x13 += x[9]
+	x14 += x[10]
+	x15 += x[11]
+
+	// Stoping at 2^70 bytes per nonce is the user's responsibility.
+	ctr := uint64(x[9])<<32 | uint64(x[8])
+	ctr++
+	x[8] = uint32(ctr)
+	x[9] = uint32(ctr >> 32)
+
+	// On amd64 this is worth +10%.
+	if useUnsafe {
+		outArr := (*[16]uint32)(unsafe.Pointer(&out[0]))
+		outArr[0] = x0
+		outArr[1] = x1
+		outArr[2] = x2
+		outArr[3] = x3
+		outArr[4] = x4
+		outArr[5] = x5
+		outArr[6] = x6
+		outArr[7] = x7
+		outArr[8] = x8
+		outArr[9] = x9
+		outArr[10] = x10
+		outArr[11] = x11
+		outArr[12] = x12
+		outArr[13] = x13
+		outArr[14] = x14
+		outArr[15] = x15
+	} else {
+		binary.LittleEndian.PutUint32(out[0:4], x0)
+		binary.LittleEndian.PutUint32(out[4:8], x1)
+		binary.LittleEndian.PutUint32(out[8:12], x2)
+		binary.LittleEndian.PutUint32(out[12:16], x3)
+		binary.LittleEndian.PutUint32(out[16:20], x4)
+		binary.LittleEndian.PutUint32(out[20:24], x5)
+		binary.LittleEndian.PutUint32(out[24:28], x6)
+		binary.LittleEndian.PutUint32(out[28:32], x7)
+		binary.LittleEndian.PutUint32(out[32:36], x8)
+		binary.LittleEndian.PutUint32(out[36:40], x9)
+		binary.LittleEndian.PutUint32(out[40:44], x10)
+		binary.LittleEndian.PutUint32(out[44:48], x11)
+		binary.LittleEndian.PutUint32(out[48:52], x12)
+		binary.LittleEndian.PutUint32(out[52:56], x13)
+		binary.LittleEndian.PutUint32(out[56:60], x14)
+		binary.LittleEndian.PutUint32(out[60:64], x15)
+	}
+}
+
+func init() {
+	switch runtime.GOARCH {
+	case "386", "amd64":
+		// Abuse unsafe to skip calling binary.LittleEndian.PutUint32
+		// in the critical path.  The right thing to do would be to just
+		// vectorize the entire implementation, however:
+		//
+		//  a) cgo performance sucks nutsack.
+		//  b) The Go assembler uses some fucked up syntax that's neither
+		//     AT&T nor Intel.
+		//
+		// So fuck it, I can't be bothered.  This is worth ~+10% on large
+		// messages.
+		useUnsafe = true
+	}
+}
+
+var _ cipher.Stream = (*Cipher)(nil)

+ 323 - 0
chacha20/chacha20_test.go

@@ -0,0 +1,323 @@
+// chacha20_test.go - ChaCha stream cipher implementation tests.
+//
+// To the extent possible under law, Yawning Angel waived all copyright
+// and related or neighboring rights to chacha20, using the Creative
+// Commons "CC0" public domain dedication. See LICENSE or
+// <http://creativecommons.org/publicdomain/zero/1.0/> for full details.
+
+package chacha20
+
+import (
+	"bytes"
+	"testing"
+)
+
+// Test vectors taken from:
+// https://tools.ietf.org/html/draft-strombergson-chacha-test-vectors-01
+var draftTestVectors = []struct {
+	name   string
+	key    []byte
+	iv     []byte
+	stream []byte
+}{
+	{
+		name: "IETF Draft: TC1: All zero key and IV.",
+		key: []byte{
+			0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+			0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+			0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+			0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+		},
+		iv: []byte{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+		stream: []byte{
+			0x76, 0xb8, 0xe0, 0xad, 0xa0, 0xf1, 0x3d, 0x90,
+			0x40, 0x5d, 0x6a, 0xe5, 0x53, 0x86, 0xbd, 0x28,
+			0xbd, 0xd2, 0x19, 0xb8, 0xa0, 0x8d, 0xed, 0x1a,
+			0xa8, 0x36, 0xef, 0xcc, 0x8b, 0x77, 0x0d, 0xc7,
+			0xda, 0x41, 0x59, 0x7c, 0x51, 0x57, 0x48, 0x8d,
+			0x77, 0x24, 0xe0, 0x3f, 0xb8, 0xd8, 0x4a, 0x37,
+			0x6a, 0x43, 0xb8, 0xf4, 0x15, 0x18, 0xa1, 0x1c,
+			0xc3, 0x87, 0xb6, 0x69, 0xb2, 0xee, 0x65, 0x86,
+			0x9f, 0x07, 0xe7, 0xbe, 0x55, 0x51, 0x38, 0x7a,
+			0x98, 0xba, 0x97, 0x7c, 0x73, 0x2d, 0x08, 0x0d,
+			0xcb, 0x0f, 0x29, 0xa0, 0x48, 0xe3, 0x65, 0x69,
+			0x12, 0xc6, 0x53, 0x3e, 0x32, 0xee, 0x7a, 0xed,
+			0x29, 0xb7, 0x21, 0x76, 0x9c, 0xe6, 0x4e, 0x43,
+			0xd5, 0x71, 0x33, 0xb0, 0x74, 0xd8, 0x39, 0xd5,
+			0x31, 0xed, 0x1f, 0x28, 0x51, 0x0a, 0xfb, 0x45,
+			0xac, 0xe1, 0x0a, 0x1f, 0x4b, 0x79, 0x4d, 0x6f,
+		},
+	},
+	{
+		name: "IETF Draft: TC2: Single bit in key set. All zero IV.",
+		key: []byte{
+			0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+			0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+			0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+			0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+		},
+		iv: []byte{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+		stream: []byte{
+			0xc5, 0xd3, 0x0a, 0x7c, 0xe1, 0xec, 0x11, 0x93,
+			0x78, 0xc8, 0x4f, 0x48, 0x7d, 0x77, 0x5a, 0x85,
+			0x42, 0xf1, 0x3e, 0xce, 0x23, 0x8a, 0x94, 0x55,
+			0xe8, 0x22, 0x9e, 0x88, 0x8d, 0xe8, 0x5b, 0xbd,
+			0x29, 0xeb, 0x63, 0xd0, 0xa1, 0x7a, 0x5b, 0x99,
+			0x9b, 0x52, 0xda, 0x22, 0xbe, 0x40, 0x23, 0xeb,
+			0x07, 0x62, 0x0a, 0x54, 0xf6, 0xfa, 0x6a, 0xd8,
+			0x73, 0x7b, 0x71, 0xeb, 0x04, 0x64, 0xda, 0xc0,
+			0x10, 0xf6, 0x56, 0xe6, 0xd1, 0xfd, 0x55, 0x05,
+			0x3e, 0x50, 0xc4, 0x87, 0x5c, 0x99, 0x30, 0xa3,
+			0x3f, 0x6d, 0x02, 0x63, 0xbd, 0x14, 0xdf, 0xd6,
+			0xab, 0x8c, 0x70, 0x52, 0x1c, 0x19, 0x33, 0x8b,
+			0x23, 0x08, 0xb9, 0x5c, 0xf8, 0xd0, 0xbb, 0x7d,
+			0x20, 0x2d, 0x21, 0x02, 0x78, 0x0e, 0xa3, 0x52,
+			0x8f, 0x1c, 0xb4, 0x85, 0x60, 0xf7, 0x6b, 0x20,
+			0xf3, 0x82, 0xb9, 0x42, 0x50, 0x0f, 0xce, 0xac,
+		},
+	},
+	{
+		name: "IETF Draft: TC3: Single bit in IV set. All zero key.",
+		key: []byte{
+			0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+			0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+			0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+			0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+		},
+		iv: []byte{0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+		stream: []byte{
+			0xef, 0x3f, 0xdf, 0xd6, 0xc6, 0x15, 0x78, 0xfb,
+			0xf5, 0xcf, 0x35, 0xbd, 0x3d, 0xd3, 0x3b, 0x80,
+			0x09, 0x63, 0x16, 0x34, 0xd2, 0x1e, 0x42, 0xac,
+			0x33, 0x96, 0x0b, 0xd1, 0x38, 0xe5, 0x0d, 0x32,
+			0x11, 0x1e, 0x4c, 0xaf, 0x23, 0x7e, 0xe5, 0x3c,
+			0xa8, 0xad, 0x64, 0x26, 0x19, 0x4a, 0x88, 0x54,
+			0x5d, 0xdc, 0x49, 0x7a, 0x0b, 0x46, 0x6e, 0x7d,
+			0x6b, 0xbd, 0xb0, 0x04, 0x1b, 0x2f, 0x58, 0x6b,
+			0x53, 0x05, 0xe5, 0xe4, 0x4a, 0xff, 0x19, 0xb2,
+			0x35, 0x93, 0x61, 0x44, 0x67, 0x5e, 0xfb, 0xe4,
+			0x40, 0x9e, 0xb7, 0xe8, 0xe5, 0xf1, 0x43, 0x0f,
+			0x5f, 0x58, 0x36, 0xae, 0xb4, 0x9b, 0xb5, 0x32,
+			0x8b, 0x01, 0x7c, 0x4b, 0x9d, 0xc1, 0x1f, 0x8a,
+			0x03, 0x86, 0x3f, 0xa8, 0x03, 0xdc, 0x71, 0xd5,
+			0x72, 0x6b, 0x2b, 0x6b, 0x31, 0xaa, 0x32, 0x70,
+			0x8a, 0xfe, 0x5a, 0xf1, 0xd6, 0xb6, 0x90, 0x58,
+		},
+	},
+	{
+		name: "IETF Draft: TC4: All bits in key and IV are set.",
+		key: []byte{
+			0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+			0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+			0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+			0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+		},
+		iv: []byte{0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff},
+		stream: []byte{
+			0xd9, 0xbf, 0x3f, 0x6b, 0xce, 0x6e, 0xd0, 0xb5,
+			0x42, 0x54, 0x55, 0x77, 0x67, 0xfb, 0x57, 0x44,
+			0x3d, 0xd4, 0x77, 0x89, 0x11, 0xb6, 0x06, 0x05,
+			0x5c, 0x39, 0xcc, 0x25, 0xe6, 0x74, 0xb8, 0x36,
+			0x3f, 0xea, 0xbc, 0x57, 0xfd, 0xe5, 0x4f, 0x79,
+			0x0c, 0x52, 0xc8, 0xae, 0x43, 0x24, 0x0b, 0x79,
+			0xd4, 0x90, 0x42, 0xb7, 0x77, 0xbf, 0xd6, 0xcb,
+			0x80, 0xe9, 0x31, 0x27, 0x0b, 0x7f, 0x50, 0xeb,
+			0x5b, 0xac, 0x2a, 0xcd, 0x86, 0xa8, 0x36, 0xc5,
+			0xdc, 0x98, 0xc1, 0x16, 0xc1, 0x21, 0x7e, 0xc3,
+			0x1d, 0x3a, 0x63, 0xa9, 0x45, 0x13, 0x19, 0xf0,
+			0x97, 0xf3, 0xb4, 0xd6, 0xda, 0xb0, 0x77, 0x87,
+			0x19, 0x47, 0x7d, 0x24, 0xd2, 0x4b, 0x40, 0x3a,
+			0x12, 0x24, 0x1d, 0x7c, 0xca, 0x06, 0x4f, 0x79,
+			0x0f, 0x1d, 0x51, 0xcc, 0xaf, 0xf6, 0xb1, 0x66,
+			0x7d, 0x4b, 0xbc, 0xa1, 0x95, 0x8c, 0x43, 0x06,
+		},
+	},
+	{
+		name: "IETF Draft: TC5: Every even bit set in key and IV.",
+		key: []byte{
+			0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55,
+			0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55,
+			0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55,
+			0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55,
+		},
+		iv: []byte{0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55},
+		stream: []byte{
+			0xbe, 0xa9, 0x41, 0x1a, 0xa4, 0x53, 0xc5, 0x43,
+			0x4a, 0x5a, 0xe8, 0xc9, 0x28, 0x62, 0xf5, 0x64,
+			0x39, 0x68, 0x55, 0xa9, 0xea, 0x6e, 0x22, 0xd6,
+			0xd3, 0xb5, 0x0a, 0xe1, 0xb3, 0x66, 0x33, 0x11,
+			0xa4, 0xa3, 0x60, 0x6c, 0x67, 0x1d, 0x60, 0x5c,
+			0xe1, 0x6c, 0x3a, 0xec, 0xe8, 0xe6, 0x1e, 0xa1,
+			0x45, 0xc5, 0x97, 0x75, 0x01, 0x7b, 0xee, 0x2f,
+			0xa6, 0xf8, 0x8a, 0xfc, 0x75, 0x80, 0x69, 0xf7,
+			0xe0, 0xb8, 0xf6, 0x76, 0xe6, 0x44, 0x21, 0x6f,
+			0x4d, 0x2a, 0x34, 0x22, 0xd7, 0xfa, 0x36, 0xc6,
+			0xc4, 0x93, 0x1a, 0xca, 0x95, 0x0e, 0x9d, 0xa4,
+			0x27, 0x88, 0xe6, 0xd0, 0xb6, 0xd1, 0xcd, 0x83,
+			0x8e, 0xf6, 0x52, 0xe9, 0x7b, 0x14, 0x5b, 0x14,
+			0x87, 0x1e, 0xae, 0x6c, 0x68, 0x04, 0xc7, 0x00,
+			0x4d, 0xb5, 0xac, 0x2f, 0xce, 0x4c, 0x68, 0xc7,
+			0x26, 0xd0, 0x04, 0xb1, 0x0f, 0xca, 0xba, 0x86,
+		},
+	},
+	{
+		name: "IETF Draft: TC6: Every odd bit set in key and IV.",
+		key: []byte{
+			0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+			0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+			0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+			0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+		},
+		iv: []byte{0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa},
+		stream: []byte{
+			0x9a, 0xa2, 0xa9, 0xf6, 0x56, 0xef, 0xde, 0x5a,
+			0xa7, 0x59, 0x1c, 0x5f, 0xed, 0x4b, 0x35, 0xae,
+			0xa2, 0x89, 0x5d, 0xec, 0x7c, 0xb4, 0x54, 0x3b,
+			0x9e, 0x9f, 0x21, 0xf5, 0xe7, 0xbc, 0xbc, 0xf3,
+			0xc4, 0x3c, 0x74, 0x8a, 0x97, 0x08, 0x88, 0xf8,
+			0x24, 0x83, 0x93, 0xa0, 0x9d, 0x43, 0xe0, 0xb7,
+			0xe1, 0x64, 0xbc, 0x4d, 0x0b, 0x0f, 0xb2, 0x40,
+			0xa2, 0xd7, 0x21, 0x15, 0xc4, 0x80, 0x89, 0x06,
+			0x72, 0x18, 0x44, 0x89, 0x44, 0x05, 0x45, 0xd0,
+			0x21, 0xd9, 0x7e, 0xf6, 0xb6, 0x93, 0xdf, 0xe5,
+			0xb2, 0xc1, 0x32, 0xd4, 0x7e, 0x6f, 0x04, 0x1c,
+			0x90, 0x63, 0x65, 0x1f, 0x96, 0xb6, 0x23, 0xe6,
+			0x2a, 0x11, 0x99, 0x9a, 0x23, 0xb6, 0xf7, 0xc4,
+			0x61, 0xb2, 0x15, 0x30, 0x26, 0xad, 0x5e, 0x86,
+			0x6a, 0x2e, 0x59, 0x7e, 0xd0, 0x7b, 0x84, 0x01,
+			0xde, 0xc6, 0x3a, 0x09, 0x34, 0xc6, 0xb2, 0xa9,
+		},
+	},
+	{
+		name: "IETF Draft: TC7: Sequence patterns in key and IV.",
+		key: []byte{
+			0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77,
+			0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff,
+			0xff, 0xee, 0xdd, 0xcc, 0xbb, 0xaa, 0x99, 0x88,
+			0x77, 0x66, 0x55, 0x44, 0x33, 0x22, 0x11, 0x00,
+		},
+		iv: []byte{0x0f, 0x1e, 0x2d, 0x3c, 0x4b, 0x5a, 0x69, 0x78},
+		stream: []byte{
+			0x9f, 0xad, 0xf4, 0x09, 0xc0, 0x08, 0x11, 0xd0,
+			0x04, 0x31, 0xd6, 0x7e, 0xfb, 0xd8, 0x8f, 0xba,
+			0x59, 0x21, 0x8d, 0x5d, 0x67, 0x08, 0xb1, 0xd6,
+			0x85, 0x86, 0x3f, 0xab, 0xbb, 0x0e, 0x96, 0x1e,
+			0xea, 0x48, 0x0f, 0xd6, 0xfb, 0x53, 0x2b, 0xfd,
+			0x49, 0x4b, 0x21, 0x51, 0x01, 0x50, 0x57, 0x42,
+			0x3a, 0xb6, 0x0a, 0x63, 0xfe, 0x4f, 0x55, 0xf7,
+			0xa2, 0x12, 0xe2, 0x16, 0x7c, 0xca, 0xb9, 0x31,
+			0xfb, 0xfd, 0x29, 0xcf, 0x7b, 0xc1, 0xd2, 0x79,
+			0xed, 0xdf, 0x25, 0xdd, 0x31, 0x6b, 0xb8, 0x84,
+			0x3d, 0x6e, 0xde, 0xe0, 0xbd, 0x1e, 0xf1, 0x21,
+			0xd1, 0x2f, 0xa1, 0x7c, 0xbc, 0x2c, 0x57, 0x4c,
+			0xcc, 0xab, 0x5e, 0x27, 0x51, 0x67, 0xb0, 0x8b,
+			0xd6, 0x86, 0xf8, 0xa0, 0x9d, 0xf8, 0x7e, 0xc3,
+			0xff, 0xb3, 0x53, 0x61, 0xb9, 0x4e, 0xbf, 0xa1,
+			0x3f, 0xec, 0x0e, 0x48, 0x89, 0xd1, 0x8d, 0xa5,
+		},
+	},
+	{
+		name: "IETF Draft: TC8: key: 'All your base are belong to us!, IV: 'IETF2013'",
+		key: []byte{
+			0xc4, 0x6e, 0xc1, 0xb1, 0x8c, 0xe8, 0xa8, 0x78,
+			0x72, 0x5a, 0x37, 0xe7, 0x80, 0xdf, 0xb7, 0x35,
+			0x1f, 0x68, 0xed, 0x2e, 0x19, 0x4c, 0x79, 0xfb,
+			0xc6, 0xae, 0xbe, 0xe1, 0xa6, 0x67, 0x97, 0x5d,
+		},
+		iv: []byte{0x1a, 0xda, 0x31, 0xd5, 0xcf, 0x68, 0x82, 0x21},
+		stream: []byte{
+			0xf6, 0x3a, 0x89, 0xb7, 0x5c, 0x22, 0x71, 0xf9,
+			0x36, 0x88, 0x16, 0x54, 0x2b, 0xa5, 0x2f, 0x06,
+			0xed, 0x49, 0x24, 0x17, 0x92, 0x30, 0x2b, 0x00,
+			0xb5, 0xe8, 0xf8, 0x0a, 0xe9, 0xa4, 0x73, 0xaf,
+			0xc2, 0x5b, 0x21, 0x8f, 0x51, 0x9a, 0xf0, 0xfd,
+			0xd4, 0x06, 0x36, 0x2e, 0x8d, 0x69, 0xde, 0x7f,
+			0x54, 0xc6, 0x04, 0xa6, 0xe0, 0x0f, 0x35, 0x3f,
+			0x11, 0x0f, 0x77, 0x1b, 0xdc, 0xa8, 0xab, 0x92,
+			0xe5, 0xfb, 0xc3, 0x4e, 0x60, 0xa1, 0xd9, 0xa9,
+			0xdb, 0x17, 0x34, 0x5b, 0x0a, 0x40, 0x27, 0x36,
+			0x85, 0x3b, 0xf9, 0x10, 0xb0, 0x60, 0xbd, 0xf1,
+			0xf8, 0x97, 0xb6, 0x29, 0x0f, 0x01, 0xd1, 0x38,
+			0xae, 0x2c, 0x4c, 0x90, 0x22, 0x5b, 0xa9, 0xea,
+			0x14, 0xd5, 0x18, 0xf5, 0x59, 0x29, 0xde, 0xa0,
+			0x98, 0xca, 0x7a, 0x6c, 0xcf, 0xe6, 0x12, 0x27,
+			0x05, 0x3c, 0x84, 0xe4, 0x9a, 0x4a, 0x33, 0x32,
+		},
+	},
+	{
+		name: "XChaCha20 Test",
+		key: []byte{
+			0x1b, 0x27, 0x55, 0x64, 0x73, 0xe9, 0x85, 0xd4,
+			0x62, 0xcd, 0x51, 0x19, 0x7a, 0x9a, 0x46, 0xc7,
+			0x60, 0x09, 0x54, 0x9e, 0xac, 0x64, 0x74, 0xf2,
+			0x06, 0xc4, 0xee, 0x08, 0x44, 0xf6, 0x83, 0x89,
+		},
+		iv: []byte{
+			0x69, 0x69, 0x6e, 0xe9, 0x55, 0xb6, 0x2b, 0x73,
+			0xcd, 0x62, 0xbd, 0xa8, 0x75, 0xfc, 0x73, 0xd6,
+			0x82, 0x19, 0xe0, 0x03, 0x6b, 0x7a, 0x0b, 0x37,
+		},
+		stream: []byte{
+			0x4f, 0xeb, 0xf2, 0xfe, 0x4b, 0x35, 0x9c, 0x50,
+			0x8d, 0xc5, 0xe8, 0xb5, 0x98, 0x0c, 0x88, 0xe3,
+			0x89, 0x46, 0xd8, 0xf1, 0x8f, 0x31, 0x34, 0x65,
+			0xc8, 0x62, 0xa0, 0x87, 0x82, 0x64, 0x82, 0x48,
+			0x01, 0x8d, 0xac, 0xdc, 0xb9, 0x04, 0x17, 0x88,
+			0x53, 0xa4, 0x6d, 0xca, 0x3a, 0x0e, 0xaa, 0xee,
+			0x74, 0x7c, 0xba, 0x97, 0x43, 0x4e, 0xaf, 0xfa,
+			0xd5, 0x8f, 0xea, 0x82, 0x22, 0x04, 0x7e, 0x0d,
+			0xe6, 0xc3, 0xa6, 0x77, 0x51, 0x06, 0xe0, 0x33,
+			0x1a, 0xd7, 0x14, 0xd2, 0xf2, 0x7a, 0x55, 0x64,
+			0x13, 0x40, 0xa1, 0xf1, 0xdd, 0x9f, 0x94, 0x53,
+			0x2e, 0x68, 0xcb, 0x24, 0x1c, 0xbd, 0xd1, 0x50,
+			0x97, 0x0d, 0x14, 0xe0, 0x5c, 0x5b, 0x17, 0x31,
+			0x93, 0xfb, 0x14, 0xf5, 0x1c, 0x41, 0xf3, 0x93,
+			0x83, 0x5b, 0xf7, 0xf4, 0x16, 0xa7, 0xe0, 0xbb,
+			0xa8, 0x1f, 0xfb, 0x8b, 0x13, 0xaf, 0x0e, 0x21,
+			0x69, 0x1d, 0x7e, 0xce, 0xc9, 0x3b, 0x75, 0xe6,
+			0xe4, 0x18, 0x3a,
+		},
+	},
+}
+
+func TestChaCha20(t *testing.T) {
+	for _, v := range draftTestVectors {
+		c, err := NewCipher(v.key, v.iv)
+		if err != nil {
+			t.Errorf("[%s]: New(k, iv) returned: %s", v.name, err)
+			continue
+		}
+		out := make([]byte, len(v.stream))
+		c.XORKeyStream(out, out)
+		if !bytes.Equal(out, v.stream) {
+			t.Errorf("[%s]: out != stream (%x != %x)", v.name, out, v.stream)
+		}
+	}
+}
+
+func doBenchN(b *testing.B, n int) {
+	var key [KeySize]byte
+	var nonce [NonceSize]byte
+	s := make([]byte, n)
+	c, err := NewCipher(key[:], nonce[:])
+	if err != nil {
+		b.Fatal(err)
+	}
+	b.SetBytes(int64(n))
+	b.ResetTimer()
+	for i := 0; i < b.N; i++ {
+		c.XORKeyStream(s, s)
+	}
+}
+
+func BenchmarkChaCha20_16(b *testing.B) {
+	doBenchN(b, 16)
+}
+
+func BenchmarkChaCha20_1k(b *testing.B) {
+	doBenchN(b, 1024)
+}
+
+func BenchmarkChaCha20_64k(b *testing.B) {
+	doBenchN(b, 65536)
+}

+ 131 - 0
error_correction.go

@@ -0,0 +1,131 @@
+// error_correction.go - New Hope key exchange error correction.
+//
+// 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
+
+import "github.com/yawning/newhope/chacha20"
+
+func abs(v int32) int32 {
+	mask := v >> 31
+	return (v ^ mask) - mask
+}
+
+func f(v0, v1 *int32, x int32) int32 {
+	// Next 6 lines compute t = x/PARAM_Q
+	b := x * 2730
+	t := b >> 25
+	b = x - t*paramQ
+	b = (paramQ-1) - b
+	b >>= 31
+	t -= b
+
+	r := t & 1
+	xit := t >> 1
+	*v0 = xit + r // v0 = round(x/(2*PARAM_Q))
+
+	t--
+	r = t & 1
+	*v1 = (t >> 1) + r
+
+	return abs(x - ((*v0) * 2 * paramQ))
+}
+
+func g(x int32) int32 {
+	// Next 6 lines compute t = x/(4 *PARAMQ)
+	b := x * 2730
+	t := b >> 27
+	b = x - t*(paramQ*4)
+	b = (paramQ * 4) - b
+	b >>= 31
+	t -= b
+
+	c := t & 1
+	t = (t >> 1) + c // t = round(x/(8*PARAM_Q))
+
+	t *= 8 * paramQ
+
+	return abs(t - x)
+}
+
+func llDecode(xi0, xi1, xi2, xi3 int32) int16 {
+	t := g(xi0)
+	t += g(xi1)
+	t += g(xi2)
+	t += g(xi3)
+
+	t -= 8 * paramQ
+	t >>= 31
+	return int16(t & 1)
+}
+
+func (c *poly) helpRec(v *poly, seed *[seedBytes]byte, nonce byte) {
+	var v0, v1, vTmp [4]int32
+	var k int32
+	var rand [32]byte
+	var n [8]byte
+
+	n[7] = nonce
+
+	stream, err := chacha20.NewCipher(seed[:], n[:])
+	if err != nil {
+		panic(err)
+	}
+	stream.XORKeyStream(rand[:], rand[:])
+	stream.Reset()
+	defer memwipe(rand[:])
+
+	for i := uint(0); i < 256; i++ {
+		rBit := int32((rand[i>>3] >> (i & 7)) & 1)
+
+		vTmp[0], vTmp[1], vTmp[2], vTmp[3] = int32(v.v[i]), int32(v.v[256+i]), int32(v.v[512+i]), int32(v.v[768+i])
+
+		k = f(&v0[0], &v1[0], 8*vTmp[0]+4*paramQ*rBit)
+		k += f(&v0[1], &v1[1], 8*vTmp[1]+4*paramQ*rBit)
+		k += f(&v0[2], &v1[2], 8*vTmp[2]+4*paramQ*int32(rBit))
+		k += f(&v0[3], &v1[3], 8*vTmp[3]+4*paramQ*int32(rBit))
+
+		k = (2*paramQ - 1 - k) >> 31
+
+		vTmp[0] = ((^k) & v0[0]) ^ (k & v1[0])
+		vTmp[1] = ((^k) & v0[1]) ^ (k & v1[1])
+		vTmp[2] = ((^k) & v0[2]) ^ (k & v1[2])
+		vTmp[3] = ((^k) & v0[3]) ^ (k & v1[3])
+
+		c.v[0+i] = uint16((vTmp[0] - vTmp[3]) & 3)
+		c.v[256+i] = uint16((vTmp[1] - vTmp[3]) & 3)
+		c.v[512+i] = uint16((vTmp[2] - vTmp[3]) & 3)
+		c.v[768+i] = uint16((-k + 2*vTmp[3]) & 3)
+	}
+
+	for i := range vTmp {
+		vTmp[i] = 0
+	}
+}
+
+func rec(key *[32]byte, v, c *poly) {
+	var tmp, vTmp, cTmp [4]int32
+	for i := range key {
+		key[i] = 0
+	}
+
+	for i := uint(0); i < 256; i++ {
+		vTmp[0], vTmp[1], vTmp[2], vTmp[3] = int32(v.v[i]), int32(v.v[256+i]), int32(v.v[512+i]), int32(v.v[768+i])
+		cTmp[0], cTmp[1], cTmp[2], cTmp[3] = int32(c.v[i]), int32(c.v[256+i]), int32(c.v[512+i]), int32(c.v[768+i])
+		tmp[0] = 16*paramQ + 8*vTmp[0] - paramQ*(2*cTmp[0]+cTmp[3])
+		tmp[1] = 16*paramQ + 8*vTmp[1] - paramQ*(2*cTmp[1]+cTmp[3])
+		tmp[2] = 16*paramQ + 8*vTmp[2] - paramQ*(2*cTmp[2]+cTmp[3])
+		tmp[3] = 16*paramQ + 8*vTmp[3] - paramQ*(cTmp[3])
+
+		key[i>>3] |= byte(llDecode(tmp[0], tmp[1], tmp[2], tmp[3]) << (i & 7))
+	}
+
+	for i := 0; i < 4; i++ {
+		tmp[i] = 0
+		vTmp[i] = 0
+		cTmp[i] = 0
+	}
+}

+ 197 - 0
newhope.go

@@ -0,0 +1,197 @@
+// newhope.go - New Hope interface.
+//
+// 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 implements a key exchange based on the Ring Learning with
+// Errors Problem.  It is a mechanical port of the Public Domain implementation
+// by Erdem Alkim, Léo Ducas, Thomas Pöppelmann, and Peter Schwabe4.
+//
+// For more information see: https://cryptojedi.org/papers/newhope-20151110.pdf
+//
+package newhope
+
+import (
+	"io"
+
+	"golang.org/x/crypto/sha3"
+)
+
+const (
+	// SharedSecretSize is the length of a Shared Secret in bytes.
+	SharedSecretSize = 32
+
+	// UpstreamVersion is the version of the upstream package this
+	// implementation is compatible with.
+	UpstreamVersion = "20151110"
+)
+
+func encodeA(r []byte, pk *poly, seed *[seedBytes]byte) {
+	pk.toBytes(r)
+	for i, v := range seed {
+		for j := 0; j < 4; j++ {
+			r[2*(4*i+j)+1] |= v << 6
+			v >>= 2
+		}
+	}
+}
+
+func decodeA(pk *poly, seed *[seedBytes]byte, r []byte) {
+	pk.fromBytes(r)
+
+	for i := range seed {
+		seed[i] = 0
+		for j := uint(0); j < 4; j++ {
+			seed[i] |= byte(r[2*(4*uint(i)+j)+1]>>6) << (2 * j)
+		}
+	}
+}
+
+func encodeB(r []byte, b *poly, c *poly) {
+	b.toBytes(r)
+	for i, v := range c.v {
+		r[2*i+1] |= byte(v << 6)
+	}
+}
+
+func decodeB(b *poly, c *poly, r []byte) {
+	b.fromBytes(r)
+	for i := range c.v {
+		c.v[i] = uint16(r[2*i+1] >> 6)
+	}
+}
+
+func memwipe(b []byte) {
+	for i := range b {
+		b[i] = 0
+	}
+}
+
+// PublicKey is a New Hope public key.
+type PublicKey struct {
+	Send [PolyBytes]byte
+}
+
+// PrivateKey is a New Hope private key.
+type PrivateKey struct {
+	sk poly
+}
+
+// GenerateKeyPair returns a private/public key pair.  The private key is
+// generated using the given reader, which must return random data.  The
+// receiver side of the key exchange (aka "Bob") MUST use KeyExchangeBob()
+// instead of this routine.
+func GenerateKeyPair(rand io.Reader) (*PrivateKey, *PublicKey, error) {
+	var a, e, pk, r poly
+	var seed, noiseSeed [seedBytes]byte
+
+	// seed <- Sample({0, 1}^256)
+	if _, err := io.ReadFull(rand, seed[:]); err != nil {
+		return nil, nil, err
+	}
+	// a <- Parse(SHAKE-128(seed))
+	a.uniform(&seed)
+
+	// s, e <- Sample(psi(n, 12))
+	if _, err := io.ReadFull(rand, noiseSeed[:]); err != nil {
+		return nil, nil, err
+	}
+	defer memwipe(noiseSeed[:])
+	privKey := new(PrivateKey)
+	privKey.sk.getNoise(&noiseSeed, 0)
+	privKey.sk.ntt()
+	e.getNoise(&noiseSeed, 1)
+	e.ntt()
+
+	// b <- as + e
+	pubKey := new(PublicKey)
+	r.pointwise(&privKey.sk, &a)
+	pk.add(&e, &r)
+	encodeA(pubKey.Send[:], &pk, &seed)
+
+	return privKey, pubKey, nil
+}
+
+// KeyExchangeBob is the Responder side of the Ring-LWE key exchange.  The
+// shared secret and "public key" (key + reconciliation data) are generated
+// using the given reader, which must return random data.
+func KeyExchangeBob(rand io.Reader, alicePk *PublicKey) (*PublicKey, []byte, error) {
+	var pka, a, sp, ep, u, v, epp, r poly
+	var seed, noiseSeed [seedBytes]byte
+
+	if _, err := io.ReadFull(rand, noiseSeed[:]); err != nil {
+		return nil, nil, err
+	}
+	defer memwipe(noiseSeed[:])
+
+	// a <- Parse(SHAKE-128(seed))
+	decodeA(&pka, &seed, alicePk.Send[:])
+	a.uniform(&seed)
+
+	// s', e', e'' <- Sample(psi(n, 12))
+	sp.getNoise(&noiseSeed, 0)
+	sp.ntt()
+	ep.getNoise(&noiseSeed, 1)
+	ep.ntt()
+	epp.getNoise(&noiseSeed, 2)
+
+	// u <- as' + e'
+	u.pointwise(&a, &sp)
+	u.add(&u, &ep)
+
+	// v <- bs' + e''
+	v.pointwise(&pka, &sp)
+	v.bitrev()
+	v.invNtt()
+	v.add(&v, &epp)
+
+	// r <- Sample(HelpRec(v))
+	r.helpRec(&v, &noiseSeed, 3)
+
+	pubKey := new(PublicKey)
+	encodeB(pubKey.Send[:], &u, &r)
+
+	// nu <- Rec(v, r)
+	var nu [SharedSecretSize]byte
+	rec(&nu, &v, &r)
+
+	// mu <- SHA3-256(nu)
+	mu := sha3.Sum256(nu[:])
+
+	// Scrub the sensitive stuff...
+	memwipe(nu[:])
+	sp.reset()
+	v.reset()
+
+	return pubKey, mu[:], nil
+}
+
+// KeyExchangeAlice is the Initiaitor side of the Ring-LWE key exchange.  The
+// provided private key is obliterated prior to returning, to promote
+// implementing Perfect Forward Secrecy.
+func KeyExchangeAlice(bobPk *PublicKey, aliceSk *PrivateKey) ([]byte, error) {
+	var u, r, vp poly
+
+	decodeB(&u, &r, bobPk.Send[:])
+
+	// v' <- us
+	vp.pointwise(&aliceSk.sk, &u)
+	vp.bitrev()
+	vp.invNtt()
+
+	// nu <- Rec(v', r)
+	var nu [SharedSecretSize]byte
+	rec(&nu, &vp, &r)
+
+	// mu <- Sha3-256(nu)
+	mu := sha3.Sum256(nu[:])
+
+	// Scrub the sensitive stuff...
+	memwipe(nu[:])
+	vp.reset()
+	aliceSk.sk.reset()
+
+	return mu[:], nil
+}

+ 107 - 0
newhope_test.go

@@ -0,0 +1,107 @@
+// newhope_test.go - New Hope Integration tests.
+//
+// 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
+
+import (
+	"bytes"
+	"crypto/rand"
+	"testing"
+)
+
+func BenchmarkKeyGen(b *testing.B) {
+	for i := 0; i < b.N; i++ {
+		GenerateKeyPair(rand.Reader)
+	}
+}
+
+func BenchmarkAlice(b *testing.B) {
+	for i := 0; i < b.N; i++ {
+		// Generate Alice's key's.
+		alicePriv, alicePub, err := GenerateKeyPair(rand.Reader)
+		if err != nil {
+			b.Fatalf("GenerateKeyPair failed: %v", err)
+		}
+
+		// Finish Bob's handshake.
+		b.StopTimer()
+		bobPub, bobShared, err := KeyExchangeBob(rand.Reader, alicePub)
+		if err != nil {
+			b.Fatalf("KeyExchangeBob failed: %v", err)
+		}
+		b.StartTimer()
+
+		// Finish Alice's handshake.
+		aliceShared, err := KeyExchangeAlice(bobPub, alicePriv)
+		if err != nil {
+			b.Fatalf("KeyExchangeAlice failed: %v", err)
+		}
+
+		b.StopTimer()
+		if !bytes.Equal(aliceShared, bobShared) {
+			b.Fatalf("shared secrets mismatched")
+		}
+		b.StartTimer()
+	}
+}
+
+func BenchmarkBob(b *testing.B) {
+	for i := 0; i < b.N; i++ {
+		b.StopTimer()
+
+		// Generate Alice's key's.
+		alicePriv, alicePub, err := GenerateKeyPair(rand.Reader)
+		if err != nil {
+			b.Fatalf("GenerateKeyPair failed: %v", err)
+		}
+
+		// Finish Bob's handshake.
+		b.StartTimer()
+		bobPub, bobShared, err := KeyExchangeBob(rand.Reader, alicePub)
+		if err != nil {
+			b.Fatalf("KeyExchangeBob failed: %v", err)
+		}
+		b.StopTimer()
+
+		// Finish Alice's handshake.
+		aliceShared, err := KeyExchangeAlice(bobPub, alicePriv)
+		if err != nil {
+			b.Fatalf("KeyExchangeAlice failed: %v", err)
+		}
+
+		if !bytes.Equal(aliceShared, bobShared) {
+			b.Fatalf("shared secrets mismatched")
+		}
+	}
+}
+
+func TestIntegration(t *testing.T) {
+	for i := 0; i < 1024; i++ {
+		// Generate Alice's key's.
+		alicePriv, alicePub, err := GenerateKeyPair(rand.Reader)
+		if err != nil {
+			t.Fatalf("GenerateKeyPair failed: %v", err)
+		}
+
+		// Finish Bob's handshake.
+		bobPub, bobShared, err := KeyExchangeBob(rand.Reader, alicePub)
+		if err != nil {
+			t.Fatalf("KeyExchangeBob failed: %v", err)
+		}
+
+		// Finish Alice's handshake.
+		aliceShared, err := KeyExchangeAlice(bobPub, alicePriv)
+		if err != nil {
+			t.Fatalf("KeyExchangeAlice failed: %v", err)
+		}
+
+		if !bytes.Equal(aliceShared, bobShared) {
+			t.Fatalf("shared secrets mismatched")
+		}
+
+	}
+}

File diff suppressed because it is too large
+ 5156 - 0
newhope_testvectors_test.go


+ 131 - 0
ntt.go

@@ -0,0 +1,131 @@
+// ntt.go - New Hope Number Theoretic Transform.
+//
+// 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
+
+var bitrevTable = [paramN]uint16{
+	0, 512, 256, 768, 128, 640, 384, 896, 64, 576, 320, 832, 192, 704, 448, 960,
+	32, 544, 288, 800, 160, 672, 416, 928, 96, 608, 352, 864, 224, 736, 480,
+	992, 16, 528, 272, 784, 144, 656, 400, 912, 80, 592, 336, 848, 208, 720,
+	464, 976, 48, 560, 304, 816, 176, 688, 432, 944, 112, 624, 368, 880,
+	240, 752, 496, 1008, 8, 520, 264, 776, 136, 648, 392, 904, 72, 584, 328,
+	840, 200, 712, 456, 968, 40, 552, 296, 808, 168, 680, 424, 936, 104,
+	616, 360, 872, 232, 744, 488, 1000, 24, 536, 280, 792, 152, 664, 408,
+	920, 88, 600, 344, 856, 216, 728, 472, 984, 56, 568, 312, 824, 184, 696,
+	440, 952, 120, 632, 376, 888, 248, 760, 504, 1016, 4, 516, 260, 772,
+	132, 644, 388, 900, 68, 580, 324, 836, 196, 708, 452, 964, 36, 548, 292,
+	804, 164, 676, 420, 932, 100, 612, 356, 868, 228, 740, 484, 996, 20,
+	532, 276, 788, 148, 660, 404, 916, 84, 596, 340, 852, 212, 724, 468,
+	980, 52, 564, 308, 820, 180, 692, 436, 948, 116, 628, 372, 884, 244,
+	756, 500, 1012, 12, 524, 268, 780, 140, 652, 396, 908, 76, 588, 332,
+	844, 204, 716, 460, 972, 44, 556, 300, 812, 172, 684, 428, 940, 108,
+	620, 364, 876, 236, 748, 492, 1004, 28, 540, 284, 796, 156, 668, 412,
+	924, 92, 604, 348, 860, 220, 732, 476, 988, 60, 572, 316, 828, 188, 700,
+	444, 956, 124, 636, 380, 892, 252, 764, 508, 1020, 2, 514, 258, 770,
+	130, 642, 386, 898, 66, 578, 322, 834, 194, 706, 450, 962, 34, 546, 290,
+	802, 162, 674, 418, 930, 98, 610, 354, 866, 226, 738, 482, 994, 18, 530,
+	274, 786, 146, 658, 402, 914, 82, 594, 338, 850, 210, 722, 466, 978, 50,
+	562, 306, 818, 178, 690, 434, 946, 114, 626, 370, 882, 242, 754, 498,
+	1010, 10, 522, 266, 778, 138, 650, 394, 906, 74, 586, 330, 842, 202,
+	714, 458, 970, 42, 554, 298, 810, 170, 682, 426, 938, 106, 618, 362,
+	874, 234, 746, 490, 1002, 26, 538, 282, 794, 154, 666, 410, 922, 90,
+	602, 346, 858, 218, 730, 474, 986, 58, 570, 314, 826, 186, 698, 442,
+	954, 122, 634, 378, 890, 250, 762, 506, 1018, 6, 518, 262, 774, 134,
+	646, 390, 902, 70, 582, 326, 838, 198, 710, 454, 966, 38, 550, 294, 806,
+	166, 678, 422, 934, 102, 614, 358, 870, 230, 742, 486, 998, 22, 534,
+	278, 790, 150, 662, 406, 918, 86, 598, 342, 854, 214, 726, 470, 982, 54,
+	566, 310, 822, 182, 694, 438, 950, 118, 630, 374, 886, 246, 758, 502,
+	1014, 14, 526, 270, 782, 142, 654, 398, 910, 78, 590, 334, 846, 206,
+	718, 462, 974, 46, 558, 302, 814, 174, 686, 430, 942, 110, 622, 366,
+	878, 238, 750, 494, 1006, 30, 542, 286, 798, 158, 670, 414, 926, 94,
+	606, 350, 862, 222, 734, 478, 990, 62, 574, 318, 830, 190, 702, 446,
+	958, 126, 638, 382, 894, 254, 766, 510, 1022, 1, 513, 257, 769, 129,
+	641, 385, 897, 65, 577, 321, 833, 193, 705, 449, 961, 33, 545, 289, 801,
+	161, 673, 417, 929, 97, 609, 353, 865, 225, 737, 481, 993, 17, 529, 273,
+	785, 145, 657, 401, 913, 81, 593, 337, 849, 209, 721, 465, 977, 49, 561,
+	305, 817, 177, 689, 433, 945, 113, 625, 369, 881, 241, 753, 497, 1009,
+	9, 521, 265, 777, 137, 649, 393, 905, 73, 585, 329, 841, 201, 713, 457,
+	969, 41, 553, 297, 809, 169, 681, 425, 937, 105, 617, 361, 873, 233,
+	745, 489, 1001, 25, 537, 281, 793, 153, 665, 409, 921, 89, 601, 345,
+	857, 217, 729, 473, 985, 57, 569, 313, 825, 185, 697, 441, 953, 121,
+	633, 377, 889, 249, 761, 505, 1017, 5, 517, 261, 773, 133, 645, 389,
+	901, 69, 581, 325, 837, 197, 709, 453, 965, 37, 549, 293, 805, 165, 677,
+	421, 933, 101, 613, 357, 869, 229, 741, 485, 997, 21, 533, 277, 789,
+	149, 661, 405, 917, 85, 597, 341, 853, 213, 725, 469, 981, 53, 565, 309,
+	821, 181, 693, 437, 949, 117, 629, 373, 885, 245, 757, 501, 1013, 13,
+	525, 269, 781, 141, 653, 397, 909, 77, 589, 333, 845, 205, 717, 461,
+	973, 45, 557, 301, 813, 173, 685, 429, 941, 109, 621, 365, 877, 237,
+	749, 493, 1005, 29, 541, 285, 797, 157, 669, 413, 925, 93, 605, 349,
+	861, 221, 733, 477, 989, 61, 573, 317, 829, 189, 701, 445, 957, 125,
+	637, 381, 893, 253, 765, 509, 1021, 3, 515, 259, 771, 131, 643, 387,
+	899, 67, 579, 323, 835, 195, 707, 451, 963, 35, 547, 291, 803, 163, 675,
+	419, 931, 99, 611, 355, 867, 227, 739, 483, 995, 19, 531, 275, 787, 147,
+	659, 403, 915, 83, 595, 339, 851, 211, 723, 467, 979, 51, 563, 307, 819,
+	179, 691, 435, 947, 115, 627, 371, 883, 243, 755, 499, 1011, 11, 523,
+	267, 779, 139, 651, 395, 907, 75, 587, 331, 843, 203, 715, 459, 971, 43,
+	555, 299, 811, 171, 683, 427, 939, 107, 619, 363, 875, 235, 747, 491,
+	1003, 27, 539, 283, 795, 155, 667, 411, 923, 91, 603, 347, 859, 219,
+	731, 475, 987, 59, 571, 315, 827, 187, 699, 443, 955, 123, 635, 379,
+	891, 251, 763, 507, 1019, 7, 519, 263, 775, 135, 647, 391, 903, 71, 583,
+	327, 839, 199, 711, 455, 967, 39, 551, 295, 807, 167, 679, 423, 935,
+	103, 615, 359, 871, 231, 743, 487, 999, 23, 535, 279, 791, 151, 663,
+	407, 919, 87, 599, 343, 855, 215, 727, 471, 983, 55, 567, 311, 823, 183,
+	695, 439, 951, 119, 631, 375, 887, 247, 759, 503, 1015, 15, 527, 271,
+	783, 143, 655, 399, 911, 79, 591, 335, 847, 207, 719, 463, 975, 47, 559,
+	303, 815, 175, 687, 431, 943, 111, 623, 367, 879, 239, 751, 495, 1007,
+	31, 543, 287, 799, 159, 671, 415, 927, 95, 607, 351, 863, 223, 735, 479,
+	991, 63, 575, 319, 831, 191, 703, 447, 959, 127, 639, 383, 895, 255,
+	767, 511, 1023,
+}
+
+func (p *poly) bitrev() {
+	for i, v := range p.v {
+		r := bitrevTable[i]
+		if uint16(i) < r {
+			p.v[i] = p.v[r]
+			p.v[r] = v
+		}
+	}
+}
+
+func (p *poly) mulCoefficients(factors *[paramN]uint16) {
+	for i, v := range factors {
+		p.v[i] = montgomeryReduce(uint32(p.v[i]) * uint32(v))
+	}
+}
+
+func ntt(a *[paramN]uint16, omega *[paramN / 2]uint16) {
+	var distance uint
+
+	for i := uint(0); i < 10; i += 2 {
+		// Even level.
+		distance = (1 << i)
+		for start := uint(0); start < distance; start++ {
+			jTwiddle := 0
+			for j := start; j < paramN-1; j += 2 * distance {
+				w := uint32(omega[jTwiddle])
+				jTwiddle++
+				tmp := a[j]
+				a[j] = tmp + a[j+distance]
+				a[j+distance] = montgomeryReduce(w * (uint32(tmp) + 3*paramQ - uint32(a[j+distance])))
+			}
+		}
+
+		// Odd level.
+		distance <<= 1
+		for start := uint(0); start < distance; start++ {
+			jTwiddle := 0
+			for j := start; j < paramN-1; j += 2 * distance {
+				w := uint32(omega[jTwiddle])
+				jTwiddle++
+				tmp := a[j]
+				a[j] = barrettReduce(tmp + a[j+distance])
+				a[j+distance] = montgomeryReduce(w * (uint32(tmp) + 3*paramQ - uint32(a[j+distance])))
+			}
+		}
+	}
+}

+ 15 - 0
params.go

@@ -0,0 +1,15 @@
+// params.go - New Hope parameters.
+//
+// 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
+
+const (
+	paramN    = 1024
+	paramK    = 12 // used in sampler
+	paramQ    = 12289
+	seedBytes = 32
+)

+ 158 - 0
poly.go

@@ -0,0 +1,158 @@
+// poly.go - New Hope polynomial.
+//
+// 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
+
+import (
+	"encoding/binary"
+
+	"golang.org/x/crypto/sha3"
+	"github.com/yawning/newhope/chacha20"
+)
+
+const (
+	// PolyBytes is the length of an encoded polynomial in bytes.
+	PolyBytes = 2048
+
+	shake128Rate = 168 // Stupid that this isn't exposed.
+)
+
+type poly struct {
+	v [paramN]uint16
+}
+
+func (p *poly) reset() {
+	for i := range p.v {
+		p.v[i] = 0
+	}
+}
+
+func (p *poly) fromBytes(a []byte) {
+	for i := range p.v {
+		p.v[i] = binary.LittleEndian.Uint16(a[2*i:]) & 0x3fff
+	}
+}
+
+func (p *poly) toBytes(r []byte) {
+	for i, v := range p.v {
+		// Make sure that coefficients have only 14 bits.
+		t := barrettReduce(v)
+		m := t - paramQ
+		c := int16(m)
+		c >>= 15
+		// Make sure that coefficients are in [0,q]
+		t = m ^ ((t ^ m) & uint16(c))
+		binary.LittleEndian.PutUint16(r[2*i:], t)
+	}
+}
+
+func (p *poly) uniform(seed *[seedBytes]byte) {
+	nBlocks := 16
+	var buf [shake128Rate * 16]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; {
+		// Specialized for q = 12889.
+		val := binary.LittleEndian.Uint16(buf[pos:]) & 0x3fff
+
+		if val < paramQ {
+			p.v[ctr] = val
+			ctr++
+		}
+		pos += 2
+		if pos > shake128Rate*nBlocks-2 {
+			nBlocks = 1
+			h.Read(buf[:shake128Rate])
+			pos = 0
+		}
+	}
+}
+
+func (p *poly) getNoise(seed *[seedBytes]byte, nonce byte) {
+	var buf [3 * paramN]byte
+	var n [8]byte
+	var v uint32
+	var b [4]byte
+
+	n[0] = nonce
+	stream, err := chacha20.NewCipher(seed[:], n[:])
+	if err != nil {
+		panic(err)
+	}
+	stream.XORKeyStream(buf[:], buf[:])
+	stream.Reset()
+
+	// First half of the output.
+	for i := 0; i < paramN/2; i += 2 {
+		v = 0
+		jV := binary.LittleEndian.Uint32(buf[2*i:])
+		for j := uint(0); j < 8; j++ {
+			v += (jV >> j) & 0x01010101
+		}
+		jV = binary.LittleEndian.Uint32(buf[2*i+2*paramN:])
+		for j := uint(0); j < 4; j++ {
+			v += (jV >> j) & 0x01010101
+		}
+		binary.LittleEndian.PutUint32(b[0:], v)
+		p.v[i] = paramQ + uint16(b[0]) - uint16(b[1])
+		p.v[i+1] = paramQ + uint16(b[2]) - uint16(b[3])
+	}
+
+	// Second half of the output.
+	for i := 0; i < paramN/2; i += 2 {
+		v = 0
+		jV := binary.LittleEndian.Uint32(buf[2*i+paramN:])
+		for j := uint(0); j < 8; j++ {
+			v += (jV >> j) & 0x01010101
+		}
+		jV = binary.LittleEndian.Uint32(buf[2*i+2*paramN:])
+		for j := uint(0); j < 4; j++ {
+			v += (jV >> (j + 4)) & 0x01010101
+		}
+		binary.LittleEndian.PutUint32(b[0:], v)
+		p.v[i+paramN/2] = paramQ + uint16(b[0]) - uint16(b[1])
+		p.v[i+paramN/2+1] = paramQ + uint16(b[2]) - uint16(b[3])
+	}
+
+	// Scrub the random bits...
+	v = 0
+	memwipe(b[:])
+	memwipe(buf[:])
+}
+
+func (p *poly) pointwise(a, b *poly) {
+	for i := range p.v {
+		t := montgomeryReduce(3186 * uint32(b.v[i]))          // t is now in Montgomery domain
+		p.v[i] = montgomeryReduce(uint32(a.v[i]) * uint32(t)) // p.v[i] is back in normal domain
+	}
+}
+
+func (p *poly) add(a, b *poly) {
+	for i := range p.v {
+		p.v[i] = barrettReduce(a.v[i] + b.v[i])
+	}
+}
+
+func (p *poly) ntt() {
+	p.mulCoefficients(&psisBitrevMontgomery)
+	ntt(&p.v, &omegasMontgomery)
+}
+
+func (p *poly) invNtt() {
+	ntt(&p.v, &omegasInvMontgomery)
+	p.mulCoefficients(&psisInvMontgomery)
+}
+
+func init() {
+	if paramK != 12 {
+		panic("poly.getNoise() only supports k=12")
+	}
+}

+ 287 - 0
precomp.go

@@ -0,0 +1,287 @@
+// precomp.go - New Hope precomputed tables.
+//
+// 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
+
+var omegasMontgomery = [paramN / 2]uint16{
+	4075, 6974, 7373, 7965, 3262, 5079, 522, 2169, 6364, 1018, 1041, 8775, 2344,
+	11011, 5574, 1973, 4536, 1050, 6844, 3860, 3818, 6118, 2683, 1190, 4789,
+	7822, 7540, 6752, 5456, 4449, 3789, 12142, 11973, 382, 3988, 468, 6843,
+	5339, 6196, 3710, 11316, 1254, 5435, 10930, 3998, 10256, 10367, 3879,
+	11889, 1728, 6137, 4948, 5862, 6136, 3643, 6874, 8724, 654, 10302, 1702,
+	7083, 6760, 56, 3199, 9987, 605, 11785, 8076, 5594, 9260, 6403, 4782,
+	6212, 4624, 9026, 8689, 4080, 11868, 6221, 3602, 975, 8077, 8851, 9445,
+	5681, 3477, 1105, 142, 241, 12231, 1003, 3532, 5009, 1956, 6008, 11404,
+	7377, 2049, 10968, 12097, 7591, 5057, 3445, 4780, 2920, 7048, 3127,
+	8120, 11279, 6821, 11502, 8807, 12138, 2127, 2839, 3957, 431, 1579,
+	6383, 9784, 5874, 677, 3336, 6234, 2766, 1323, 9115, 12237, 2031, 6956,
+	6413, 2281, 3969, 3991, 12133, 9522, 4737, 10996, 4774, 5429, 11871,
+	3772, 453, 5908, 2882, 1805, 2051, 1954, 11713, 3963, 2447, 6142, 8174,
+	3030, 1843, 2361, 12071, 2908, 3529, 3434, 3202, 7796, 2057, 5369,
+	11939, 1512, 6906, 10474, 11026, 49, 10806, 5915, 1489, 9789, 5942,
+	10706, 10431, 7535, 426, 8974, 3757, 10314, 9364, 347, 5868, 9551, 9634,
+	6554, 10596, 9280, 11566, 174, 2948, 2503, 6507, 10723, 11606, 2459, 64,
+	3656, 8455, 5257, 5919, 7856, 1747, 9166, 5486, 9235, 6065, 835, 3570,
+	4240, 11580, 4046, 10970, 9139, 1058, 8210, 11848, 922, 7967, 1958,
+	10211, 1112, 3728, 4049, 11130, 5990, 1404, 325, 948, 11143, 6190, 295,
+	11637, 5766, 8212, 8273, 2919, 8527, 6119, 6992, 8333, 1360, 2555, 6167,
+	1200, 7105, 7991, 3329, 9597, 12121, 5106, 5961, 10695, 10327, 3051,
+	9923, 4896, 9326, 81, 3091, 1000, 7969, 4611, 726, 1853, 12149, 4255,
+	11112, 2768, 10654, 1062, 2294, 3553, 4805, 2747, 4846, 8577, 9154,
+	1170, 2319, 790, 11334, 9275, 9088, 1326, 5086, 9094, 6429, 11077,
+	10643, 3504, 3542, 8668, 9744, 1479, 1, 8246, 7143, 11567, 10984, 4134,
+	5736, 4978, 10938, 5777, 8961, 4591, 5728, 6461, 5023, 9650, 7468, 949,
+	9664, 2975, 11726, 2744, 9283, 10092, 5067, 12171, 2476, 3748, 11336,
+	6522, 827, 9452, 5374, 12159, 7935, 3296, 3949, 9893, 4452, 10908, 2525,
+	3584, 8112, 8011, 10616, 4989, 6958, 11809, 9447, 12280, 1022, 11950,
+	9821, 11745, 5791, 5092, 2089, 9005, 2881, 3289, 2013, 9048, 729, 7901,
+	1260, 5755, 4632, 11955, 2426, 10593, 1428, 4890, 5911, 3932, 9558,
+	8830, 3637, 5542, 145, 5179, 8595, 3707, 10530, 355, 3382, 4231, 9741,
+	1207, 9041, 7012, 1168, 10146, 11224, 4645, 11885, 10911, 10377, 435,
+	7952, 4096, 493, 9908, 6845, 6039, 2422, 2187, 9723, 8643, 9852, 9302,
+	6022, 7278, 1002, 4284, 5088, 1607, 7313, 875, 8509, 9430, 1045, 2481,
+	5012, 7428, 354, 6591, 9377, 11847, 2401, 1067, 7188, 11516, 390, 8511,
+	8456, 7270, 545, 8585, 9611, 12047, 1537, 4143, 4714, 4885, 1017, 5084,
+	1632, 3066, 27, 1440, 8526, 9273, 12046, 11618, 9289, 3400, 9890, 3136,
+	7098, 8758, 11813, 7384, 3985, 11869, 6730, 10745, 10111, 2249, 4048,
+	2884, 11136, 2126, 1630, 9103, 5407, 2686, 9042, 2969, 8311, 9424, 9919,
+	8779, 5332, 10626, 1777, 4654, 10863, 7351, 3636, 9585, 5291, 8374,
+	2166, 4919, 12176, 9140, 12129, 7852, 12286, 4895, 10805, 2780, 5195,
+	2305, 7247, 9644, 4053, 10600, 3364, 3271, 4057, 4414, 9442, 7917, 2174,
+}
+
+var omegasInvMontgomery = [paramN / 2]uint16{
+	4075, 5315, 4324, 4916, 10120, 11767, 7210, 9027, 10316, 6715, 1278, 9945,
+	3514, 11248, 11271, 5925, 147, 8500, 7840, 6833, 5537, 4749, 4467, 7500,
+	11099, 9606, 6171, 8471, 8429, 5445, 11239, 7753, 9090, 12233, 5529,
+	5206, 10587, 1987, 11635, 3565, 5415, 8646, 6153, 6427, 7341, 6152,
+	10561, 400, 8410, 1922, 2033, 8291, 1359, 6854, 11035, 973, 8579, 6093,
+	6950, 5446, 11821, 8301, 11907, 316, 52, 3174, 10966, 9523, 6055, 8953,
+	11612, 6415, 2505, 5906, 10710, 11858, 8332, 9450, 10162, 151, 3482,
+	787, 5468, 1010, 4169, 9162, 5241, 9369, 7509, 8844, 7232, 4698, 192,
+	1321, 10240, 4912, 885, 6281, 10333, 7280, 8757, 11286, 58, 12048,
+	12147, 11184, 8812, 6608, 2844, 3438, 4212, 11314, 8687, 6068, 421,
+	8209, 3600, 3263, 7665, 6077, 7507, 5886, 3029, 6695, 4213, 504, 11684,
+	2302, 1962, 1594, 6328, 7183, 168, 2692, 8960, 4298, 5184, 11089, 6122,
+	9734, 10929, 3956, 5297, 6170, 3762, 9370, 4016, 4077, 6523, 652, 11994,
+	6099, 1146, 11341, 11964, 10885, 6299, 1159, 8240, 8561, 11177, 2078,
+	10331, 4322, 11367, 441, 4079, 11231, 3150, 1319, 8243, 709, 8049, 8719,
+	11454, 6224, 3054, 6803, 3123, 10542, 4433, 6370, 7032, 3834, 8633,
+	12225, 9830, 683, 1566, 5782, 9786, 9341, 12115, 723, 3009, 1693, 5735,
+	2655, 2738, 6421, 11942, 2925, 1975, 8532, 3315, 11863, 4754, 1858,
+	1583, 6347, 2500, 10800, 6374, 1483, 12240, 1263, 1815, 5383, 10777,
+	350, 6920, 10232, 4493, 9087, 8855, 8760, 9381, 218, 9928, 10446, 9259,
+	4115, 6147, 9842, 8326, 576, 10335, 10238, 10484, 9407, 6381, 11836,
+	8517, 418, 6860, 7515, 1293, 7552, 2767, 156, 8298, 8320, 10008, 5876,
+	5333, 10258, 10115, 4372, 2847, 7875, 8232, 9018, 8925, 1689, 8236,
+	2645, 5042, 9984, 7094, 9509, 1484, 7394, 3, 4437, 160, 3149, 113, 7370,
+	10123, 3915, 6998, 2704, 8653, 4938, 1426, 7635, 10512, 1663, 6957,
+	3510, 2370, 2865, 3978, 9320, 3247, 9603, 6882, 3186, 10659, 10163,
+	1153, 9405, 8241, 10040, 2178, 1544, 5559, 420, 8304, 4905, 476, 3531,
+	5191, 9153, 2399, 8889, 3000, 671, 243, 3016, 3763, 10849, 12262, 9223,
+	10657, 7205, 11272, 7404, 7575, 8146, 10752, 242, 2678, 3704, 11744,
+	5019, 3833, 3778, 11899, 773, 5101, 11222, 9888, 442, 2912, 5698, 11935,
+	4861, 7277, 9808, 11244, 2859, 3780, 11414, 4976, 10682, 7201, 8005,
+	11287, 5011, 6267, 2987, 2437, 3646, 2566, 10102, 9867, 6250, 5444,
+	2381, 11796, 8193, 4337, 11854, 1912, 1378, 404, 7644, 1065, 2143,
+	11121, 5277, 3248, 11082, 2548, 8058, 8907, 11934, 1759, 8582, 3694,
+	7110, 12144, 6747, 8652, 3459, 2731, 8357, 6378, 7399, 10861, 1696,
+	9863, 334, 7657, 6534, 11029, 4388, 11560, 3241, 10276, 9000, 9408,
+	3284, 10200, 7197, 6498, 544, 2468, 339, 11267, 9, 2842, 480, 5331,
+	7300, 1673, 4278, 4177, 8705, 9764, 1381, 7837, 2396, 8340, 8993, 4354,
+	130, 6915, 2837, 11462, 5767, 953, 8541, 9813, 118, 7222, 2197, 3006,
+	9545, 563, 9314, 2625, 11340, 4821, 2639, 7266, 5828, 6561, 7698, 3328,
+	6512, 1351, 7311, 6553, 8155, 1305, 722, 5146, 4043, 12288, 10810, 2545,
+	3621, 8747, 8785, 1646, 1212, 5860, 3195, 7203, 10963, 3201, 3014, 955,
+	11499, 9970, 11119, 3135, 3712, 7443, 9542, 7484, 8736, 9995, 11227,
+	1635, 9521, 1177, 8034, 140, 10436, 11563, 7678, 4320, 11289, 9198,
+	12208, 2963, 7393, 2366, 9238,
+}
+
+var psisBitrevMontgomery = [paramN]uint16{
+	4075, 6974, 7373, 7965, 3262, 5079, 522, 2169, 6364, 1018, 1041, 8775, 2344,
+	11011, 5574, 1973, 4536, 1050, 6844, 3860, 3818, 6118, 2683, 1190, 4789,
+	7822, 7540, 6752, 5456, 4449, 3789, 12142, 11973, 382, 3988, 468, 6843,
+	5339, 6196, 3710, 11316, 1254, 5435, 10930, 3998, 10256, 10367, 3879,
+	11889, 1728, 6137, 4948, 5862, 6136, 3643, 6874, 8724, 654, 10302, 1702,
+	7083, 6760, 56, 3199, 9987, 605, 11785, 8076, 5594, 9260, 6403, 4782,
+	6212, 4624, 9026, 8689, 4080, 11868, 6221, 3602, 975, 8077, 8851, 9445,
+	5681, 3477, 1105, 142, 241, 12231, 1003, 3532, 5009, 1956, 6008, 11404,
+	7377, 2049, 10968, 12097, 7591, 5057, 3445, 4780, 2920, 7048, 3127,
+	8120, 11279, 6821, 11502, 8807, 12138, 2127, 2839, 3957, 431, 1579,
+	6383, 9784, 5874, 677, 3336, 6234, 2766, 1323, 9115, 12237, 2031, 6956,
+	6413, 2281, 3969, 3991, 12133, 9522, 4737, 10996, 4774, 5429, 11871,
+	3772, 453, 5908, 2882, 1805, 2051, 1954, 11713, 3963, 2447, 6142, 8174,
+	3030, 1843, 2361, 12071, 2908, 3529, 3434, 3202, 7796, 2057, 5369,
+	11939, 1512, 6906, 10474, 11026, 49, 10806, 5915, 1489, 9789, 5942,
+	10706, 10431, 7535, 426, 8974, 3757, 10314, 9364, 347, 5868, 9551, 9634,
+	6554, 10596, 9280, 11566, 174, 2948, 2503, 6507, 10723, 11606, 2459, 64,
+	3656, 8455, 5257, 5919, 7856, 1747, 9166, 5486, 9235, 6065, 835, 3570,
+	4240, 11580, 4046, 10970, 9139, 1058, 8210, 11848, 922, 7967, 1958,
+	10211, 1112, 3728, 4049, 11130, 5990, 1404, 325, 948, 11143, 6190, 295,
+	11637, 5766, 8212, 8273, 2919, 8527, 6119, 6992, 8333, 1360, 2555, 6167,
+	1200, 7105, 7991, 3329, 9597, 12121, 5106, 5961, 10695, 10327, 3051,
+	9923, 4896, 9326, 81, 3091, 1000, 7969, 4611, 726, 1853, 12149, 4255,
+	11112, 2768, 10654, 1062, 2294, 3553, 4805, 2747, 4846, 8577, 9154,
+	1170, 2319, 790, 11334, 9275, 9088, 1326, 5086, 9094, 6429, 11077,
+	10643, 3504, 3542, 8668, 9744, 1479, 1, 8246, 7143, 11567, 10984, 4134,
+	5736, 4978, 10938, 5777, 8961, 4591, 5728, 6461, 5023, 9650, 7468, 949,
+	9664, 2975, 11726, 2744, 9283, 10092, 5067, 12171, 2476, 3748, 11336,
+	6522, 827, 9452, 5374, 12159, 7935, 3296, 3949, 9893, 4452, 10908, 2525,
+	3584, 8112, 8011, 10616, 4989, 6958, 11809, 9447, 12280, 1022, 11950,
+	9821, 11745, 5791, 5092, 2089, 9005, 2881, 3289, 2013, 9048, 729, 7901,
+	1260, 5755, 4632, 11955, 2426, 10593, 1428, 4890, 5911, 3932, 9558,
+	8830, 3637, 5542, 145, 5179, 8595, 3707, 10530, 355, 3382, 4231, 9741,
+	1207, 9041, 7012, 1168, 10146, 11224, 4645, 11885, 10911, 10377, 435,
+	7952, 4096, 493, 9908, 6845, 6039, 2422, 2187, 9723, 8643, 9852, 9302,
+	6022, 7278, 1002, 4284, 5088, 1607, 7313, 875, 8509, 9430, 1045, 2481,
+	5012, 7428, 354, 6591, 9377, 11847, 2401, 1067, 7188, 11516, 390, 8511,
+	8456, 7270, 545, 8585, 9611, 12047, 1537, 4143, 4714, 4885, 1017, 5084,
+	1632, 3066, 27, 1440, 8526, 9273, 12046, 11618, 9289, 3400, 9890, 3136,
+	7098, 8758, 11813, 7384, 3985, 11869, 6730, 10745, 10111, 2249, 4048,
+	2884, 11136, 2126, 1630, 9103, 5407, 2686, 9042, 2969, 8311, 9424, 9919,
+	8779, 5332, 10626, 1777, 4654, 10863, 7351, 3636, 9585, 5291, 8374,
+	2166, 4919, 12176, 9140, 12129, 7852, 12286, 4895, 10805, 2780, 5195,
+	2305, 7247, 9644, 4053, 10600, 3364, 3271, 4057, 4414, 9442, 7917, 2174,
+	3947, 11951, 2455, 6599, 10545, 10975, 3654, 2894, 7681, 7126, 7287,
+	12269, 4119, 3343, 2151, 1522, 7174, 7350, 11041, 2442, 2148, 5959,
+	6492, 8330, 8945, 5598, 3624, 10397, 1325, 6565, 1945, 11260, 10077,
+	2674, 3338, 3276, 11034, 506, 6505, 1392, 5478, 8778, 1178, 2776, 3408,
+	10347, 11124, 2575, 9489, 12096, 6092, 10058, 4167, 6085, 923, 11251,
+	11912, 4578, 10669, 11914, 425, 10453, 392, 10104, 8464, 4235, 8761,
+	7376, 2291, 3375, 7954, 8896, 6617, 7790, 1737, 11667, 3982, 9342, 6680,
+	636, 6825, 7383, 512, 4670, 2900, 12050, 7735, 994, 1687, 11883, 7021,
+	146, 10485, 1403, 5189, 6094, 2483, 2054, 3042, 10945, 3981, 10821,
+	11826, 8882, 8151, 180, 9600, 7684, 5219, 10880, 6780, 204, 11232, 2600,
+	7584, 3121, 3017, 11053, 7814, 7043, 4251, 4739, 11063, 6771, 7073,
+	9261, 2360, 11925, 1928, 11825, 8024, 3678, 3205, 3359, 11197, 5209,
+	8581, 3238, 8840, 1136, 9363, 1826, 3171, 4489, 7885, 346, 2068, 1389,
+	8257, 3163, 4840, 6127, 8062, 8921, 612, 4238, 10763, 8067, 125, 11749,
+	10125, 5416, 2110, 716, 9839, 10584, 11475, 11873, 3448, 343, 1908,
+	4538, 10423, 7078, 4727, 1208, 11572, 3589, 2982, 1373, 1721, 10753,
+	4103, 2429, 4209, 5412, 5993, 9011, 438, 3515, 7228, 1218, 8347, 5232,
+	8682, 1327, 7508, 4924, 448, 1014, 10029, 12221, 4566, 5836, 12229,
+	2717, 1535, 3200, 5588, 5845, 412, 5102, 7326, 3744, 3056, 2528, 7406,
+	8314, 9202, 6454, 6613, 1417, 10032, 7784, 1518, 3765, 4176, 5063, 9828,
+	2275, 6636, 4267, 6463, 2065, 7725, 3495, 8328, 8755, 8144, 10533, 5966,
+	12077, 9175, 9520, 5596, 6302, 8400, 579, 6781, 11014, 5734, 11113,
+	11164, 4860, 1131, 10844, 9068, 8016, 9694, 3837, 567, 9348, 7000, 6627,
+	7699, 5082, 682, 11309, 5207, 4050, 7087, 844, 7434, 3769, 293, 9057,
+	6940, 9344, 10883, 2633, 8190, 3944, 5530, 5604, 3480, 2171, 9282,
+	11024, 2213, 8136, 3805, 767, 12239, 216, 11520, 6763, 10353, 7, 8566,
+	845, 7235, 3154, 4360, 3285, 10268, 2832, 3572, 1282, 7559, 3229, 8360,
+	10583, 6105, 3120, 6643, 6203, 8536, 8348, 6919, 3536, 9199, 10891,
+	11463, 5043, 1658, 5618, 8787, 5789, 4719, 751, 11379, 6389, 10783,
+	3065, 7806, 6586, 2622, 5386, 510, 7628, 6921, 578, 10345, 11839, 8929,
+	4684, 12226, 7154, 9916, 7302, 8481, 3670, 11066, 2334, 1590, 7878,
+	10734, 1802, 1891, 5103, 6151, 8820, 3418, 7846, 9951, 4693, 417, 9996,
+	9652, 4510, 2946, 5461, 365, 881, 1927, 1015, 11675, 11009, 1371, 12265,
+	2485, 11385, 5039, 6742, 8449, 1842, 12217, 8176, 9577, 4834, 7937,
+	9461, 2643, 11194, 3045, 6508, 4094, 3451, 7911, 11048, 5406, 4665,
+	3020, 6616, 11345, 7519, 3669, 5287, 1790, 7014, 5410, 11038, 11249,
+	2035, 6125, 10407, 4565, 7315, 5078, 10506, 2840, 2478, 9270, 4194,
+	9195, 4518, 7469, 1160, 6878, 2730, 10421, 10036, 1734, 3815, 10939,
+	5832, 10595, 10759, 4423, 8420, 9617, 7119, 11010, 11424, 9173, 189,
+	10080, 10526, 3466, 10588, 7592, 3578, 11511, 7785, 9663, 530, 12150,
+	8957, 2532, 3317, 9349, 10243, 1481, 9332, 3454, 3758, 7899, 4218, 2593,
+	11410, 2276, 982, 6513, 1849, 8494, 9021, 4523, 7988, 8, 457, 648, 150,
+	8000, 2307, 2301, 874, 5650, 170, 9462, 2873, 9855, 11498, 2535, 11169,
+	5808, 12268, 9687, 1901, 7171, 11787, 3846, 1573, 6063, 3793, 466,
+	11259, 10608, 3821, 6320, 4649, 6263, 2929,
+}
+
+var psisInvMontgomery = [paramN]uint16{
+	256, 10570, 1510, 7238, 1034, 7170, 6291, 7921, 11665, 3422, 4000, 2327,
+	2088, 5565, 795, 10647, 1521, 5484, 2539, 7385, 1055, 7173, 8047, 11683,
+	1669, 1994, 3796, 5809, 4341, 9398, 11876, 12230, 10525, 12037, 12253,
+	3506, 4012, 9351, 4847, 2448, 7372, 9831, 3160, 2207, 5582, 2553, 7387,
+	6322, 9681, 1383, 10731, 1533, 219, 5298, 4268, 7632, 6357, 9686, 8406,
+	4712, 9451, 10128, 4958, 5975, 11387, 8649, 11769, 6948, 11526, 12180,
+	1740, 10782, 6807, 2728, 7412, 4570, 4164, 4106, 11120, 12122, 8754,
+	11784, 3439, 5758, 11356, 6889, 9762, 11928, 1704, 1999, 10819, 12079,
+	12259, 7018, 11536, 1648, 1991, 2040, 2047, 2048, 10826, 12080, 8748,
+	8272, 8204, 1172, 1923, 7297, 2798, 7422, 6327, 4415, 7653, 6360, 11442,
+	12168, 7005, 8023, 9924, 8440, 8228, 2931, 7441, 1063, 3663, 5790, 9605,
+	10150, 1450, 8985, 11817, 10466, 10273, 12001, 3470, 7518, 1074, 1909,
+	7295, 9820, 4914, 702, 5367, 7789, 8135, 9940, 1420, 3714, 11064, 12114,
+	12264, 1752, 5517, 9566, 11900, 1700, 3754, 5803, 829, 1874, 7290, 2797,
+	10933, 5073, 7747, 8129, 6428, 6185, 11417, 1631, 233, 5300, 9535,
+	10140, 11982, 8734, 8270, 2937, 10953, 8587, 8249, 2934, 9197, 4825,
+	5956, 4362, 9401, 1343, 3703, 529, 10609, 12049, 6988, 6265, 895, 3639,
+	4031, 4087, 4095, 585, 10617, 8539, 4731, 4187, 9376, 3095, 9220, 10095,
+	10220, 1460, 10742, 12068, 1724, 5513, 11321, 6884, 2739, 5658, 6075,
+	4379, 11159, 10372, 8504, 4726, 9453, 3106, 7466, 11600, 10435, 8513,
+	9994, 8450, 9985, 3182, 10988, 8592, 2983, 9204, 4826, 2445, 5616, 6069,
+	867, 3635, 5786, 11360, 5134, 2489, 10889, 12089, 1727, 7269, 2794,
+	9177, 1311, 5454, 9557, 6632, 2703, 9164, 10087, 1441, 3717, 531, 3587,
+	2268, 324, 5313, 759, 1864, 5533, 2546, 7386, 9833, 8427, 4715, 11207,
+	1601, 7251, 4547, 11183, 12131, 1733, 10781, 10318, 1474, 10744, 5046,
+	4232, 11138, 10369, 6748, 964, 7160, 4534, 7670, 8118, 8182, 4680,
+	11202, 6867, 981, 8918, 1274, 182, 26, 7026, 8026, 11680, 12202, 10521,
+	1503, 7237, 4545, 5916, 9623, 8397, 11733, 10454, 3249, 9242, 6587, 941,
+	1890, 270, 10572, 6777, 9746, 6659, 6218, 6155, 6146, 878, 1881, 7291,
+	11575, 12187, 1741, 7271, 8061, 11685, 6936, 4502, 9421, 4857, 4205,
+	7623, 1089, 10689, 1527, 8996, 10063, 11971, 10488, 6765, 2722, 3900,
+	9335, 11867, 6962, 11528, 5158, 4248, 4118, 5855, 2592, 5637, 6072,
+	2623, 7397, 8079, 9932, 4930, 5971, 853, 3633, 519, 8852, 11798, 3441,
+	11025, 1575, 225, 8810, 11792, 12218, 3501, 9278, 3081, 9218, 4828,
+	7712, 8124, 11694, 12204, 3499, 4011, 573, 3593, 5780, 7848, 9899,
+	10192, 1456, 208, 7052, 2763, 7417, 11593, 10434, 12024, 8740, 11782,
+	10461, 3250, 5731, 7841, 9898, 1414, 202, 3540, 7528, 2831, 2160, 10842,
+	5060, 4234, 4116, 588, 84, 12, 7024, 2759, 9172, 6577, 11473, 1639,
+	9012, 3043, 7457, 6332, 11438, 1634, 1989, 9062, 11828, 8712, 11778,
+	12216, 10523, 6770, 9745, 10170, 4964, 9487, 6622, 946, 8913, 6540,
+	6201, 4397, 9406, 8366, 9973, 8447, 8229, 11709, 8695, 10020, 3187,
+	5722, 2573, 10901, 6824, 4486, 4152, 9371, 8361, 2950, 2177, 311, 1800,
+	9035, 8313, 11721, 3430, 490, 70, 10, 1757, 251, 3547, 7529, 11609,
+	3414, 7510, 4584, 4166, 9373, 1339, 5458, 7802, 11648, 1664, 7260, 9815,
+	10180, 6721, 9738, 10169, 8475, 8233, 9954, 1422, 8981, 1283, 5450,
+	11312, 1616, 3742, 11068, 10359, 4991, 713, 3613, 9294, 8350, 4704, 672,
+	96, 7036, 9783, 11931, 3460, 5761, 823, 10651, 12055, 10500, 1500, 5481,
+	783, 3623, 11051, 8601, 8251, 8201, 11705, 10450, 5004, 4226, 7626,
+	2845, 2162, 3820, 7568, 9859, 3164, 452, 10598, 1514, 5483, 6050, 6131,
+	4387, 7649, 8115, 6426, 918, 8909, 8295, 1185, 5436, 11310, 8638, 1234,
+	5443, 11311, 5127, 2488, 2111, 10835, 5059, 7745, 2862, 3920, 560, 80,
+	1767, 2008, 3798, 11076, 6849, 2734, 10924, 12094, 8750, 1250, 10712,
+	6797, 971, 7161, 1023, 8924, 4786, 7706, 4612, 4170, 7618, 6355, 4419,
+	5898, 11376, 10403, 10264, 6733, 4473, 639, 5358, 2521, 9138, 3061,
+	5704, 4326, 618, 5355, 765, 5376, 768, 7132, 4530, 9425, 3102, 9221,
+	6584, 11474, 10417, 10266, 12000, 6981, 6264, 4406, 2385, 7363, 4563,
+	4163, 7617, 9866, 3165, 9230, 11852, 10471, 5007, 5982, 11388, 5138,
+	734, 3616, 11050, 12112, 6997, 11533, 12181, 10518, 12036, 3475, 2252,
+	7344, 9827, 4915, 9480, 6621, 4457, 7659, 9872, 6677, 4465, 4149, 7615,
+	4599, 657, 3605, 515, 10607, 6782, 4480, 640, 1847, 3775, 5806, 2585,
+	5636, 9583, 1369, 10729, 8555, 10000, 11962, 5220, 7768, 8132, 8184,
+	9947, 1421, 203, 29, 8782, 11788, 1684, 10774, 10317, 4985, 9490, 8378,
+	4708, 11206, 5112, 5997, 7879, 11659, 12199, 8765, 10030, 4944, 5973,
+	6120, 6141, 6144, 7900, 11662, 1666, 238, 34, 3516, 5769, 9602, 8394,
+	9977, 6692, 956, 10670, 6791, 9748, 11926, 8726, 11780, 5194, 742, 106,
+	8793, 10034, 3189, 10989, 5081, 4237, 5872, 4350, 2377, 10873, 6820,
+	6241, 11425, 10410, 10265, 3222, 5727, 9596, 4882, 2453, 2106, 3812,
+	11078, 12116, 5242, 4260, 11142, 8614, 11764, 12214, 5256, 4262, 4120,
+	11122, 5100, 11262, 5120, 2487, 5622, 9581, 8391, 8221, 2930, 10952,
+	12098, 6995, 6266, 9673, 4893, 699, 3611, 4027, 5842, 11368, 1624, 232,
+	8811, 8281, 1183, 169, 8802, 3013, 2186, 5579, 797, 3625, 4029, 11109,
+	1587, 7249, 11569, 8675, 6506, 2685, 10917, 12093, 12261, 12285, 1755,
+	7273, 1039, 1904, 272, 3550, 9285, 3082, 5707, 6082, 4380, 7648, 11626,
+	5172, 4250, 9385, 8363, 8217, 4685, 5936, 848, 8899, 6538, 934, 1889,
+	3781, 9318, 10109, 10222, 6727, 961, 5404, 772, 5377, 9546, 8386, 1198,
+	8949, 3034, 2189, 7335, 4559, 5918, 2601, 10905, 5069, 9502, 3113, 7467,
+	8089, 11689, 5181, 9518, 8382, 2953, 3933, 4073, 4093, 7607, 8109, 2914,
+	5683, 4323, 11151, 1593, 10761, 6804, 972, 3650, 2277, 5592, 4310, 7638,
+	9869, 4921, 703, 1856, 9043, 4803, 9464, 1352, 8971, 11815, 5199, 7765,
+	6376, 4422, 7654, 2849, 407, 8836, 6529, 7955, 2892, 9191, 1313, 10721,
+	12065, 12257, 1751, 9028, 8312, 2943, 2176, 3822, 546, 78, 8789, 11789,
+	10462, 12028, 6985, 4509, 9422, 1346, 5459, 4291, 613, 10621, 6784,
+	9747, 3148, 7472, 2823, 5670, 810, 7138, 8042, 4660, 7688, 6365, 6176,
+	6149, 2634, 5643, 9584, 10147, 11983, 5223, 9524, 11894, 10477, 8519,
+	1217, 3685, 2282, 326, 10580, 3267, 7489, 4581, 2410, 5611, 11335, 6886,
+	8006, 8166, 11700, 3427, 11023, 8597, 10006, 3185, 455, 65, 5276, 7776,
+	4622, 5927, 7869, 9902, 11948, 5218, 2501, 5624, 2559, 10899, 1557,
+	1978, 10816, 10323, 8497, 4725, 675, 1852, 10798, 12076, 10503, 3256,
+	9243, 3076, 2195, 10847, 12083, 10504, 12034, 10497,
+}

+ 28 - 0
reduce.go

@@ -0,0 +1,28 @@
+// poly.go - New Hope reductions.
+//
+// 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
+
+const (
+	qinv = 12287 // -inverse_mod(p,2^18)
+	rlog = 18
+)
+
+func montgomeryReduce(a uint32) uint16 {
+	u := a * qinv
+	u &= ((1 << rlog) - 1)
+	u *= paramQ
+	a = (a + u) >> 18
+	return uint16(a)
+}
+
+func barrettReduce(a uint16) uint16 {
+	u := (uint32(a) * 5) >> 16
+	u *= paramQ
+	a -= uint16(u)
+	return a
+}