]> Cypherpunks repositories - gostls13.git/commitdiff
crypto/internal/fips140test: add functional tests
authorFilippo Valsorda <filippo@golang.org>
Mon, 27 Jan 2025 12:02:27 +0000 (13:02 +0100)
committerGopher Robot <gobot@golang.org>
Thu, 13 Feb 2025 10:42:23 +0000 (02:42 -0800)
Running TestIntegrityCheckFailure|TestCASTFailures|TestFIPS140 with -v
and the appropriate GOFIPS140 environment variables will produce logs
sufficient for the functional testing session of the FIPS 140-3
validation. The tests can also be cross-compiled with -c and executed on
the target.

Change-Id: I6a6a465606518923d3f288e030c0f1b977aa6415
Reviewed-on: https://go-review.googlesource.com/c/go/+/648816
Reviewed-by: Ian Lance Taylor <iant@google.com>
Reviewed-by: Daniel McCarney <daniel@binaryparadox.net>
LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com>
Auto-Submit: Filippo Valsorda <filippo@golang.org>
Reviewed-by: Roland Shoemaker <roland@golang.org>
src/crypto/internal/fips140test/check_test.go
src/crypto/internal/fips140test/fips_test.go
src/crypto/internal/fips140test/nistec_test.go
src/crypto/internal/fips140test/sshkdf_test.go

