Skip to content

Commit 47bb92a

Browse files
committed
[WIP] Add ML-DSA (FIPS204)
The final version of FIPS204 has not been released, thus this implementation is not yet final.
1 parent 2a2b195 commit 47bb92a

File tree

148 files changed

+7890
-274
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

148 files changed

+7890
-274
lines changed

sign/dilithium/example_test.go

+1-1
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,6 @@ func Example() {
5151
fmt.Printf("O.K.")
5252

5353
// Output:
54-
// Supported modes: [Dilithium2 Dilithium2-AES Dilithium3 Dilithium3-AES Dilithium5 Dilithium5-AES]
54+
// Supported modes: [Dilithium2 Dilithium2-AES Dilithium3 Dilithium3-AES Dilithium5 Dilithium5-AES ML-DSA-44 ML-DSA-65 ML-DSA-87]
5555
// O.K.
5656
}

sign/dilithium/gen.go

+79-13
Original file line numberDiff line numberDiff line change
@@ -14,12 +14,11 @@ import (
1414
"strings"
1515
"text/template"
1616

17-
"github.com/cloudflare/circl/sign/dilithium/internal/common/params"
17+
"github.com/cloudflare/circl/sign/internal/dilithium/params"
1818
)
1919

2020
type Mode struct {
2121
Name string
22-
UseAES bool
2322
K int
2423
L int
2524
Eta int
@@ -28,26 +27,47 @@ type Mode struct {
2827
Tau int
2928
Gamma1Bits int
3029
Gamma2 int
30+
TRSize int
31+
CTildeSize int
3132
}
3233

3334
func (m Mode) Pkg() string {
3435
return strings.ToLower(m.Mode())
3536
}
3637

38+
func (m Mode) PkgPath() string {
39+
if m.NIST() {
40+
return path.Join("..", "mldsa", m.Pkg())
41+
}
42+
43+
return m.Pkg()
44+
}
45+
3746
func (m Mode) Impl() string {
3847
return "impl" + m.Mode()
3948
}
4049

4150
func (m Mode) Mode() string {
51+
if m.NIST() {
52+
return strings.ReplaceAll(m.Name, "-", "")
53+
}
54+
4255
return strings.ReplaceAll(strings.ReplaceAll(m.Name,
4356
"Dilithium", "Mode"), "-AES", "AES")
4457
}
4558

59+
func (m Mode) UseAES() bool {
60+
return strings.HasSuffix(m.Name, "-AES")
61+
}
62+
63+
func (m Mode) NIST() bool {
64+
return strings.HasPrefix(m.Name, "ML-DSA-")
65+
}
66+
4667
var (
4768
Modes = []Mode{
4869
{
4970
Name: "Dilithium2",
50-
UseAES: false,
5171
K: 4,
5272
L: 4,
5373
Eta: 2,
@@ -56,10 +76,11 @@ var (
5676
Tau: 39,
5777
Gamma1Bits: 17,
5878
Gamma2: (params.Q - 1) / 88,
79+
TRSize: 32,
80+
CTildeSize: 32,
5981
},
6082
{
6183
Name: "Dilithium2-AES",
62-
UseAES: true,
6384
K: 4,
6485
L: 4,
6586
Eta: 2,
@@ -68,10 +89,11 @@ var (
6889
Tau: 39,
6990
Gamma1Bits: 17,
7091
Gamma2: (params.Q - 1) / 88,
92+
TRSize: 32,
93+
CTildeSize: 32,
7194
},
7295
{
7396
Name: "Dilithium3",
74-
UseAES: false,
7597
K: 6,
7698
L: 5,
7799
Eta: 4,
@@ -80,10 +102,11 @@ var (
80102
Tau: 49,
81103
Gamma1Bits: 19,
82104
Gamma2: (params.Q - 1) / 32,
105+
TRSize: 32,
106+
CTildeSize: 32,
83107
},
84108
{
85109
Name: "Dilithium3-AES",
86-
UseAES: true,
87110
K: 6,
88111
L: 5,
89112
Eta: 4,
@@ -92,10 +115,11 @@ var (
92115
Tau: 49,
93116
Gamma1Bits: 19,
94117
Gamma2: (params.Q - 1) / 32,
118+
TRSize: 32,
119+
CTildeSize: 32,
95120
},
96121
{
97122
Name: "Dilithium5",
98-
UseAES: false,
99123
K: 8,
100124
L: 7,
101125
Eta: 2,
@@ -104,10 +128,11 @@ var (
104128
Tau: 60,
105129
Gamma1Bits: 19,
106130
Gamma2: (params.Q - 1) / 32,
131+
TRSize: 32,
132+
CTildeSize: 32,
107133
},
108134
{
109135
Name: "Dilithium5-AES",
110-
UseAES: true,
111136
K: 8,
112137
L: 7,
113138
Eta: 2,
@@ -116,6 +141,47 @@ var (
116141
Tau: 60,
117142
Gamma1Bits: 19,
118143
Gamma2: (params.Q - 1) / 32,
144+
TRSize: 32,
145+
CTildeSize: 32,
146+
},
147+
{
148+
Name: "ML-DSA-44",
149+
K: 4,
150+
L: 4,
151+
Eta: 2,
152+
DoubleEtaBits: 3,
153+
Omega: 80,
154+
Tau: 39,
155+
Gamma1Bits: 17,
156+
Gamma2: (params.Q - 1) / 88,
157+
TRSize: 64,
158+
CTildeSize: 32,
159+
},
160+
{
161+
Name: "ML-DSA-65",
162+
K: 6,
163+
L: 5,
164+
Eta: 4,
165+
DoubleEtaBits: 4,
166+
Omega: 55,
167+
Tau: 49,
168+
Gamma1Bits: 19,
169+
Gamma2: (params.Q - 1) / 32,
170+
TRSize: 64,
171+
CTildeSize: 48,
172+
},
173+
{
174+
Name: "ML-DSA-87",
175+
K: 8,
176+
L: 7,
177+
Eta: 2,
178+
DoubleEtaBits: 3,
179+
Omega: 75,
180+
Tau: 60,
181+
Gamma1Bits: 19,
182+
Gamma2: (params.Q - 1) / 32,
183+
TRSize: 64,
184+
CTildeSize: 64,
119185
},
120186
}
121187
TemplateWarning = "// Code generated from"
@@ -153,7 +219,7 @@ func generateParamsFiles() {
153219
if offset == -1 {
154220
panic("Missing template warning in params.templ.go")
155221
}
156-
err = os.WriteFile(mode.Pkg()+"/internal/params.go",
222+
err = os.WriteFile(mode.PkgPath()+"/internal/params.go",
157223
[]byte(res[offset:]), 0o644)
158224
if err != nil {
159225
panic(err)
@@ -206,7 +272,7 @@ func generateModePackageFiles() {
206272
if offset == -1 {
207273
panic("Missing template warning in modePkg.templ.go")
208274
}
209-
err = os.WriteFile(mode.Pkg()+"/dilithium.go", []byte(res[offset:]), 0o644)
275+
err = os.WriteFile(mode.PkgPath()+"/dilithium.go", []byte(res[offset:]), 0o644)
210276
if err != nil {
211277
panic(err)
212278
}
@@ -246,10 +312,10 @@ func generateSourceFiles() {
246312
continue
247313
}
248314

249-
fs, err = os.ReadDir(path.Join(mode.Pkg(), "internal"))
315+
fs, err = os.ReadDir(path.Join(mode.PkgPath(), "internal"))
250316
for _, f := range fs {
251317
name := f.Name()
252-
fn := path.Join(mode.Pkg(), "internal", name)
318+
fn := path.Join(mode.PkgPath(), "internal", name)
253319
if ignored(name) {
254320
continue
255321
}
@@ -273,7 +339,7 @@ func generateSourceFiles() {
273339
}
274340
}
275341
for name, expected := range files {
276-
fn := path.Join(mode.Pkg(), "internal", name)
342+
fn := path.Join(mode.PkgPath(), "internal", name)
277343
expected = []byte(fmt.Sprintf(
278344
"%s mode3/internal/%s by gen.go\n\n%s",
279345
TemplateWarning,

sign/dilithium/kat_test.go

+22-3
Original file line numberDiff line numberDiff line change
@@ -6,24 +6,32 @@ package dilithium
66
import (
77
"crypto/sha256"
88
"fmt"
9+
"strings"
910
"testing"
1011

1112
"github.com/cloudflare/circl/internal/nist"
1213
)
1314

1415
func TestPQCgenKATSign(t *testing.T) {
15-
// Generated from reference implementation commit 61b51a71701b8ae9f546a1e5,
16-
// which can be found at https://github.com/pq-crystals/dilithium
1716
for _, tc := range []struct {
1817
name string
1918
want string
2019
}{
20+
// Generated from reference implementation commit 61b51a71701b8ae9f546a1e5,
21+
// which can be found at https://github.com/pq-crystals/dilithium
2122
{"Dilithium2", "38ed991c5ca11e39ab23945ca37af89e059d16c5474bf8ba96b15cb4e948af2a"},
2223
{"Dilithium3", "8196b32212753f525346201ffec1c7a0a852596fa0b57bd4e2746231dab44d55"},
2324
{"Dilithium5", "7ded97a6e6c809b43b54c248171d7504fa6a0cab651bf288bb00034782667481"},
2425
{"Dilithium2-AES", "b6673f8da5bba7dfae63adbbdf559f4fcfb715d1f91da98d4b52e26203d69196"},
2526
{"Dilithium3-AES", "482f4d672a9f1dc38cc8bcf8b1731b03fe99fcb6f2b73aa4a376b99faf89ccbe"},
2627
{"Dilithium5-AES", "54dfa85013d1b3da4f1d7c6dd270bc91a083cfece3d320c97906da125fd2a48f"},
28+
29+
// Generated from reference implementation commit e7bed6258b9a3703ce78d4ec3,
30+
// which can be found on the standard branch
31+
// of https://github.com/pq-crystals/dilithium
32+
{"ML-DSA-44", "4657f244d1204e5847b3cacea4fc6116579571bee8ac89b8cba6771f303ee260"},
33+
{"ML-DSA-65", "99a95d7ef804020a666f455c5003232d0c0200dfc4f5df85dceb8f56256dcba8"},
34+
{"ML-DSA-87", "3377835fffb7cf9aac52947225c8974335bc05532ddf672a8b706ab8991435a2"},
2735
} {
2836
t.Run(tc.name, func(t *testing.T) {
2937
mode := ModeByName(tc.name)
@@ -38,7 +46,18 @@ func TestPQCgenKATSign(t *testing.T) {
3846
}
3947
f := sha256.New()
4048
g := nist.NewDRBG(&seed)
41-
fmt.Fprintf(f, "# %s\n\n", tc.name)
49+
nameInKat := tc.name
50+
if !strings.HasPrefix(tc.name, "Dilithium") {
51+
switch tc.name {
52+
case "ML-DSA-44":
53+
nameInKat = "Dilithium2"
54+
case "ML-DSA-65":
55+
nameInKat = "Dilithium3"
56+
case "ML-DSA-87":
57+
nameInKat = "Dilithium5"
58+
}
59+
}
60+
fmt.Fprintf(f, "# %s\n\n", nameInKat)
4261
for i := 0; i < 100; i++ {
4362
mlen := 33 * (i + 1)
4463
g.Fill(seed[:])

sign/dilithium/mldsa44.go

+91
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)