Commit 3bfb67f
committed
ML-KEM: add modulus overflow test vectors from CCTV
Generator, for posterity.
package main
import (
"flag"
"fmt"
"math/rand"
)
const (
n = 256
q = 3329
encodingSize12 = n * 12 / 8
)
var shortFlag = flag.Bool("short", false, "generate the short subset")
var kFlag = flag.Int("k", 3, "2 for -512, 3 for -768, 4 for -1024")
var startID = flag.Int("start", 1, "start ID for the first vector")
func main() {
flag.Parse()
for i := 0; i < *kFlag; i++ {
genVector(func(t [][n]uint16) { t[i][0] = q })
genVector(func(t [][n]uint16) { t[i][255] = q })
genVector(func(t [][n]uint16) { t[i][0] = 1<<12 - 1 })
genVector(func(t [][n]uint16) { t[i][255] = 1<<12 - 1 })
}
if !*shortFlag {
var i, j int
var x uint16 = q
var doneValues, donePositions bool
for {
genVector(func(t [][n]uint16) { t[i][j] = x })
x++
if x == 1<<12 {
x = q
doneValues = true
}
j++
if j == n {
j = 0
i++
}
if i == *kFlag {
i = 0
donePositions = true
}
if doneValues && donePositions {
break
}
}
}
}
const template = `{
"tcId": %d,
"flags": [
"ModulusOverflow"
],
"m": "42424242424242424242424242424242424242424242424242424242424242424242424242424242424242424242424242424242424242424242424242424242",
"ek": "%x",
"c": "",
"K": "",
"result": "invalid"
},
`
func genVector(f func([][n]uint16)) {
t := make([][n]uint16, *kFlag)
for i := range t {
t[i] = r[i]
}
f(t)
out := make([]byte, 0)
for i := range t {
out = polyByteEncode(out, t[i])
}
out = append(out, ρ...)
fmt.Printf(template, *startID, out)
*startID++
}
var r = [4][n]uint16{randomPoly(), randomPoly(), randomPoly(), randomPoly()}
var ρ = make([]byte, 32)
func init() { rand.Read(ρ) }
func randomPoly() [n]uint16 {
var f [n]uint16
for i := range f {
f[i] = uint16(rand.Intn(q))
}
return f
}
// polyByteEncode appends the 384-byte encoding of f to b.
//
// It implements ByteEncode₁₂, according to FIPS 203 (DRAFT), Algorithm 4.
func polyByteEncode(b []byte, f [n]uint16) []byte {
out, B := sliceForAppend(b, encodingSize12)
for i := 0; i < n; i += 2 {
x := uint32(f[i]) | uint32(f[i+1])<<12
B[0] = uint8(x)
B[1] = uint8(x >> 8)
B[2] = uint8(x >> 16)
B = B[3:]
}
return out
}
// sliceForAppend takes a slice and a requested number of bytes. It returns a
// slice with the contents of the given slice followed by that many bytes and a
// second slice that aliases into it and contains only the extra bytes. If the
// original slice has sufficient capacity then no allocation is performed.
func sliceForAppend(in []byte, n int) (head, tail []byte) {
if total := len(in) + n; cap(in) >= total {
head = in[:total]
} else {
head = make([]byte, total)
copy(head, in)
}
tail = head[len(in):]
return
}1 parent 8a02741 commit 3bfb67f
1 file changed
+431
-1
lines changed
0 commit comments