index 6b0cd3f39e1695cfaefc964a6102e1fe07c34118..3c594bdb338b0e229a1f77152556c3c9dd5be818 100644 (file)
@@ -5,6 +5,7 @@
 package fipstest
 
 import (
+       "bytes"
        "crypto/internal/fips140"
        . "crypto/internal/fips140/check"
        "crypto/internal/fips140/check/checktest"
@@ -13,14 +14,14 @@ import (
        "internal/godebug"
        "internal/testenv"
        "os"
+       "path/filepath"
+       "runtime"
        "testing"
        "unicode"
        "unsafe"
 )
 
-const enableFIPSTest = true
-
-func TestFIPSCheckVerify(t *testing.T) {
+func TestIntegrityCheck(t *testing.T) {
        if Verified {
                t.Logf("verified")
                return
@@ -30,15 +31,11 @@ func TestFIPSCheckVerify(t *testing.T) {
                t.Fatalf("GODEBUG=fips140=on but verification did not run")
        }
 
-       if !enableFIPSTest {
-               return
-       }
-
        if err := fips140.Supported(); err != nil {
                t.Skipf("skipping: %v", err)
        }
 
-       cmd := testenv.Command(t, os.Args[0], "-test.v", "-test.run=TestFIPSCheck")
+       cmd := testenv.Command(t, os.Args[0], "-test.v", "-test.run=TestIntegrityCheck")
        cmd.Env = append(cmd.Environ(), "GODEBUG=fips140=on")
        out, err := cmd.CombinedOutput()
        if err != nil {
@@ -47,11 +44,52 @@ func TestFIPSCheckVerify(t *testing.T) {
        t.Logf("exec'ed GODEBUG=fips140=on and succeeded:\n%s", out)
 }
 
-func TestFIPSCheckInfo(t *testing.T) {
-       if !enableFIPSTest {
-               return
+func TestIntegrityCheckFailure(t *testing.T) {
+       moduleStatus(t)
+       testenv.MustHaveExec(t)
+       if err := fips140.Supported(); err != nil {
+               t.Skipf("skipping: %v", err)
+       }
+
+       bin, err := os.ReadFile(os.Args[0])
+       if err != nil {
+               t.Fatal(err)
        }
 
+       // Replace the expected module checksum with a different value.
+       bin = bytes.ReplaceAll(bin, Linkinfo.Sum[:], bytes.Repeat([]byte("X"), len(Linkinfo.Sum)))
+
+       binPath := filepath.Join(t.TempDir(), "fips140test.exe")
+       if err := os.WriteFile(binPath, bin, 0o755); err != nil {
+               t.Fatal(err)
+       }
+
+       if runtime.GOOS == "darwin" {
+               // Regenerate the macOS ad-hoc code signature.
+               cmd := testenv.Command(t, "codesign", "-s", "-", "-f", binPath)
+               out, err := cmd.CombinedOutput()
+               if err != nil {
+                       t.Fatalf("codesign failed: %v\n%s", err, out)
+               }
+       }
+
+       t.Logf("running modified binary...")
+       cmd := testenv.Command(t, binPath, "-test.v", "-test.run=TestIntegrityCheck$")
+       cmd.Env = append(cmd.Environ(), "GODEBUG=fips140=on")
+       out, err := cmd.CombinedOutput()
+       t.Logf("%s", out)
+       if err == nil {
+               t.Errorf("modified binary did not fail as expected")
+       }
+       if !bytes.Contains(out, []byte("fips140: verification mismatch")) {
+               t.Errorf("modified binary did not fail with expected message")
+       }
+       if bytes.Contains(out, []byte("verified")) {
+               t.Errorf("modified binary did not exit")
+       }
+}
+
+func TestIntegrityCheckInfo(t *testing.T) {
        if err := fips140.Supported(); err != nil {
                t.Skipf("skipping: %v", err)
        }
index 8da5278050ba6c478c759614198f33795565798b..1dd8aa21a9628d18bce4cc678668f79f6676b947 100644 (file)
 // to either minimize, skip, or remove them. Finally, the module needs to avoid
 // importing internal packages like testenv and cryptotest to avoid locking in
 // their APIs.
+//
+// Also, this package includes the ACVP and functional testing harnesses.
 package fipstest
 
 import (
+       "bytes"
+       "crypto/internal/boring"
+       "crypto/internal/fips140"
+       "crypto/internal/fips140/aes"
+       "crypto/internal/fips140/aes/gcm"
+       "crypto/internal/fips140/check"
+       "crypto/internal/fips140/drbg"
+       "crypto/internal/fips140/ecdh"
+       "crypto/internal/fips140/ecdsa"
+       "crypto/internal/fips140/ed25519"
+       "crypto/internal/fips140/hkdf"
+       "crypto/internal/fips140/hmac"
+       "crypto/internal/fips140/mlkem"
+       "crypto/internal/fips140/pbkdf2"
+       "crypto/internal/fips140/rsa"
+       "crypto/internal/fips140/sha256"
+       "crypto/internal/fips140/sha3"
+       "crypto/internal/fips140/sha512"
+       "crypto/internal/fips140/tls12"
+       "crypto/internal/fips140/tls13"
+       "crypto/rand"
        "encoding/hex"
        "strings"
        "testing"
 )
 
+func moduleStatus(t *testing.T) {
+       if fips140.Enabled {
+               t.Log("FIPS 140-3 mode enabled")
+       } else {
+               t.Log("FIPS 140-3 mode not enabled")
+       }
+
+       t.Logf("Module name: %s", fips140.Name())
+       t.Logf("Module version: %s", fips140.Version())
+
+       if check.Verified {
+               t.Log("FIPS 140-3 integrity self-check succeeded")
+       } else {
+               t.Log("FIPS 140-3 integrity self-check not succeeded")
+       }
+}
+
+func TestFIPS140(t *testing.T) {
+       moduleStatus(t)
+       if boring.Enabled {
+               t.Skip("Go+BoringCrypto shims prevent the service indicator from being set")
+       }
+
+       aesKey := make([]byte, 128/8)
+       aesIV := make([]byte, aes.BlockSize)
+       plaintext := []byte("Go Cryptographic Module TestFIPS140 plaintext...")
+       plaintextSHA256 := decodeHex(t, "06b2614e2ef315832b23f5d0ff70294d8ddd3889527dfbe75707fe41da929325")
+       aesBlock, err := aes.New(aesKey)
+       fatalIfErr(t, err)
+
+       t.Run("AES-CTR", func(t *testing.T) {
+               ensureServiceIndicator(t)
+               ctr := aes.NewCTR(aesBlock, aesIV)
+               ciphertext := make([]byte, len(plaintext))
+               ctr.XORKeyStream(ciphertext, plaintext)
+               t.Logf("AES-CTR ciphertext: %x", ciphertext)
+               out := make([]byte, len(plaintext))
+               ctr = aes.NewCTR(aesBlock, aesIV)
+               ctr.XORKeyStream(out, ciphertext)
+               t.Logf("AES-CTR decrypted plaintext: %s", out)
+               if !bytes.Equal(plaintext, out) {
+                       t.Errorf("AES-CTR round trip failed")
+               }
+       })
+
+       t.Run("AES-CBC", func(t *testing.T) {
+               ensureServiceIndicator(t)
+               cbcEnc := aes.NewCBCEncrypter(aesBlock, [16]byte(aesIV))
+               ciphertext := make([]byte, len(plaintext))
+               cbcEnc.CryptBlocks(ciphertext, plaintext)
+               t.Logf("AES-CBC ciphertext: %x", ciphertext)
+               cbcDec := aes.NewCBCDecrypter(aesBlock, [16]byte(aesIV))
+               out := make([]byte, len(plaintext))
+               cbcDec.CryptBlocks(out, ciphertext)
+               t.Logf("AES-CBC decrypted plaintext: %s", out)
+               if !bytes.Equal(plaintext, out) {
+                       t.Errorf("AES-CBC round trip failed")
+               }
+       })
+
+       t.Run("AES-GCM", func(t *testing.T) {
+               ensureServiceIndicator(t)
+               g, err := gcm.New(aesBlock, 12, 16)
+               fatalIfErr(t, err)
+               nonce := make([]byte, 12)
+               ciphertext := make([]byte, len(plaintext)+g.Overhead())
+               gcm.SealWithRandomNonce(g, nonce, ciphertext, plaintext, nil)
+               t.Logf("AES-GCM ciphertext: %x", ciphertext)
+               out, err := g.Open(nil, nonce, ciphertext, nil)
+               fatalIfErr(t, err)
+               t.Logf("AES-GCM decrypted plaintext: %s", out)
+               if !bytes.Equal(plaintext, out) {
+                       t.Errorf("AES-GCM round trip failed")
+               }
+       })
+
+       t.Run("Counter KDF", func(t *testing.T) {
+               ensureServiceIndicator(t)
+               k := gcm.NewCounterKDF(aesBlock)
+               context := [12]byte{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12}
+               key := k.DeriveKey(0x01, context)
+               t.Logf("Counter KDF key: %x", key)
+       })
+
+       t.Run("KAS-ECC-SSC ephemeralUnified", func(t *testing.T) {
+               ensureServiceIndicator(t)
+               k, err := ecdh.GenerateKey(ecdh.P256(), rand.Reader)
+               fatalIfErr(t, err)
+               pk := k.PublicKey()
+               shared, err := ecdh.ECDH(ecdh.P256(), k, pk)
+               fatalIfErr(t, err)
+               t.Logf("KAS-ECC-SSC shared secret: %x", shared)
+       })
+
+       t.Run("ECDSA KeyGen, SigGen, SigVer", func(t *testing.T) {
+               ensureServiceIndicator(t)
+               k, err := ecdsa.GenerateKey(ecdsa.P256(), rand.Reader)
+               fatalIfErr(t, err)
+
+               sig, err := ecdsa.Sign(ecdsa.P256(), sha256.New, k, rand.Reader, plaintextSHA256)
+               fatalIfErr(t, err)
+               t.Logf("ECDSA signature: %x", sig)
+               err = ecdsa.Verify(ecdsa.P256(), k.PublicKey(), plaintextSHA256, sig)
+               if err != nil {
+                       t.Errorf("ECDSA signature verification failed")
+               }
+
+               sig, err = ecdsa.SignDeterministic(ecdsa.P256(), sha256.New, k, plaintextSHA256)
+               fatalIfErr(t, err)
+               t.Logf("ECDSA deterministic signature: %x", sig)
+               err = ecdsa.Verify(ecdsa.P256(), k.PublicKey(), plaintextSHA256, sig)
+               if err != nil {
+                       t.Errorf("ECDSA deterministic signature verification failed")
+               }
+       })
+
+       t.Run("EDDSA KeyGen, SigGen, SigVer", func(t *testing.T) {
+               ensureServiceIndicator(t)
+               k, err := ed25519.GenerateKey()
+               fatalIfErr(t, err)
+
+               sig := ed25519.Sign(k, plaintext)
+               t.Logf("EDDSA signature: %x", sig)
+
+               pk, err := ed25519.NewPublicKey(k.PublicKey())
+               fatalIfErr(t, err)
+               err = ed25519.Verify(pk, plaintext, sig)
+               if err != nil {
+                       t.Errorf("EDDSA signature verification failed")
+               }
+       })
+
+       t.Run("ctrDRBG", func(t *testing.T) {
+               ensureServiceIndicator(t)
+               r := drbg.NewCounter((*[48]byte)(plaintext))
+               r.Reseed((*[48]byte)(plaintext), (*[48]byte)(plaintext))
+               out := make([]byte, 16)
+               r.Generate(out, (*[48]byte)(plaintext))
+               t.Logf("ctrDRBG output: %x", out)
+       })
+
+       t.Run("HMAC", func(t *testing.T) {
+               ensureServiceIndicator(t)
+               h := hmac.New(sha256.New, plaintext)
+               h.Write(plaintext)
+               out := h.Sum(nil)
+               t.Logf("HMAC output: %x", out)
+       })
+
+       t.Run("ML-KEM KeyGen, Encap, Decap", func(t *testing.T) {
+               ensureServiceIndicator(t)
+               k, err := mlkem.GenerateKey768()
+               fatalIfErr(t, err)
+
+               ss, c := k.EncapsulationKey().Encapsulate()
+               t.Logf("ML-KEM encapsulation: %x", c)
+
+               ss2, err := k.Decapsulate(c)
+               fatalIfErr(t, err)
+               t.Logf("ML-KEM shared secret: %x", ss)
+               if !bytes.Equal(ss, ss2) {
+                       t.Errorf("ML-KEM round trip failed")
+               }
+       })
+
+       var rsaKey *rsa.PrivateKey
+       t.Run("RSA KeyGen", func(t *testing.T) {
+               ensureServiceIndicator(t)
+               var err error
+               rsaKey, err = rsa.GenerateKey(rand.Reader, 2048)
+               fatalIfErr(t, err)
+               t.Log("RSA key generated")
+       })
+
+       t.Run("RSA SigGen, SigVer PKCS 1.5", func(t *testing.T) {
+               ensureServiceIndicator(t)
+               sig, err := rsa.SignPKCS1v15(rsaKey, "SHA-256", plaintextSHA256)
+               fatalIfErr(t, err)
+               t.Logf("RSA PKCS1v15 signature: %x", sig)
+
+               err = rsa.VerifyPKCS1v15(rsaKey.PublicKey(), "SHA-256", plaintextSHA256, sig)
+               fatalIfErr(t, err)
+       })
+
+       t.Run("RSA SigGen, SigVer PSS", func(t *testing.T) {
+               ensureServiceIndicator(t)
+               sig, err := rsa.SignPSS(rand.Reader, rsaKey, sha256.New(), plaintextSHA256, 16)
+               fatalIfErr(t, err)
+               t.Logf("RSA PSS signature: %x", sig)
+
+               err = rsa.VerifyPSS(rsaKey.PublicKey(), sha256.New(), plaintextSHA256, sig)
+               fatalIfErr(t, err)
+       })
+
+       t.Run("KTS IFC OAEP", func(t *testing.T) {
+               ensureServiceIndicator(t)
+               c, err := rsa.EncryptOAEP(sha256.New(), sha256.New(), rand.Reader, rsaKey.PublicKey(), plaintextSHA256, nil)
+               fatalIfErr(t, err)
+               t.Logf("RSA OAEP ciphertext: %x", c)
+
+               out, err := rsa.DecryptOAEP(sha256.New(), sha256.New(), rsaKey, c, nil)
+               fatalIfErr(t, err)
+               t.Logf("RSA OAEP decrypted plaintext: %x", out)
+               if !bytes.Equal(plaintextSHA256, out) {
+                       t.Errorf("RSA OAEP round trip failed")
+               }
+       })
+
+       t.Run("SHA2-224", func(t *testing.T) {
+               ensureServiceIndicator(t)
+               h := sha256.New224()
+               h.Write(plaintext)
+               out := h.Sum(nil)
+               t.Logf("SHA2-224 output: %x", out)
+       })
+
+       t.Run("SHA2-256", func(t *testing.T) {
+               ensureServiceIndicator(t)
+               h := sha256.New()
+               h.Write(plaintext)
+               out := h.Sum(nil)
+               t.Logf("SHA2-256 output: %x", out)
+       })
+
+       t.Run("SHA2-384", func(t *testing.T) {
+               ensureServiceIndicator(t)
+               h := sha512.New384()
+               h.Write(plaintext)
+               out := h.Sum(nil)
+               t.Logf("SHA2-384 output: %x", out)
+       })
+
+       t.Run("SHA2-512", func(t *testing.T) {
+               ensureServiceIndicator(t)
+               h := sha512.New()
+               h.Write(plaintext)
+               out := h.Sum(nil)
+               t.Logf("SHA2-512 output: %x", out)
+       })
+
+       t.Run("SHA2-512/224", func(t *testing.T) {
+               ensureServiceIndicator(t)
+               h := sha512.New512_224()
+               h.Write(plaintext)
+               out := h.Sum(nil)
+               t.Logf("SHA2-512/224 output: %x", out)
+       })
+
+       t.Run("SHA2-512/256", func(t *testing.T) {
+               ensureServiceIndicator(t)
+               h := sha512.New512_256()
+               h.Write(plaintext)
+               out := h.Sum(nil)
+               t.Logf("SHA2-512/256 output: %x", out)
+       })
+
+       t.Run("SHA3-224", func(t *testing.T) {
+               ensureServiceIndicator(t)
+               h := sha3.New224()
+               h.Write(plaintext)
+               out := h.Sum(nil)
+               t.Logf("SHA3-224 output: %x", out)
+       })
+
+       t.Run("SHA3-256", func(t *testing.T) {
+               ensureServiceIndicator(t)
+               h := sha3.New256()
+               h.Write(plaintext)
+               out := h.Sum(nil)
+               t.Logf("SHA3-256 output: %x", out)
+       })
+
+       t.Run("SHA3-384", func(t *testing.T) {
+               ensureServiceIndicator(t)
+               h := sha3.New384()
+               h.Write(plaintext)
+               out := h.Sum(nil)
+               t.Logf("SHA3-384 output: %x", out)
+       })
+
+       t.Run("SHA3-512", func(t *testing.T) {
+               ensureServiceIndicator(t)
+               h := sha3.New512()
+               h.Write(plaintext)
+               out := h.Sum(nil)
+               t.Logf("SHA3-512 output: %x", out)
+       })
+
+       t.Run("SHAKE-128", func(t *testing.T) {
+               ensureServiceIndicator(t)
+               h := sha3.NewShake128()
+               h.Write(plaintext)
+               out := make([]byte, 16)
+               h.Read(out)
+               t.Logf("SHAKE-128 output: %x", out)
+       })
+
+       t.Run("SHAKE-256", func(t *testing.T) {
+               ensureServiceIndicator(t)
+               h := sha3.NewShake256()
+               h.Write(plaintext)
+               out := make([]byte, 16)
+               h.Read(out)
+               t.Logf("SHAKE-256 output: %x", out)
+       })
+
+       t.Run("cSHAKE-128", func(t *testing.T) {
+               ensureServiceIndicator(t)
+               h := sha3.NewCShake128(nil, []byte("test"))
+               h.Write(plaintext)
+               out := make([]byte, 16)
+               h.Read(out)
+               t.Logf("cSHAKE-128 output: %x", out)
+       })
+
+       t.Run("cSHAKE-256", func(t *testing.T) {
+               ensureServiceIndicator(t)
+               h := sha3.NewCShake256(nil, []byte("test"))
+               h.Write(plaintext)
+               out := make([]byte, 16)
+               h.Read(out)
+               t.Logf("cSHAKE-256 output: %x", out)
+       })
+
+       t.Run("KDA HKDF", func(t *testing.T) {
+               ensureServiceIndicator(t)
+               key := hkdf.Key(sha256.New, plaintextSHA256, []byte("salt"), "info", 16)
+               t.Logf("HKDF key: %x", key)
+       })
+
+       t.Run("KDA OneStepNoCounter", func(t *testing.T) {
+               ensureServiceIndicator(t)
+               key := hkdf.Extract(sha256.New, plaintextSHA256, []byte("salt"))
+               t.Logf("KDA OneStepNoCounter key: %x", key)
+       })
+
+       t.Run("Feedback KDF", func(t *testing.T) {
+               ensureServiceIndicator(t)
+               key := hkdf.Expand(sha256.New, plaintextSHA256, "info", 16)
+               t.Logf("Feedback KDF key: %x", key)
+       })
+
+       t.Run("PBKDF", func(t *testing.T) {
+               ensureServiceIndicator(t)
+               key, err := pbkdf2.Key(sha256.New, "password", plaintextSHA256, 2, 16)
+               fatalIfErr(t, err)
+               t.Logf("PBKDF key: %x", key)
+       })
+
+       t.Run("KDF TLS v1.2 CVL", func(t *testing.T) {
+               ensureServiceIndicator(t)
+               key := tls12.MasterSecret(sha256.New, plaintextSHA256, []byte("test"))
+               t.Logf("TLS v1.2 CVL Master Secret: %x", key)
+       })
+
+       t.Run("KDF TLS v1.3 CVL", func(t *testing.T) {
+               ensureServiceIndicator(t)
+               es := tls13.NewEarlySecret(sha256.New, plaintextSHA256)
+               hs := es.HandshakeSecret(plaintextSHA256)
+               ms := hs.MasterSecret()
+               client := ms.ClientApplicationTrafficSecret(sha256.New())
+               server := ms.ServerApplicationTrafficSecret(sha256.New())
+               t.Logf("TLS v1.3 CVL Application Traffic Secrets: client %x, server %x", client, server)
+       })
+}
+
+func ensureServiceIndicator(t *testing.T) {
+       fips140.ResetServiceIndicator()
+       t.Cleanup(func() {
+               if fips140.ServiceIndicator() {
+                       t.Logf("Service indicator is set")
+               } else {
+                       t.Errorf("Service indicator is not set")
+               }
+       })
+}
+
+func fatalIfErr(t *testing.T, err error) {
+       t.Helper()
+       if err != nil {
+               t.Fatal(err)
+       }
+}
+
 func decodeHex(t *testing.T, s string) []byte {
        t.Helper()
        s = strings.ReplaceAll(s, " ", "")
index 3849add7004e2a43b627522c190ca99aa7d9406e..3b3de2bc2cb1f68bb0980a853f321f38e7ebede9 100644 (file)
@@ -251,10 +251,3 @@ func testScalarMult[P nistPoint[P]](t *testing.T, newPoint func() P, c elliptic.
                })
        }
 }
-
-func fatalIfErr(t *testing.T, err error) {
-       t.Helper()
-       if err != nil {
-               t.Fatal(err)
-       }
-}
index 91135205de9bd5f3dac0c469a64efca0fc3a57f7..3538af8469bee86d577965eb4af9c7cece582d08 100644 (file)
@@ -8,23 +8,22 @@ import (
        "bytes"
        "crypto/internal/fips140/ssh"
        "crypto/sha256"
-       "encoding/hex"
        "testing"
 )
 
 func TestSSHACVPVector(t *testing.T) {
        // https://github.com/usnistgov/ACVP-Server/blob/3a7333f638/gen-val/json-files/kdf-components-ssh-1.0/prompt.json#L910-L915
-       K := fromHex("0000010100E534CD9780786AF19994DD68C3FD7FE1E1F77C3938B2005C49B080CF88A63A44079774A36F23BA4D73470CB318C30524854D2F36BAB9A45AD73DBB3BC5DD39A547F62BC921052E102E37F3DD0CD79A04EB46ACC14B823B326096A89E33E8846624188BB3C8F16B320E7BB8F5EB05F080DCEE244A445DBED3A9F3BA8C373D8BE62CDFE2FC5876F30F90F01F0A55E5251B23E0DBBFCFB1450715E329BB00FB222E850DDB11201460B8AEF3FC8965D3B6D3AFBB885A6C11F308F10211B82EA2028C7A84DD0BB8D5D6AC3A48D0C2B93609269C585E03889DB3621993E7F7C09A007FB6B5C06FFA532B0DBF11F71F740D9CD8FAD2532E21B9423BF3D85EE4E396BE32")
-       H := fromHex("8FB22F0864960DA5679FD377248E41C2D0390E5AB3BB7955A3B6C588FB75B20D")
-       sessionID := fromHex("269A512E7B560E13396E0F3F56BDA730E23EE122EE6D59C91C58FB07872BCCCC")
+       K := decodeHex(t, "0000010100E534CD9780786AF19994DD68C3FD7FE1E1F77C3938B2005C49B080CF88A63A44079774A36F23BA4D73470CB318C30524854D2F36BAB9A45AD73DBB3BC5DD39A547F62BC921052E102E37F3DD0CD79A04EB46ACC14B823B326096A89E33E8846624188BB3C8F16B320E7BB8F5EB05F080DCEE244A445DBED3A9F3BA8C373D8BE62CDFE2FC5876F30F90F01F0A55E5251B23E0DBBFCFB1450715E329BB00FB222E850DDB11201460B8AEF3FC8965D3B6D3AFBB885A6C11F308F10211B82EA2028C7A84DD0BB8D5D6AC3A48D0C2B93609269C585E03889DB3621993E7F7C09A007FB6B5C06FFA532B0DBF11F71F740D9CD8FAD2532E21B9423BF3D85EE4E396BE32")
+       H := decodeHex(t, "8FB22F0864960DA5679FD377248E41C2D0390E5AB3BB7955A3B6C588FB75B20D")
+       sessionID := decodeHex(t, "269A512E7B560E13396E0F3F56BDA730E23EE122EE6D59C91C58FB07872BCCCC")
 
        // https://github.com/usnistgov/ACVP-Server/blob/3a7333f638/gen-val/json-files/kdf-components-ssh-1.0/expectedResults.json#L1306-L1314
-       initialIVClient := fromHex("82321D9FE2ACD958D3F55F4D3FF5C79D")
-       initialIVServer := fromHex("03F336F61311770BD5346B41E04CDB1F")
-       encryptionKeyClient := fromHex("20E55008D0120C400F42E5D2E148AB75")
-       encryptionKeyServer := fromHex("8BF4DEBEC96F4ADBBE5BB43828D56E6D")
-       integrityKeyClient := fromHex("15F53BCCE2645D0AD1C539C09BF9054AA3A4B10B71E96B9E3A15672405341BB5")
-       integrityKeyServer := fromHex("00BB773FD63AC7B7281A7B54C130CCAD363EE8928104E67CA5A3211EE3BBAB93")
+       initialIVClient := decodeHex(t, "82321D9FE2ACD958D3F55F4D3FF5C79D")
+       initialIVServer := decodeHex(t, "03F336F61311770BD5346B41E04CDB1F")
+       encryptionKeyClient := decodeHex(t, "20E55008D0120C400F42E5D2E148AB75")
+       encryptionKeyServer := decodeHex(t, "8BF4DEBEC96F4ADBBE5BB43828D56E6D")
+       integrityKeyClient := decodeHex(t, "15F53BCCE2645D0AD1C539C09BF9054AA3A4B10B71E96B9E3A15672405341BB5")
+       integrityKeyServer := decodeHex(t, "00BB773FD63AC7B7281A7B54C130CCAD363EE8928104E67CA5A3211EE3BBAB93")
 
        gotIVClient, gotKeyClient, gotIntegrityClient := ssh.Keys(
                sha256.New, ssh.ClientKeys, K, H, sessionID, 16, 16, 32)
@@ -50,11 +49,3 @@ func TestSSHACVPVector(t *testing.T) {
                t.Errorf("got integrity key server %x, want %x", gotIntegrityServer, integrityKeyServer)
        }
 }
-
-func fromHex(s string) []byte {
-       b, err := hex.DecodeString(s)
-       if err != nil {
-               panic(err)
-       }
-       return b
-}