Skip to content

Commit

Permalink
[WIP] Add ML-DSA (FIPS204)
Browse files Browse the repository at this point in the history
The final version of FIPS204 has not been released, thus this
implementation is not yet final.
  • Loading branch information
bwesterb committed Feb 15, 2024
1 parent 2a2b195 commit 4fe82b4
Show file tree
Hide file tree
Showing 142 changed files with 7,883 additions and 269 deletions.
2 changes: 1 addition & 1 deletion sign/dilithium/example_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,6 @@ func Example() {
fmt.Printf("O.K.")

// Output:
// Supported modes: [Dilithium2 Dilithium2-AES Dilithium3 Dilithium3-AES Dilithium5 Dilithium5-AES]
// Supported modes: [Dilithium2 Dilithium2-AES Dilithium3 Dilithium3-AES Dilithium5 Dilithium5-AES ML-DSA-44 ML-DSA-65 ML-DSA-87]
// O.K.
}
92 changes: 79 additions & 13 deletions sign/dilithium/gen.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,12 +14,11 @@ import (
"strings"
"text/template"

"github.com/cloudflare/circl/sign/dilithium/internal/common/params"
"github.com/cloudflare/circl/sign/internal/dilithium/params"
)

type Mode struct {
Name string
UseAES bool
K int
L int
Eta int
Expand All @@ -28,26 +27,47 @@ type Mode struct {
Tau int
Gamma1Bits int
Gamma2 int
TRSize int
CTildeSize int
}

func (m Mode) Pkg() string {
return strings.ToLower(m.Mode())
}

func (m Mode) PkgPath() string {
if m.NIST() {
return path.Join("..", "mldsa", m.Pkg())
}

return m.Pkg()
}

func (m Mode) Impl() string {
return "impl" + m.Mode()
}

func (m Mode) Mode() string {
if m.NIST() {
return strings.ReplaceAll(m.Name, "-", "")
}

return strings.ReplaceAll(strings.ReplaceAll(m.Name,
"Dilithium", "Mode"), "-AES", "AES")
}

func (m Mode) UseAES() bool {
return strings.HasSuffix(m.Name, "-AES")
}

func (m Mode) NIST() bool {
return strings.HasPrefix(m.Name, "ML-DSA-")
}

var (
Modes = []Mode{
{
Name: "Dilithium2",
UseAES: false,
K: 4,
L: 4,
Eta: 2,
Expand All @@ -56,10 +76,11 @@ var (
Tau: 39,
Gamma1Bits: 17,
Gamma2: (params.Q - 1) / 88,
TRSize: 32,
CTildeSize: 32,
},
{
Name: "Dilithium2-AES",
UseAES: true,
K: 4,
L: 4,
Eta: 2,
Expand All @@ -68,10 +89,11 @@ var (
Tau: 39,
Gamma1Bits: 17,
Gamma2: (params.Q - 1) / 88,
TRSize: 32,
CTildeSize: 32,
},
{
Name: "Dilithium3",
UseAES: false,
K: 6,
L: 5,
Eta: 4,
Expand All @@ -80,10 +102,11 @@ var (
Tau: 49,
Gamma1Bits: 19,
Gamma2: (params.Q - 1) / 32,
TRSize: 32,
CTildeSize: 32,
},
{
Name: "Dilithium3-AES",
UseAES: true,
K: 6,
L: 5,
Eta: 4,
Expand All @@ -92,10 +115,11 @@ var (
Tau: 49,
Gamma1Bits: 19,
Gamma2: (params.Q - 1) / 32,
TRSize: 32,
CTildeSize: 32,
},
{
Name: "Dilithium5",
UseAES: false,
K: 8,
L: 7,
Eta: 2,
Expand All @@ -104,10 +128,11 @@ var (
Tau: 60,
Gamma1Bits: 19,
Gamma2: (params.Q - 1) / 32,
TRSize: 32,
CTildeSize: 32,
},
{
Name: "Dilithium5-AES",
UseAES: true,
K: 8,
L: 7,
Eta: 2,
Expand All @@ -116,6 +141,47 @@ var (
Tau: 60,
Gamma1Bits: 19,
Gamma2: (params.Q - 1) / 32,
TRSize: 32,
CTildeSize: 32,
},
{
Name: "ML-DSA-44",
K: 4,
L: 4,
Eta: 2,
DoubleEtaBits: 3,
Omega: 80,
Tau: 39,
Gamma1Bits: 17,
Gamma2: (params.Q - 1) / 88,
TRSize: 64,
CTildeSize: 32,
},
{
Name: "ML-DSA-65",
K: 6,
L: 5,
Eta: 4,
DoubleEtaBits: 4,
Omega: 55,
Tau: 49,
Gamma1Bits: 19,
Gamma2: (params.Q - 1) / 32,
TRSize: 64,
CTildeSize: 48,
},
{
Name: "ML-DSA-87",
K: 8,
L: 7,
Eta: 2,
DoubleEtaBits: 3,
Omega: 75,
Tau: 60,
Gamma1Bits: 19,
Gamma2: (params.Q - 1) / 32,
TRSize: 64,
CTildeSize: 64,
},
}
TemplateWarning = "// Code generated from"
Expand Down Expand Up @@ -153,7 +219,7 @@ func generateParamsFiles() {
if offset == -1 {
panic("Missing template warning in params.templ.go")
}
err = os.WriteFile(mode.Pkg()+"/internal/params.go",
err = os.WriteFile(mode.PkgPath()+"/internal/params.go",
[]byte(res[offset:]), 0o644)
if err != nil {
panic(err)
Expand Down Expand Up @@ -206,7 +272,7 @@ func generateModePackageFiles() {
if offset == -1 {
panic("Missing template warning in modePkg.templ.go")
}
err = os.WriteFile(mode.Pkg()+"/dilithium.go", []byte(res[offset:]), 0o644)
err = os.WriteFile(mode.PkgPath()+"/dilithium.go", []byte(res[offset:]), 0o644)
if err != nil {
panic(err)
}
Expand Down Expand Up @@ -246,10 +312,10 @@ func generateSourceFiles() {
continue
}

fs, err = os.ReadDir(path.Join(mode.Pkg(), "internal"))
fs, err = os.ReadDir(path.Join(mode.PkgPath(), "internal"))
for _, f := range fs {
name := f.Name()
fn := path.Join(mode.Pkg(), "internal", name)
fn := path.Join(mode.PkgPath(), "internal", name)
if ignored(name) {
continue
}
Expand All @@ -273,7 +339,7 @@ func generateSourceFiles() {
}
}
for name, expected := range files {
fn := path.Join(mode.Pkg(), "internal", name)
fn := path.Join(mode.PkgPath(), "internal", name)
expected = []byte(fmt.Sprintf(
"%s mode3/internal/%s by gen.go\n\n%s",
TemplateWarning,
Expand Down
25 changes: 22 additions & 3 deletions sign/dilithium/kat_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,24 +6,32 @@ package dilithium
import (
"crypto/sha256"
"fmt"
"strings"
"testing"

"github.com/cloudflare/circl/internal/nist"
)

func TestPQCgenKATSign(t *testing.T) {
// Generated from reference implementation commit 61b51a71701b8ae9f546a1e5,
// which can be found at https://github.com/pq-crystals/dilithium
for _, tc := range []struct {
name string
want string
}{
// Generated from reference implementation commit 61b51a71701b8ae9f546a1e5,
// which can be found at https://github.com/pq-crystals/dilithium
{"Dilithium2", "38ed991c5ca11e39ab23945ca37af89e059d16c5474bf8ba96b15cb4e948af2a"},
{"Dilithium3", "8196b32212753f525346201ffec1c7a0a852596fa0b57bd4e2746231dab44d55"},
{"Dilithium5", "7ded97a6e6c809b43b54c248171d7504fa6a0cab651bf288bb00034782667481"},
{"Dilithium2-AES", "b6673f8da5bba7dfae63adbbdf559f4fcfb715d1f91da98d4b52e26203d69196"},
{"Dilithium3-AES", "482f4d672a9f1dc38cc8bcf8b1731b03fe99fcb6f2b73aa4a376b99faf89ccbe"},
{"Dilithium5-AES", "54dfa85013d1b3da4f1d7c6dd270bc91a083cfece3d320c97906da125fd2a48f"},

// Generated from reference implementation commit e7bed6258b9a3703ce78d4ec3,
// which can be found on the standard branch
// of https://github.com/pq-crystals/dilithium
{"ML-DSA-44", "4657f244d1204e5847b3cacea4fc6116579571bee8ac89b8cba6771f303ee260"},
{"ML-DSA-65", "99a95d7ef804020a666f455c5003232d0c0200dfc4f5df85dceb8f56256dcba8"},
{"ML-DSA-87", "3377835fffb7cf9aac52947225c8974335bc05532ddf672a8b706ab8991435a2"},
} {
t.Run(tc.name, func(t *testing.T) {
mode := ModeByName(tc.name)
Expand All @@ -38,7 +46,18 @@ func TestPQCgenKATSign(t *testing.T) {
}
f := sha256.New()
g := nist.NewDRBG(&seed)
fmt.Fprintf(f, "# %s\n\n", tc.name)
nameInKat := tc.name
if !strings.HasPrefix(tc.name, "Dilithium") {
switch tc.name {
case "ML-DSA-44":
nameInKat = "Dilithium2"
case "ML-DSA-65":
nameInKat = "Dilithium3"
case "ML-DSA-87":
nameInKat = "Dilithium5"
}
}
fmt.Fprintf(f, "# %s\n\n", nameInKat)
for i := 0; i < 100; i++ {
mlen := 33 * (i + 1)
g.Fill(seed[:])
Expand Down
91 changes: 91 additions & 0 deletions sign/dilithium/mldsa44.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading

0 comments on commit 4fe82b4

Please sign in to comment.