Initial project import
This commit is contained in:
commit
23f2d29e32
11957 files changed
+1754577
No files matched your search
@@ -0,0 +1,146 @@
|
||||
// Copyright 2025 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
//
|
||||
// Ported to V from Go's crypto/internal/fips140/mldsa.
|
||||
module mldsa
|
||||
|
||||
import crypto.sha3
|
||||
|
||||
// algo. 30: RejNTTPoly (s. 7.3)
|
||||
@[direct_array_access]
|
||||
fn sample_ntt(rho []u8, s u8, r u8) NttElement {
|
||||
mut g := sha3.new_shake128()
|
||||
g.write(rho)
|
||||
g.write([s, r])
|
||||
|
||||
mut a := NttElement{}
|
||||
mut j := 0
|
||||
mut buf := g.read(168)
|
||||
mut off := 0
|
||||
for j < n {
|
||||
if off + 2 >= buf.len {
|
||||
buf = g.read(168)
|
||||
off = 0
|
||||
}
|
||||
v := u32(buf[off]) | (u32(buf[off + 1]) << 8) | (u32(buf[off + 2]) << 16)
|
||||
off += 3
|
||||
candidate := v & 0x7fffff
|
||||
if candidate < q {
|
||||
a[j] = field_to_montgomery(candidate) or { continue }
|
||||
j++
|
||||
}
|
||||
}
|
||||
return a
|
||||
}
|
||||
|
||||
// algo. 31: RejBoundedPoly (s. 7.3)
|
||||
@[direct_array_access]
|
||||
fn sample_bounded_poly(rho []u8, r u8, p Params) RingElement {
|
||||
mut h := sha3.new_shake256()
|
||||
h.write(rho)
|
||||
h.write([r, 0])
|
||||
|
||||
mut a := RingElement{}
|
||||
mut j := 0
|
||||
mut buf := h.read(136)
|
||||
mut off := 0
|
||||
for {
|
||||
if off >= buf.len {
|
||||
buf = h.read(136)
|
||||
off = 0
|
||||
}
|
||||
z0 := buf[off] & 0x0f
|
||||
z1 := buf[off] >> 4
|
||||
off++
|
||||
|
||||
coeff, ok := coeff_from_half_byte(z0, p)
|
||||
if ok {
|
||||
a[j] = coeff
|
||||
j++
|
||||
}
|
||||
if j >= n {
|
||||
break
|
||||
}
|
||||
|
||||
coeff2, ok2 := coeff_from_half_byte(z1, p)
|
||||
if ok2 {
|
||||
a[j] = coeff2
|
||||
j++
|
||||
}
|
||||
if j >= n {
|
||||
break
|
||||
}
|
||||
}
|
||||
return a
|
||||
}
|
||||
|
||||
// algo. 29: SampleInBall (s. 7.3)
|
||||
@[direct_array_access]
|
||||
fn sample_in_ball(rho []u8, p Params) RingElement {
|
||||
mut h := sha3.new_shake256()
|
||||
h.write(rho)
|
||||
s := h.read(8)
|
||||
|
||||
// pre-read ~2x expected bytes to avoid per-byte allocations
|
||||
mut buf := h.read(p.tau * 2)
|
||||
mut off := 0
|
||||
|
||||
mut c := RingElement{}
|
||||
for i := 256 - p.tau; i < 256; i++ {
|
||||
for {
|
||||
if off >= buf.len {
|
||||
buf = h.read(256)
|
||||
off = 0
|
||||
}
|
||||
j := buf[off]
|
||||
off++
|
||||
if j <= u8(i) {
|
||||
c[i] = c[j]
|
||||
bit_idx := i + p.tau - 256
|
||||
bit := (s[bit_idx / 8] >> (bit_idx % 8)) & 1
|
||||
if bit == 0 {
|
||||
c[j] = mont_one
|
||||
} else {
|
||||
c[j] = mont_minus_one
|
||||
}
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
return c
|
||||
}
|
||||
|
||||
// algo. 15: CoeffFromHalfByte (s. 7.1)
|
||||
fn coeff_from_half_byte(b u8, p Params) (FieldElement, bool) {
|
||||
match p.eta {
|
||||
2 {
|
||||
if b > 14 {
|
||||
return FieldElement(0), false
|
||||
}
|
||||
quotient := (u32(b) * 0x3334) >> 16 // barrett b % 5
|
||||
remainder := u32(b) - quotient * 5
|
||||
return field_sub_to_montgomery(2, remainder), true
|
||||
}
|
||||
4 {
|
||||
if b > 8 {
|
||||
return FieldElement(0), false
|
||||
}
|
||||
return field_sub_to_montgomery(4, u32(b)), true
|
||||
}
|
||||
else {
|
||||
panic('mldsa: unsupported eta') // unreachable
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// algo. 32: ExpandA (s. 7.3)
|
||||
fn compute_matrix_a(rho []u8, p Params) []NttElement {
|
||||
mut a := []NttElement{len: p.k * p.l}
|
||||
for r in 0 .. p.k {
|
||||
for s in 0 .. p.l {
|
||||
a[r * p.l + s] = sample_ntt(rho, u8(s), u8(r))
|
||||
}
|
||||
}
|
||||
return a
|
||||
}
|
||||
Reference in new issue
Block a user