diff options
| author | Daniel McCarney <daniel@binaryparadox.net> | 2024-11-21 17:52:50 -0500 |
|---|---|---|
| committer | Gopher Robot <gobot@golang.org> | 2024-11-22 03:09:37 +0000 |
| commit | 9aaef91d3e75994f19d33a4fcee08b5225432af6 (patch) | |
| tree | 9733e9e9454e8a900fbff490340f7e76c0ffa732 /src/crypto/internal | |
| parent | b2f7a2154a36c6dd7d20c53205aab6348228618f (diff) | |
| download | go-9aaef91d3e75994f19d33a4fcee08b5225432af6.tar.xz | |
crypto/mlkem: init package
This commit exposes the crypto/internal/mlkem package as a public crypto
package based on the linked proposal. Since we've already implemented
this internal to the FIPS boundary this largely defers to that
implementation.
Updates #70122
Change-Id: I5ec9c2783c4d44583244c6d16597704a51e9b738
Reviewed-on: https://go-review.googlesource.com/c/go/+/630240
Reviewed-by: Filippo Valsorda <filippo@golang.org>
Reviewed-by: Roland Shoemaker <roland@golang.org>
Auto-Submit: Filippo Valsorda <filippo@golang.org>
LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com>
Reviewed-by: Dmitri Shuralyov <dmitshur@google.com>
Diffstat (limited to 'src/crypto/internal')
| -rw-r--r-- | src/crypto/internal/fips140test/mlkem_test.go | 309 |
1 files changed, 0 insertions, 309 deletions
diff --git a/src/crypto/internal/fips140test/mlkem_test.go b/src/crypto/internal/fips140test/mlkem_test.go deleted file mode 100644 index 43467456f0..0000000000 --- a/src/crypto/internal/fips140test/mlkem_test.go +++ /dev/null @@ -1,309 +0,0 @@ -// Copyright 2023 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. - -package fipstest_test - -// TODO(fips, #70122): move this to crypto/mlkem once it exists. - -import ( - "bytes" - . "crypto/internal/fips140/mlkem" - "crypto/internal/fips140/sha3" - "crypto/rand" - _ "embed" - "encoding/hex" - "flag" - "testing" -) - -type encapsulationKey interface { - Bytes() []byte - Encapsulate() ([]byte, []byte) -} - -type decapsulationKey[E encapsulationKey] interface { - Bytes() []byte - Decapsulate([]byte) ([]byte, error) - EncapsulationKey() E -} - -func TestRoundTrip(t *testing.T) { - t.Run("768", func(t *testing.T) { - testRoundTrip(t, GenerateKey768, NewEncapsulationKey768, NewDecapsulationKey768) - }) - t.Run("1024", func(t *testing.T) { - testRoundTrip(t, GenerateKey1024, NewEncapsulationKey1024, NewDecapsulationKey1024) - }) -} - -func testRoundTrip[E encapsulationKey, D decapsulationKey[E]]( - t *testing.T, generateKey func() (D, error), - newEncapsulationKey func([]byte) (E, error), - newDecapsulationKey func([]byte) (D, error)) { - dk, err := generateKey() - if err != nil { - t.Fatal(err) - } - ek := dk.EncapsulationKey() - c, Ke := ek.Encapsulate() - Kd, err := dk.Decapsulate(c) - if err != nil { - t.Fatal(err) - } - if !bytes.Equal(Ke, Kd) { - t.Fail() - } - - ek1, err := newEncapsulationKey(ek.Bytes()) - if err != nil { - t.Fatal(err) - } - if !bytes.Equal(ek.Bytes(), ek1.Bytes()) { - t.Fail() - } - dk1, err := newDecapsulationKey(dk.Bytes()) - if err != nil { - t.Fatal(err) - } - if !bytes.Equal(dk.Bytes(), dk1.Bytes()) { - t.Fail() - } - c1, Ke1 := ek1.Encapsulate() - Kd1, err := dk1.Decapsulate(c1) - if err != nil { - t.Fatal(err) - } - if !bytes.Equal(Ke1, Kd1) { - t.Fail() - } - - dk2, err := generateKey() - if err != nil { - t.Fatal(err) - } - if bytes.Equal(dk.EncapsulationKey().Bytes(), dk2.EncapsulationKey().Bytes()) { - t.Fail() - } - if bytes.Equal(dk.Bytes(), dk2.Bytes()) { - t.Fail() - } - - c2, Ke2 := dk.EncapsulationKey().Encapsulate() - if bytes.Equal(c, c2) { - t.Fail() - } - if bytes.Equal(Ke, Ke2) { - t.Fail() - } -} - -func TestBadLengths(t *testing.T) { - t.Run("768", func(t *testing.T) { - testBadLengths(t, GenerateKey768, NewEncapsulationKey768, NewDecapsulationKey768) - }) - t.Run("1024", func(t *testing.T) { - testBadLengths(t, GenerateKey1024, NewEncapsulationKey1024, NewDecapsulationKey1024) - }) -} - -func testBadLengths[E encapsulationKey, D decapsulationKey[E]]( - t *testing.T, generateKey func() (D, error), - newEncapsulationKey func([]byte) (E, error), - newDecapsulationKey func([]byte) (D, error)) { - dk, err := generateKey() - dkBytes := dk.Bytes() - if err != nil { - t.Fatal(err) - } - ek := dk.EncapsulationKey() - ekBytes := dk.EncapsulationKey().Bytes() - c, _ := ek.Encapsulate() - - for i := 0; i < len(dkBytes)-1; i++ { - if _, err := newDecapsulationKey(dkBytes[:i]); err == nil { - t.Errorf("expected error for dk length %d", i) - } - } - dkLong := dkBytes - for i := 0; i < 100; i++ { - dkLong = append(dkLong, 0) - if _, err := newDecapsulationKey(dkLong); err == nil { - t.Errorf("expected error for dk length %d", len(dkLong)) - } - } - - for i := 0; i < len(ekBytes)-1; i++ { - if _, err := newEncapsulationKey(ekBytes[:i]); err == nil { - t.Errorf("expected error for ek length %d", i) - } - } - ekLong := ekBytes - for i := 0; i < 100; i++ { - ekLong = append(ekLong, 0) - if _, err := newEncapsulationKey(ekLong); err == nil { - t.Errorf("expected error for ek length %d", len(ekLong)) - } - } - - for i := 0; i < len(c)-1; i++ { - if _, err := dk.Decapsulate(c[:i]); err == nil { - t.Errorf("expected error for c length %d", i) - } - } - cLong := c - for i := 0; i < 100; i++ { - cLong = append(cLong, 0) - if _, err := dk.Decapsulate(cLong); err == nil { - t.Errorf("expected error for c length %d", len(cLong)) - } - } -} - -var millionFlag = flag.Bool("million", false, "run the million vector test") - -// TestAccumulated accumulates 10k (or 100, or 1M) random vectors and checks the -// hash of the result, to avoid checking in 150MB of test vectors. -func TestAccumulated(t *testing.T) { - n := 10000 - expected := "8a518cc63da366322a8e7a818c7a0d63483cb3528d34a4cf42f35d5ad73f22fc" - if testing.Short() { - n = 100 - expected = "1114b1b6699ed191734fa339376afa7e285c9e6acf6ff0177d346696ce564415" - } - if *millionFlag { - n = 1000000 - expected = "424bf8f0e8ae99b78d788a6e2e8e9cdaf9773fc0c08a6f433507cb559edfd0f0" - } - - s := sha3.NewShake128() - o := sha3.NewShake128() - seed := make([]byte, SeedSize) - var msg [32]byte - ct1 := make([]byte, CiphertextSize768) - - for i := 0; i < n; i++ { - s.Read(seed) - dk, err := NewDecapsulationKey768(seed) - if err != nil { - t.Fatal(err) - } - ek := dk.EncapsulationKey() - o.Write(ek.Bytes()) - - s.Read(msg[:]) - ct, k := ek.EncapsulateInternal(&msg) - o.Write(ct) - o.Write(k) - - kk, err := dk.Decapsulate(ct) - if err != nil { - t.Fatal(err) - } - if !bytes.Equal(kk, k) { - t.Errorf("k: got %x, expected %x", kk, k) - } - - s.Read(ct1) - k1, err := dk.Decapsulate(ct1) - if err != nil { - t.Fatal(err) - } - o.Write(k1) - } - - got := hex.EncodeToString(o.Sum(nil)) - if got != expected { - t.Errorf("got %s, expected %s", got, expected) - } -} - -var sink byte - -func BenchmarkKeyGen(b *testing.B) { - var d, z [32]byte - rand.Read(d[:]) - rand.Read(z[:]) - b.ResetTimer() - for i := 0; i < b.N; i++ { - dk := GenerateKeyInternal768(&d, &z) - sink ^= dk.EncapsulationKey().Bytes()[0] - } -} - -func BenchmarkEncaps(b *testing.B) { - seed := make([]byte, SeedSize) - rand.Read(seed) - var m [32]byte - rand.Read(m[:]) - dk, err := NewDecapsulationKey768(seed) - if err != nil { - b.Fatal(err) - } - ekBytes := dk.EncapsulationKey().Bytes() - b.ResetTimer() - for i := 0; i < b.N; i++ { - ek, err := NewEncapsulationKey768(ekBytes) - if err != nil { - b.Fatal(err) - } - c, K := ek.EncapsulateInternal(&m) - sink ^= c[0] ^ K[0] - } -} - -func BenchmarkDecaps(b *testing.B) { - dk, err := GenerateKey768() - if err != nil { - b.Fatal(err) - } - ek := dk.EncapsulationKey() - c, _ := ek.Encapsulate() - b.ResetTimer() - for i := 0; i < b.N; i++ { - K, _ := dk.Decapsulate(c) - sink ^= K[0] - } -} - -func BenchmarkRoundTrip(b *testing.B) { - dk, err := GenerateKey768() - if err != nil { - b.Fatal(err) - } - ek := dk.EncapsulationKey() - ekBytes := ek.Bytes() - c, _ := ek.Encapsulate() - if err != nil { - b.Fatal(err) - } - b.Run("Alice", func(b *testing.B) { - for i := 0; i < b.N; i++ { - dkS, err := GenerateKey768() - if err != nil { - b.Fatal(err) - } - ekS := dkS.EncapsulationKey().Bytes() - sink ^= ekS[0] - - Ks, err := dk.Decapsulate(c) - if err != nil { - b.Fatal(err) - } - sink ^= Ks[0] - } - }) - b.Run("Bob", func(b *testing.B) { - for i := 0; i < b.N; i++ { - ek, err := NewEncapsulationKey768(ekBytes) - if err != nil { - b.Fatal(err) - } - cS, Ks := ek.Encapsulate() - if err != nil { - b.Fatal(err) - } - sink ^= cS[0] ^ Ks[0] - } - }) -} |
