xs/vendor/git.schwanenlied.me/yawning/kyber.git/cbd.go
Russ Magee caac02a77b 1/2 Updated Makefile to allow VENDOR flag (adds -vendor to version string)
2/2 Added vendor/ dir to lock down dependent pkg versions.
The author of git.schwanenlied.me/yawning/{chacha20,newhope,kyber}.git has copied
their repos to gitlab.com/yawning/ but some imports of chacha20 from newhope still
inconsistently refer to git.schwanenlied.me/, breaking build.
Licenses for chacha20 also changed from CC0 to AGPL, which may or may not be an
issue. Until the two aforementioned issues are resolved, locking to last-good
versions is probably the best way forward for now.

To build with vendored deps, use make VENDOR=1 clean all
2020-01-29 13:55:38 -08:00

100 lines
2.6 KiB
Go

// cbd.go - Centered binomial distribution.
//
// To the extent possible under law, Yawning Angel has waived all copyright
// and related or neighboring rights to the software, using the Creative
// Commons "CC0" public domain dedication. See LICENSE or
// <http://creativecommons.org/publicdomain/zero/1.0/> for full details.
package kyber
// Load bytes into a 64-bit integer in little-endian order.
func loadLittleEndian(x []byte, bytes int) uint64 {
var r uint64
for i, v := range x[:bytes] {
r |= uint64(v) << (8 * uint(i))
}
return r
}
// Given an array of uniformly random bytes, compute polynomial with
// coefficients distributed according to a centered binomial distribution
// with parameter eta.
func (p *poly) cbd(buf []byte, eta int) {
hardwareAccelImpl.cbdFn(p, buf, eta)
}
func cbdRef(p *poly, buf []byte, eta int) {
switch eta {
case 3:
var a, b [4]uint32
for i := 0; i < kyberN/4; i++ {
t := loadLittleEndian(buf[3*i:], 3)
var d uint32
for j := 0; j < 3; j++ {
d += uint32((t >> uint(j)) & 0x249249)
}
a[0] = d & 0x7
b[0] = (d >> 3) & 0x7
a[1] = (d >> 6) & 0x7
b[1] = (d >> 9) & 0x7
a[2] = (d >> 12) & 0x7
b[2] = (d >> 15) & 0x7
a[3] = (d >> 18) & 0x7
b[3] = (d >> 21)
p.coeffs[4*i+0] = uint16(a[0] + kyberQ - b[0])
p.coeffs[4*i+1] = uint16(a[1] + kyberQ - b[1])
p.coeffs[4*i+2] = uint16(a[2] + kyberQ - b[2])
p.coeffs[4*i+3] = uint16(a[3] + kyberQ - b[3])
}
case 4:
var a, b [4]uint32
for i := 0; i < kyberN/4; i++ {
t := loadLittleEndian(buf[4*i:], 4)
var d uint32
for j := 0; j < 4; j++ {
d += uint32((t >> uint(j)) & 0x11111111)
}
a[0] = d & 0xf
b[0] = (d >> 4) & 0xf
a[1] = (d >> 8) & 0xf
b[1] = (d >> 12) & 0xf
a[2] = (d >> 16) & 0xf
b[2] = (d >> 20) & 0xf
a[3] = (d >> 24) & 0xf
b[3] = (d >> 28)
p.coeffs[4*i+0] = uint16(a[0] + kyberQ - b[0])
p.coeffs[4*i+1] = uint16(a[1] + kyberQ - b[1])
p.coeffs[4*i+2] = uint16(a[2] + kyberQ - b[2])
p.coeffs[4*i+3] = uint16(a[3] + kyberQ - b[3])
}
case 5:
var a, b [4]uint64
for i := 0; i < kyberN/4; i++ {
t := loadLittleEndian(buf[5*i:], 5)
var d uint64
for j := 0; j < 5; j++ {
d += (t >> uint(j)) & 0x0842108421
}
a[0] = d & 0x1f
b[0] = (d >> 5) & 0x1f
a[1] = (d >> 10) & 0x1f
b[1] = (d >> 15) & 0x1f
a[2] = (d >> 20) & 0x1f
b[2] = (d >> 25) & 0x1f
a[3] = (d >> 30) & 0x1f
b[3] = (d >> 35)
p.coeffs[4*i+0] = uint16(a[0] + kyberQ - b[0])
p.coeffs[4*i+1] = uint16(a[1] + kyberQ - b[1])
p.coeffs[4*i+2] = uint16(a[2] + kyberQ - b[2])
p.coeffs[4*i+3] = uint16(a[3] + kyberQ - b[3])
}
default:
panic("kyber: eta must be in {3,4,5}")
}
}