Help us shape the future of Go! Take the 2026 Go Developer Survey

Source file src/crypto/internal/fips140test/fips_test.go

     1  // Copyright 2024 The Go Authors. All rights reserved.
     2  // Use of this source code is governed by a BSD-style
     3  // license that can be found in the LICENSE file.
     4  
     5  // Package fipstest collects external tests that would ordinarily live in
     6  // crypto/internal/fips140/... packages. That tree gets snapshot at each
     7  // validation, while we want tests to evolve and still apply to all versions of
     8  // the module. Also, we can't fix failing tests in a module snapshot, so we need
     9  // to either minimize, skip, or remove them. Finally, the module needs to avoid
    10  // importing internal packages like testenv and cryptotest to avoid locking in
    11  // their APIs.
    12  //
    13  // Also, this package includes the ACVP and functional testing harnesses.
    14  package fipstest
    15  
    16  import (
    17  	"bytes"
    18  	"crypto/internal/boring"
    19  	"crypto/internal/cryptotest"
    20  	"crypto/internal/fips140"
    21  	"crypto/internal/fips140/aes"
    22  	"crypto/internal/fips140/aes/gcm"
    23  	"crypto/internal/fips140/check"
    24  	"crypto/internal/fips140/drbg"
    25  	"crypto/internal/fips140/ecdh"
    26  	"crypto/internal/fips140/ecdsa"
    27  	"crypto/internal/fips140/ed25519"
    28  	"crypto/internal/fips140/hkdf"
    29  	"crypto/internal/fips140/hmac"
    30  	"crypto/internal/fips140/mlkem"
    31  	"crypto/internal/fips140/pbkdf2"
    32  	"crypto/internal/fips140/rsa"
    33  	"crypto/internal/fips140/sha256"
    34  	"crypto/internal/fips140/sha3"
    35  	"crypto/internal/fips140/sha512"
    36  	"crypto/internal/fips140/tls12"
    37  	"crypto/internal/fips140/tls13"
    38  	"crypto/rand"
    39  	"encoding/hex"
    40  	"runtime/debug"
    41  	"strings"
    42  	"testing"
    43  )
    44  
    45  func moduleStatus(t *testing.T) {
    46  	if fips140.Enabled {
    47  		t.Log("FIPS 140-3 mode enabled")
    48  	} else {
    49  		t.Log("FIPS 140-3 mode not enabled")
    50  	}
    51  
    52  	t.Logf("Module name: %s", fips140.Name())
    53  	t.Logf("Module version: %s", fips140.Version())
    54  
    55  	if noPAAPAI {
    56  		t.Log("PAA/PAI disabled")
    57  	} else {
    58  		t.Log("PAA/PAI enabled")
    59  	}
    60  
    61  	if check.Verified {
    62  		t.Log("FIPS 140-3 integrity self-check succeeded")
    63  	} else {
    64  		t.Log("FIPS 140-3 integrity self-check not succeeded")
    65  	}
    66  }
    67  
    68  func TestVersion(t *testing.T) {
    69  	bi, ok := debug.ReadBuildInfo()
    70  	if !ok {
    71  		t.Skip("no build info")
    72  	}
    73  	for _, setting := range bi.Settings {
    74  		if setting.Key != "GOFIPS140" {
    75  			continue
    76  		}
    77  		exp := setting.Value
    78  		// Remove the -hash suffix, if any.
    79  		// The version from fips140.Version omits it.
    80  		exp, _, _ = strings.Cut(exp, "-")
    81  		if v := fips140.Version(); v != exp {
    82  			t.Errorf("Version is %q, expected %q", v, exp)
    83  		}
    84  		return
    85  	}
    86  	// Without GOFIPS140, the Version should be "latest".
    87  	if v := fips140.Version(); v != "latest" {
    88  		t.Errorf("Version is %q, expected latest", v)
    89  	}
    90  }
    91  
    92  func TestFIPS140(t *testing.T) {
    93  	moduleStatus(t)
    94  	if boring.Enabled {
    95  		t.Skip("Go+BoringCrypto shims prevent the service indicator from being set")
    96  	}
    97  
    98  	aesKey := make([]byte, 128/8)
    99  	aesIV := make([]byte, aes.BlockSize)
   100  	plaintext := []byte("Go Cryptographic Module TestFIPS140 plaintext...")
   101  	plaintextSHA256 := decodeHex(t, "06b2614e2ef315832b23f5d0ff70294d8ddd3889527dfbe75707fe41da929325")
   102  	plaintextSHA384 := decodeHex(t, "ad20990965f6caec69e016072881f80f049c0687554809901ec4c0988c3fec678c0926fe5661742185be968de6c4d9b2")
   103  	aesBlock, err := aes.New(aesKey)
   104  	fatalIfErr(t, err)
   105  
   106  	testFIPS140v126(t, plaintext)
   107  
   108  	t.Run("AES-CTR", func(t *testing.T) {
   109  		ensureServiceIndicator(t)
   110  		ctr := aes.NewCTR(aesBlock, aesIV)
   111  		ciphertext := make([]byte, len(plaintext))
   112  		ctr.XORKeyStream(ciphertext, plaintext)
   113  		t.Logf("AES-CTR ciphertext: %x", ciphertext)
   114  		out := make([]byte, len(plaintext))
   115  		ctr = aes.NewCTR(aesBlock, aesIV)
   116  		ctr.XORKeyStream(out, ciphertext)
   117  		t.Logf("AES-CTR decrypted plaintext: %s", out)
   118  		if !bytes.Equal(plaintext, out) {
   119  			t.Errorf("AES-CTR round trip failed")
   120  		}
   121  	})
   122  
   123  	t.Run("AES-CBC", func(t *testing.T) {
   124  		ensureServiceIndicator(t)
   125  		cbcEnc := aes.NewCBCEncrypter(aesBlock, [16]byte(aesIV))
   126  		ciphertext := make([]byte, len(plaintext))
   127  		cbcEnc.CryptBlocks(ciphertext, plaintext)
   128  		t.Logf("AES-CBC ciphertext: %x", ciphertext)
   129  		cbcDec := aes.NewCBCDecrypter(aesBlock, [16]byte(aesIV))
   130  		out := make([]byte, len(plaintext))
   131  		cbcDec.CryptBlocks(out, ciphertext)
   132  		t.Logf("AES-CBC decrypted plaintext: %s", out)
   133  		if !bytes.Equal(plaintext, out) {
   134  			t.Errorf("AES-CBC round trip failed")
   135  		}
   136  	})
   137  
   138  	t.Run("AES-GCM", func(t *testing.T) {
   139  		ensureServiceIndicator(t)
   140  		g, err := gcm.New(aesBlock, 12, 16)
   141  		fatalIfErr(t, err)
   142  		nonce := make([]byte, 12)
   143  		ciphertext := make([]byte, len(plaintext)+g.Overhead())
   144  		gcm.SealWithRandomNonce(g, nonce, ciphertext, plaintext, nil)
   145  		t.Logf("AES-GCM ciphertext: %x", ciphertext)
   146  		out, err := g.Open(nil, nonce, ciphertext, nil)
   147  		fatalIfErr(t, err)
   148  		t.Logf("AES-GCM decrypted plaintext: %s", out)
   149  		if !bytes.Equal(plaintext, out) {
   150  			t.Errorf("AES-GCM round trip failed")
   151  		}
   152  	})
   153  
   154  	t.Run("Counter KDF", func(t *testing.T) {
   155  		ensureServiceIndicator(t)
   156  		k := gcm.NewCounterKDF(aesBlock)
   157  		context := [12]byte{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12}
   158  		key := k.DeriveKey(0x01, context)
   159  		t.Logf("Counter KDF key: %x", key)
   160  	})
   161  
   162  	t.Run("KAS-ECC-SSC ephemeralUnified", func(t *testing.T) {
   163  		ensureServiceIndicator(t)
   164  		k, err := ecdh.GenerateKey(ecdh.P256(), rand.Reader)
   165  		fatalIfErr(t, err)
   166  		pk := k.PublicKey()
   167  		shared, err := ecdh.ECDH(ecdh.P256(), k, pk)
   168  		fatalIfErr(t, err)
   169  		t.Logf("KAS-ECC-SSC shared secret: %x", shared)
   170  	})
   171  
   172  	t.Run("ECDSA KeyGen, SigGen, SigVer", func(t *testing.T) {
   173  		ensureServiceIndicator(t)
   174  		k, err := ecdsa.GenerateKey(ecdsa.P256(), rand.Reader)
   175  		fatalIfErr(t, err)
   176  
   177  		sig, err := ecdsa.Sign(ecdsa.P256(), sha256.New, k, rand.Reader, plaintextSHA256)
   178  		fatalIfErr(t, err)
   179  		t.Logf("ECDSA signature: %x", sig)
   180  		err = ecdsa.Verify(ecdsa.P256(), k.PublicKey(), plaintextSHA256, sig)
   181  		if err != nil {
   182  			t.Errorf("ECDSA signature verification failed")
   183  		}
   184  
   185  		sig, err = ecdsa.SignDeterministic(ecdsa.P256(), sha256.New, k, plaintextSHA256)
   186  		fatalIfErr(t, err)
   187  		t.Logf("ECDSA deterministic signature: %x", sig)
   188  		err = ecdsa.Verify(ecdsa.P256(), k.PublicKey(), plaintextSHA256, sig)
   189  		if err != nil {
   190  			t.Errorf("ECDSA deterministic signature verification failed")
   191  		}
   192  	})
   193  
   194  	t.Run("EDDSA KeyGen, SigGen, SigVer", func(t *testing.T) {
   195  		ensureServiceIndicator(t)
   196  		k, err := ed25519.GenerateKey()
   197  		fatalIfErr(t, err)
   198  
   199  		sig := ed25519.Sign(k, plaintext)
   200  		t.Logf("EDDSA signature: %x", sig)
   201  
   202  		pk, err := ed25519.NewPublicKey(k.PublicKey())
   203  		fatalIfErr(t, err)
   204  		err = ed25519.Verify(pk, plaintext, sig)
   205  		if err != nil {
   206  			t.Errorf("EDDSA signature verification failed")
   207  		}
   208  	})
   209  
   210  	t.Run("ctrDRBG", func(t *testing.T) {
   211  		ensureServiceIndicator(t)
   212  		r := drbg.NewCounter((*[48]byte)(plaintext))
   213  		r.Reseed((*[48]byte)(plaintext), (*[48]byte)(plaintext))
   214  		out := make([]byte, 16)
   215  		r.Generate(out, (*[48]byte)(plaintext))
   216  		t.Logf("ctrDRBG output: %x", out)
   217  	})
   218  
   219  	t.Run("HMAC", func(t *testing.T) {
   220  		ensureServiceIndicator(t)
   221  		h := hmac.New(sha256.New, plaintext)
   222  		h.Write(plaintext)
   223  		out := h.Sum(nil)
   224  		t.Logf("HMAC output: %x", out)
   225  	})
   226  
   227  	t.Run("HMAC w/ Keccak-256 [NOT APPROVED]", func(t *testing.T) {
   228  		cryptotest.MustMinimumFIPS140ModuleVersion(t, "v1.28.0")
   229  		ensureServiceIndicatorFalse(t)
   230  		h := hmac.New(sha3.NewLegacyKeccak256, plaintext)
   231  		h.Write(plaintext)
   232  		out := h.Sum(nil)
   233  		t.Logf("HMAC w/ Keccak-256 output: %x", out)
   234  	})
   235  
   236  	t.Run("ML-KEM KeyGen, Encap, Decap", func(t *testing.T) {
   237  		ensureServiceIndicator(t)
   238  		k, err := mlkem.GenerateKey768()
   239  		fatalIfErr(t, err)
   240  
   241  		ss, c := k.EncapsulationKey().Encapsulate()
   242  		t.Logf("ML-KEM encapsulation: %x", c)
   243  
   244  		ss2, err := k.Decapsulate(c)
   245  		fatalIfErr(t, err)
   246  		t.Logf("ML-KEM shared secret: %x", ss)
   247  		if !bytes.Equal(ss, ss2) {
   248  			t.Errorf("ML-KEM round trip failed")
   249  		}
   250  	})
   251  
   252  	var rsaKey *rsa.PrivateKey
   253  	t.Run("RSA KeyGen", func(t *testing.T) {
   254  		ensureServiceIndicator(t)
   255  		var err error
   256  		rsaKey, err = rsa.GenerateKey(rand.Reader, 2048)
   257  		fatalIfErr(t, err)
   258  		t.Log("RSA key generated")
   259  	})
   260  
   261  	t.Run("RSA SigGen, SigVer PKCS 1.5", func(t *testing.T) {
   262  		ensureServiceIndicator(t)
   263  		sig, err := rsa.SignPKCS1v15(rsaKey, "SHA-256", plaintextSHA256)
   264  		fatalIfErr(t, err)
   265  		t.Logf("RSA PKCS1v15 signature: %x", sig)
   266  
   267  		err = rsa.VerifyPKCS1v15(rsaKey.PublicKey(), "SHA-256", plaintextSHA256, sig)
   268  		fatalIfErr(t, err)
   269  	})
   270  
   271  	t.Run("RSA SigGen, SigVer PSS", func(t *testing.T) {
   272  		ensureServiceIndicator(t)
   273  		sig, err := rsa.SignPSS(rand.Reader, rsaKey, sha256.New(), plaintextSHA256, 16)
   274  		fatalIfErr(t, err)
   275  		t.Logf("RSA PSS signature: %x", sig)
   276  
   277  		err = rsa.VerifyPSS(rsaKey.PublicKey(), sha256.New(), plaintextSHA256, sig)
   278  		fatalIfErr(t, err)
   279  	})
   280  
   281  	t.Run("RSA SigGen PSS w/ Keccak-256 [NOT APPROVED]", func(t *testing.T) {
   282  		cryptotest.MustMinimumFIPS140ModuleVersion(t, "v1.28.0")
   283  		ensureServiceIndicatorFalse(t)
   284  		sig, err := rsa.SignPSS(rand.Reader, rsaKey, sha3.NewLegacyKeccak256(), plaintextSHA256, 16)
   285  		fatalIfErr(t, err)
   286  		t.Logf("RSA PSS w/ Keccak-256 signature: %x", sig)
   287  	})
   288  
   289  	t.Run("RSA KeyGen w/ small key [NOT APPROVED]", func(t *testing.T) {
   290  		ensureServiceIndicatorFalse(t)
   291  		_, err := rsa.GenerateKey(rand.Reader, 512)
   292  		fatalIfErr(t, err)
   293  		t.Log("RSA key generated")
   294  	})
   295  
   296  	t.Run("KTS IFC OAEP", func(t *testing.T) {
   297  		ensureServiceIndicator(t)
   298  		c, err := rsa.EncryptOAEP(sha256.New(), sha256.New(), rand.Reader, rsaKey.PublicKey(), plaintextSHA256, nil)
   299  		fatalIfErr(t, err)
   300  		t.Logf("RSA OAEP ciphertext: %x", c)
   301  
   302  		out, err := rsa.DecryptOAEP(sha256.New(), sha256.New(), rsaKey, c, nil)
   303  		fatalIfErr(t, err)
   304  		t.Logf("RSA OAEP decrypted plaintext: %x", out)
   305  		if !bytes.Equal(plaintextSHA256, out) {
   306  			t.Errorf("RSA OAEP round trip failed")
   307  		}
   308  	})
   309  
   310  	t.Run("SHA2-224", func(t *testing.T) {
   311  		ensureServiceIndicator(t)
   312  		h := sha256.New224()
   313  		h.Write(plaintext)
   314  		out := h.Sum(nil)
   315  		t.Logf("SHA2-224 output: %x", out)
   316  	})
   317  
   318  	t.Run("SHA2-256", func(t *testing.T) {
   319  		ensureServiceIndicator(t)
   320  		h := sha256.New()
   321  		h.Write(plaintext)
   322  		out := h.Sum(nil)
   323  		t.Logf("SHA2-256 output: %x", out)
   324  	})
   325  
   326  	t.Run("SHA2-384", func(t *testing.T) {
   327  		ensureServiceIndicator(t)
   328  		h := sha512.New384()
   329  		h.Write(plaintext)
   330  		out := h.Sum(nil)
   331  		t.Logf("SHA2-384 output: %x", out)
   332  	})
   333  
   334  	t.Run("SHA2-512", func(t *testing.T) {
   335  		ensureServiceIndicator(t)
   336  		h := sha512.New()
   337  		h.Write(plaintext)
   338  		out := h.Sum(nil)
   339  		t.Logf("SHA2-512 output: %x", out)
   340  	})
   341  
   342  	t.Run("SHA2-512/224", func(t *testing.T) {
   343  		ensureServiceIndicator(t)
   344  		h := sha512.New512_224()
   345  		h.Write(plaintext)
   346  		out := h.Sum(nil)
   347  		t.Logf("SHA2-512/224 output: %x", out)
   348  	})
   349  
   350  	t.Run("SHA2-512/256", func(t *testing.T) {
   351  		ensureServiceIndicator(t)
   352  		h := sha512.New512_256()
   353  		h.Write(plaintext)
   354  		out := h.Sum(nil)
   355  		t.Logf("SHA2-512/256 output: %x", out)
   356  	})
   357  
   358  	t.Run("SHA3-224", func(t *testing.T) {
   359  		ensureServiceIndicator(t)
   360  		h := sha3.New224()
   361  		h.Write(plaintext)
   362  		out := h.Sum(nil)
   363  		t.Logf("SHA3-224 output: %x", out)
   364  	})
   365  
   366  	t.Run("SHA3-256", func(t *testing.T) {
   367  		ensureServiceIndicator(t)
   368  		h := sha3.New256()
   369  		h.Write(plaintext)
   370  		out := h.Sum(nil)
   371  		t.Logf("SHA3-256 output: %x", out)
   372  	})
   373  
   374  	t.Run("SHA3-384", func(t *testing.T) {
   375  		ensureServiceIndicator(t)
   376  		h := sha3.New384()
   377  		h.Write(plaintext)
   378  		out := h.Sum(nil)
   379  		t.Logf("SHA3-384 output: %x", out)
   380  	})
   381  
   382  	t.Run("SHA3-512", func(t *testing.T) {
   383  		ensureServiceIndicator(t)
   384  		h := sha3.New512()
   385  		h.Write(plaintext)
   386  		out := h.Sum(nil)
   387  		t.Logf("SHA3-512 output: %x", out)
   388  	})
   389  
   390  	t.Run("SHAKE-128", func(t *testing.T) {
   391  		ensureServiceIndicator(t)
   392  		h := sha3.NewShake128()
   393  		h.Write(plaintext)
   394  		out := make([]byte, 16)
   395  		h.Read(out)
   396  		t.Logf("SHAKE-128 output: %x", out)
   397  	})
   398  
   399  	t.Run("SHAKE-256", func(t *testing.T) {
   400  		ensureServiceIndicator(t)
   401  		h := sha3.NewShake256()
   402  		h.Write(plaintext)
   403  		out := make([]byte, 16)
   404  		h.Read(out)
   405  		t.Logf("SHAKE-256 output: %x", out)
   406  	})
   407  
   408  	t.Run("cSHAKE-128", func(t *testing.T) {
   409  		ensureServiceIndicator(t)
   410  		h := sha3.NewCShake128(nil, []byte("test"))
   411  		h.Write(plaintext)
   412  		out := make([]byte, 16)
   413  		h.Read(out)
   414  		t.Logf("cSHAKE-128 output: %x", out)
   415  	})
   416  
   417  	t.Run("cSHAKE-256", func(t *testing.T) {
   418  		ensureServiceIndicator(t)
   419  		h := sha3.NewCShake256(nil, []byte("test"))
   420  		h.Write(plaintext)
   421  		out := make([]byte, 16)
   422  		h.Read(out)
   423  		t.Logf("cSHAKE-256 output: %x", out)
   424  	})
   425  
   426  	t.Run("Keccak-256 [NOT APPROVED]", func(t *testing.T) {
   427  		cryptotest.MustMinimumFIPS140ModuleVersion(t, "v1.28.0")
   428  		ensureServiceIndicatorFalse(t)
   429  		h := sha3.NewLegacyKeccak256()
   430  		h.Write(plaintext)
   431  		out := h.Sum(nil)
   432  		t.Logf("Keccak-256 output: %x", out)
   433  	})
   434  
   435  	t.Run("KDA HKDF", func(t *testing.T) {
   436  		ensureServiceIndicator(t)
   437  		key := hkdf.Key(sha256.New, plaintextSHA256, []byte("salt"), "info", 16)
   438  		t.Logf("HKDF key: %x", key)
   439  	})
   440  
   441  	t.Run("KDA OneStepNoCounter", func(t *testing.T) {
   442  		ensureServiceIndicator(t)
   443  		key := hkdf.Extract(sha256.New, plaintextSHA256, []byte("salt"))
   444  		t.Logf("KDA OneStepNoCounter key: %x", key)
   445  	})
   446  
   447  	t.Run("Feedback KDF", func(t *testing.T) {
   448  		ensureServiceIndicator(t)
   449  		key := hkdf.Expand(sha256.New, plaintextSHA256, "info", 16)
   450  		t.Logf("Feedback KDF key: %x", key)
   451  	})
   452  
   453  	t.Run("PBKDF", func(t *testing.T) {
   454  		ensureServiceIndicator(t)
   455  		key, err := pbkdf2.Key(sha256.New, "password", plaintextSHA256, 2, 16)
   456  		fatalIfErr(t, err)
   457  		t.Logf("PBKDF key: %x", key)
   458  	})
   459  
   460  	t.Run("KDF TLS v1.2 CVL", func(t *testing.T) {
   461  		ensureServiceIndicator(t)
   462  		key := tls12.MasterSecret(sha256.New, plaintextSHA256, []byte("test"))
   463  		t.Logf("TLS v1.2 CVL Master Secret: %x", key)
   464  	})
   465  
   466  	t.Run("KDF TLS v1.2 CVL SHA-384", func(t *testing.T) {
   467  		cryptotest.MustMinimumFIPS140ModuleVersion(t, "v1.28.0")
   468  		ensureServiceIndicator(t)
   469  		key := tls12.MasterSecret(sha512.New384, plaintextSHA384, []byte("test"))
   470  		t.Logf("TLS v1.2 CVL SHA-384 Master Secret: %x", key)
   471  	})
   472  
   473  	t.Run("KDF TLS v1.3 CVL", func(t *testing.T) {
   474  		ensureServiceIndicator(t)
   475  		es := tls13.NewEarlySecret(sha256.New, plaintextSHA256)
   476  		hs := es.HandshakeSecret(plaintextSHA256)
   477  		ms := hs.MasterSecret()
   478  		client := ms.ClientApplicationTrafficSecret(sha256.New())
   479  		server := ms.ServerApplicationTrafficSecret(sha256.New())
   480  		t.Logf("TLS v1.3 CVL Application Traffic Secrets: client %x, server %x", client, server)
   481  	})
   482  }
   483  
   484  func ensureServiceIndicator(t *testing.T) {
   485  	fips140.ResetServiceIndicator()
   486  	t.Cleanup(func() {
   487  		if fips140.ServiceIndicator() {
   488  			t.Logf("Service indicator is set")
   489  		} else {
   490  			t.Errorf("Service indicator is not set")
   491  		}
   492  	})
   493  }
   494  
   495  func ensureServiceIndicatorFalse(t *testing.T) {
   496  	fips140.ResetServiceIndicator()
   497  	t.Cleanup(func() {
   498  		if !fips140.ServiceIndicator() {
   499  			t.Logf("Service indicator is not set")
   500  		} else {
   501  			t.Errorf("Service indicator is set")
   502  		}
   503  	})
   504  }
   505  
   506  func fatalIfErr(t *testing.T, err error) {
   507  	t.Helper()
   508  	if err != nil {
   509  		t.Fatal(err)
   510  	}
   511  }
   512  
   513  func decodeHex(t *testing.T, s string) []byte {
   514  	t.Helper()
   515  	s = strings.ReplaceAll(s, " ", "")
   516  	b, err := hex.DecodeString(s)
   517  	if err != nil {
   518  		t.Fatal(err)
   519  	}
   520  	return b
   521  }
   522  

View as plain text