package aes
import (
+ "crypto/internal/boring"
"crypto/internal/cryptotest"
"fmt"
"testing"
}
}
+func TestExtraMethods(t *testing.T) {
+ if boring.Enabled {
+ t.Skip("Go+BoringCrypto still uses the interface upgrades in crypto/cipher")
+ }
+ cryptotest.TestAllImplementations(t, "aes", func(t *testing.T) {
+ b, _ := NewCipher(make([]byte, 16))
+ cryptotest.NoExtraMethods(t, &b)
+ })
+}
+
func BenchmarkEncrypt(b *testing.B) {
b.Run("AES-128", func(b *testing.B) { benchmarkEncrypt(b, encryptTests[1]) })
b.Run("AES-192", func(b *testing.B) { benchmarkEncrypt(b, encryptTests[2]) })
})
}
+func TestCBCExtraMethods(t *testing.T) {
+ block, _ := aes.NewCipher(make([]byte, 16))
+ iv := make([]byte, block.BlockSize())
+ s := cipher.NewCBCEncrypter(block, iv)
+ cryptotest.NoExtraMethods(t, &s, "SetIV")
+
+ s = cipher.NewCBCDecrypter(block, iv)
+ cryptotest.NoExtraMethods(t, &s, "SetIV")
+}
+
func newRandReader(t *testing.T) io.Reader {
seed := time.Now().UnixNano()
t.Logf("Deterministic RNG seed: 0x%x", seed)
cryptotest.TestStreamFromBlock(t, block, cipher.NewCTR)
})
}
+
+func TestCTRExtraMethods(t *testing.T) {
+ block, _ := aes.NewCipher(make([]byte, 16))
+ iv := make([]byte, block.BlockSize())
+ s := cipher.NewCTR(block, iv)
+ cryptotest.NoExtraMethods(t, &s)
+}
}
}
+func TestGCMExtraMethods(t *testing.T) {
+ testAllImplementations(t, func(t *testing.T, newCipher func([]byte) cipher.Block) {
+ t.Run("NewGCM", func(t *testing.T) {
+ a, _ := cipher.NewGCM(newCipher(make([]byte, 16)))
+ cryptotest.NoExtraMethods(t, &a)
+ })
+ t.Run("NewGCMWithTagSize", func(t *testing.T) {
+ a, _ := cipher.NewGCMWithTagSize(newCipher(make([]byte, 16)), 12)
+ cryptotest.NoExtraMethods(t, &a)
+ })
+ t.Run("NewGCMWithNonceSize", func(t *testing.T) {
+ a, _ := cipher.NewGCMWithNonceSize(newCipher(make([]byte, 16)), 12)
+ cryptotest.NoExtraMethods(t, &a)
+ })
+ t.Run("NewGCMWithRandomNonce", func(t *testing.T) {
+ block := newCipher(make([]byte, 16))
+ if _, ok := block.(*wrapper); ok || boring.Enabled {
+ t.Skip("NewGCMWithRandomNonce requires an AES block cipher")
+ }
+ a, _ := cipher.NewGCMWithRandomNonce(block)
+ cryptotest.NoExtraMethods(t, &a)
+ })
+ })
+}
+
func TestFIPSServiceIndicator(t *testing.T) {
newGCM := func() cipher.AEAD {
key := make([]byte, 16)
--- /dev/null
+// Copyright 2024 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 cryptotest
+
+import (
+ "fmt"
+ "reflect"
+ "slices"
+ "testing"
+)
+
+// NoExtraMethods checks that the concrete type of *ms has no exported methods
+// beyond the methods of the interface type of *ms, and any others specified in
+// the allowed list.
+//
+// These methods are accessible through interface upgrades, so they end up part
+// of the API even if undocumented per Hyrum's Law.
+//
+// ms must be a pointer to a non-nil interface.
+func NoExtraMethods(t *testing.T, ms interface{}, allowed ...string) {
+ t.Helper()
+ extraMethods, err := extraMethods(ms)
+ if err != nil {
+ t.Fatal(err)
+ }
+ for _, m := range extraMethods {
+ if slices.Contains(allowed, m) {
+ continue
+ }
+ t.Errorf("unexpected method %q", m)
+ }
+}
+
+func extraMethods(ip interface{}) ([]string, error) {
+ v := reflect.ValueOf(ip)
+ if v.Kind() != reflect.Ptr || v.Elem().Kind() != reflect.Interface || v.Elem().IsNil() {
+ return nil, fmt.Errorf("argument must be a pointer to a non-nil interface")
+ }
+
+ interfaceType := v.Elem().Type()
+ concreteType := v.Elem().Elem().Type()
+
+ interfaceMethods := make(map[string]bool)
+ for i := range interfaceType.NumMethod() {
+ interfaceMethods[interfaceType.Method(i).Name] = true
+ }
+
+ var extraMethods []string
+ for i := range concreteType.NumMethod() {
+ m := concreteType.Method(i)
+ if !m.IsExported() {
+ continue
+ }
+ if !interfaceMethods[m.Name] {
+ extraMethods = append(extraMethods, m.Name)
+ }
+ }
+
+ return extraMethods, nil
+}
cryptotest.TestHash(t, New)
}
+func TestExtraMethods(t *testing.T) {
+ h := New()
+ cryptotest.NoExtraMethods(t, &h, "MarshalBinary", "UnmarshalBinary", "AppendBinary")
+}
+
var bench = New()
var buf = make([]byte, 1024*1024*8+1)
var sum = make([]byte, bench.Size())
cryptotest.TestHash(t, New)
}
+func TestExtraMethods(t *testing.T) {
+ h := New()
+ cryptotest.NoExtraMethods(t, &h, "ConstantTimeSum",
+ "MarshalBinary", "UnmarshalBinary", "AppendBinary")
+}
+
var bench = New()
var buf = make([]byte, 8192)
})
}
+func TestExtraMethods(t *testing.T) {
+ t.Run("SHA-224", func(t *testing.T) {
+ cryptotest.TestAllImplementations(t, "sha256", func(t *testing.T) {
+ h := New224()
+ cryptotest.NoExtraMethods(t, &h, "MarshalBinary", "UnmarshalBinary", "AppendBinary")
+ })
+ })
+ t.Run("SHA-256", func(t *testing.T) {
+ cryptotest.TestAllImplementations(t, "sha256", func(t *testing.T) {
+ h := New()
+ cryptotest.NoExtraMethods(t, &h, "MarshalBinary", "UnmarshalBinary", "AppendBinary")
+ })
+ })
+}
+
var bench = New()
var buf = make([]byte, 8192)
})
}
+func TestExtraMethods(t *testing.T) {
+ t.Run("SHA-384", func(t *testing.T) {
+ cryptotest.TestAllImplementations(t, "sha512", func(t *testing.T) {
+ h := New384()
+ cryptotest.NoExtraMethods(t, &h, "MarshalBinary", "UnmarshalBinary", "AppendBinary")
+ })
+ })
+ t.Run("SHA-512/224", func(t *testing.T) {
+ cryptotest.TestAllImplementations(t, "sha512", func(t *testing.T) {
+ h := New512_224()
+ cryptotest.NoExtraMethods(t, &h, "MarshalBinary", "UnmarshalBinary", "AppendBinary")
+ })
+ })
+ t.Run("SHA-512/256", func(t *testing.T) {
+ cryptotest.TestAllImplementations(t, "sha512", func(t *testing.T) {
+ h := New512_256()
+ cryptotest.NoExtraMethods(t, &h, "MarshalBinary", "UnmarshalBinary", "AppendBinary")
+ })
+ })
+ t.Run("SHA-512", func(t *testing.T) {
+ cryptotest.TestAllImplementations(t, "sha512", func(t *testing.T) {
+ h := New()
+ cryptotest.NoExtraMethods(t, &h, "MarshalBinary", "UnmarshalBinary", "AppendBinary")
+ })
+ })
+}
+
var bench = New()
var buf = make([]byte, 8192)