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/fips140"
    20  	"crypto/internal/fips140/aes"
    21  	"crypto/internal/fips140/aes/gcm"
    22  	"crypto/internal/fips140/check"
    23  	"crypto/internal/fips140/drbg"
    24  	"crypto/internal/fips140/ecdh"
    25  	"crypto/internal/fips140/ecdsa"
    26  	"crypto/internal/fips140/ed25519"
    27  	"crypto/internal/fips140/hkdf"
    28  	"crypto/internal/fips140/hmac"
    29  	"crypto/internal/fips140/mlkem"
    30  	"crypto/internal/fips140/pbkdf2"
    31  	"crypto/internal/fips140/rsa"
    32  	"crypto/internal/fips140/sha256"
    33  	"crypto/internal/fips140/sha3"
    34  	"crypto/internal/fips140/sha512"
    35  	"crypto/internal/fips140/tls12"
    36  	"crypto/internal/fips140/tls13"
    37  	"crypto/rand"
    38  	"encoding/hex"
    39  	"runtime"
    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  	t.Logf("GOOS/GOARCH: %s/%s", runtime.GOOS, runtime.GOARCH)
    55  
    56  	if noPAAPAI {
    57  		t.Log("PAA/PAI disabled")
    58  	} else {
    59  		t.Log("PAA/PAI enabled")
    60  	}
    61  
    62  	if check.Verified {
    63  		t.Log("FIPS 140-3 integrity self-check succeeded")
    64  	} else {
    65  		t.Log("FIPS 140-3 integrity self-check not succeeded")
    66  	}
    67  }
    68  
    69  func TestVersion(t *testing.T) {
    70  	bi, ok := debug.ReadBuildInfo()
    71  	if !ok {
    72  		t.Skip("no build info")
    73  	}
    74  	for _, setting := range bi.Settings {
    75  		if setting.Key != "GOFIPS140" {
    76  			continue
    77  		}
    78  		exp := setting.Value
    79  		// Remove the -hash suffix, if any.
    80  		// The version from fips140.Version omits it.
    81  		exp, _, _ = strings.Cut(exp, "-")
    82  		if v := fips140.Version(); v != exp {
    83  			t.Errorf("Version is %q, expected %q", v, exp)
    84  		}
    85  		return
    86  	}
    87  	// Without GOFIPS140, the Version should be "latest".
    88  	if v := fips140.Version(); v != "latest" {
    89  		t.Errorf("Version is %q, expected latest", v)
    90  	}
    91  }
    92  
    93  func TestFIPS140(t *testing.T) {
    94  	moduleStatus(t)
    95  	if boring.Enabled {
    96  		t.Skip("Go+BoringCrypto shims prevent the service indicator from being set")
    97  	}
    98  
    99  	aesKey := make([]byte, 128/8)
   100  	aesIV := make([]byte, aes.BlockSize)
   101  	plaintext := []byte("Go Cryptographic Module TestFIPS140 plaintext...")
   102  	plaintextSHA256 := decodeHex(t, "06b2614e2ef315832b23f5d0ff70294d8ddd3889527dfbe75707fe41da929325")
   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("ML-KEM KeyGen, Encap, Decap", func(t *testing.T) {
   228  		ensureServiceIndicator(t)
   229  		k, err := mlkem.GenerateKey768()
   230  		fatalIfErr(t, err)
   231  
   232  		ss, c := k.EncapsulationKey().Encapsulate()
   233  		t.Logf("ML-KEM encapsulation: %x", c)
   234  
   235  		ss2, err := k.Decapsulate(c)
   236  		fatalIfErr(t, err)
   237  		t.Logf("ML-KEM shared secret: %x", ss)
   238  		if !bytes.Equal(ss, ss2) {
   239  			t.Errorf("ML-KEM round trip failed")
   240  		}
   241  	})
   242  
   243  	var rsaKey *rsa.PrivateKey
   244  	t.Run("RSA KeyGen", func(t *testing.T) {
   245  		ensureServiceIndicator(t)
   246  		var err error
   247  		rsaKey, err = rsa.GenerateKey(rand.Reader, 2048)
   248  		fatalIfErr(t, err)
   249  		t.Log("RSA key generated")
   250  	})
   251  
   252  	t.Run("RSA SigGen, SigVer PKCS 1.5", func(t *testing.T) {
   253  		ensureServiceIndicator(t)
   254  		sig, err := rsa.SignPKCS1v15(rsaKey, "SHA-256", plaintextSHA256)
   255  		fatalIfErr(t, err)
   256  		t.Logf("RSA PKCS1v15 signature: %x", sig)
   257  
   258  		err = rsa.VerifyPKCS1v15(rsaKey.PublicKey(), "SHA-256", plaintextSHA256, sig)
   259  		fatalIfErr(t, err)
   260  	})
   261  
   262  	t.Run("RSA SigGen, SigVer PSS", func(t *testing.T) {
   263  		ensureServiceIndicator(t)
   264  		sig, err := rsa.SignPSS(rand.Reader, rsaKey, sha256.New(), plaintextSHA256, 16)
   265  		fatalIfErr(t, err)
   266  		t.Logf("RSA PSS signature: %x", sig)
   267  
   268  		err = rsa.VerifyPSS(rsaKey.PublicKey(), sha256.New(), plaintextSHA256, sig)
   269  		fatalIfErr(t, err)
   270  	})
   271  
   272  	t.Run("RSA KeyGen w/ small key [NOT APPROVED]", func(t *testing.T) {
   273  		ensureServiceIndicatorFalse(t)
   274  		_, err := rsa.GenerateKey(rand.Reader, 512)
   275  		fatalIfErr(t, err)
   276  		t.Log("RSA key generated")
   277  	})
   278  
   279  	t.Run("KTS IFC OAEP", func(t *testing.T) {
   280  		ensureServiceIndicator(t)
   281  		c, err := rsa.EncryptOAEP(sha256.New(), sha256.New(), rand.Reader, rsaKey.PublicKey(), plaintextSHA256, nil)
   282  		fatalIfErr(t, err)
   283  		t.Logf("RSA OAEP ciphertext: %x", c)
   284  
   285  		out, err := rsa.DecryptOAEP(sha256.New(), sha256.New(), rsaKey, c, nil)
   286  		fatalIfErr(t, err)
   287  		t.Logf("RSA OAEP decrypted plaintext: %x", out)
   288  		if !bytes.Equal(plaintextSHA256, out) {
   289  			t.Errorf("RSA OAEP round trip failed")
   290  		}
   291  	})
   292  
   293  	t.Run("SHA2-224", func(t *testing.T) {
   294  		ensureServiceIndicator(t)
   295  		h := sha256.New224()
   296  		h.Write(plaintext)
   297  		out := h.Sum(nil)
   298  		t.Logf("SHA2-224 output: %x", out)
   299  	})
   300  
   301  	t.Run("SHA2-256", func(t *testing.T) {
   302  		ensureServiceIndicator(t)
   303  		h := sha256.New()
   304  		h.Write(plaintext)
   305  		out := h.Sum(nil)
   306  		t.Logf("SHA2-256 output: %x", out)
   307  	})
   308  
   309  	t.Run("SHA2-384", func(t *testing.T) {
   310  		ensureServiceIndicator(t)
   311  		h := sha512.New384()
   312  		h.Write(plaintext)
   313  		out := h.Sum(nil)
   314  		t.Logf("SHA2-384 output: %x", out)
   315  	})
   316  
   317  	t.Run("SHA2-512", func(t *testing.T) {
   318  		ensureServiceIndicator(t)
   319  		h := sha512.New()
   320  		h.Write(plaintext)
   321  		out := h.Sum(nil)
   322  		t.Logf("SHA2-512 output: %x", out)
   323  	})
   324  
   325  	t.Run("SHA2-512/224", func(t *testing.T) {
   326  		ensureServiceIndicator(t)
   327  		h := sha512.New512_224()
   328  		h.Write(plaintext)
   329  		out := h.Sum(nil)
   330  		t.Logf("SHA2-512/224 output: %x", out)
   331  	})
   332  
   333  	t.Run("SHA2-512/256", func(t *testing.T) {
   334  		ensureServiceIndicator(t)
   335  		h := sha512.New512_256()
   336  		h.Write(plaintext)
   337  		out := h.Sum(nil)
   338  		t.Logf("SHA2-512/256 output: %x", out)
   339  	})
   340  
   341  	t.Run("SHA3-224", func(t *testing.T) {
   342  		ensureServiceIndicator(t)
   343  		h := sha3.New224()
   344  		h.Write(plaintext)
   345  		out := h.Sum(nil)
   346  		t.Logf("SHA3-224 output: %x", out)
   347  	})
   348  
   349  	t.Run("SHA3-256", func(t *testing.T) {
   350  		ensureServiceIndicator(t)
   351  		h := sha3.New256()
   352  		h.Write(plaintext)
   353  		out := h.Sum(nil)
   354  		t.Logf("SHA3-256 output: %x", out)
   355  	})
   356  
   357  	t.Run("SHA3-384", func(t *testing.T) {
   358  		ensureServiceIndicator(t)
   359  		h := sha3.New384()
   360  		h.Write(plaintext)
   361  		out := h.Sum(nil)
   362  		t.Logf("SHA3-384 output: %x", out)
   363  	})
   364  
   365  	t.Run("SHA3-512", func(t *testing.T) {
   366  		ensureServiceIndicator(t)
   367  		h := sha3.New512()
   368  		h.Write(plaintext)
   369  		out := h.Sum(nil)
   370  		t.Logf("SHA3-512 output: %x", out)
   371  	})
   372  
   373  	t.Run("SHAKE-128", func(t *testing.T) {
   374  		ensureServiceIndicator(t)
   375  		h := sha3.NewShake128()
   376  		h.Write(plaintext)
   377  		out := make([]byte, 16)
   378  		h.Read(out)
   379  		t.Logf("SHAKE-128 output: %x", out)
   380  	})
   381  
   382  	t.Run("SHAKE-256", func(t *testing.T) {
   383  		ensureServiceIndicator(t)
   384  		h := sha3.NewShake256()
   385  		h.Write(plaintext)
   386  		out := make([]byte, 16)
   387  		h.Read(out)
   388  		t.Logf("SHAKE-256 output: %x", out)
   389  	})
   390  
   391  	t.Run("cSHAKE-128", func(t *testing.T) {
   392  		ensureServiceIndicator(t)
   393  		h := sha3.NewCShake128(nil, []byte("test"))
   394  		h.Write(plaintext)
   395  		out := make([]byte, 16)
   396  		h.Read(out)
   397  		t.Logf("cSHAKE-128 output: %x", out)
   398  	})
   399  
   400  	t.Run("cSHAKE-256", func(t *testing.T) {
   401  		ensureServiceIndicator(t)
   402  		h := sha3.NewCShake256(nil, []byte("test"))
   403  		h.Write(plaintext)
   404  		out := make([]byte, 16)
   405  		h.Read(out)
   406  		t.Logf("cSHAKE-256 output: %x", out)
   407  	})
   408  
   409  	t.Run("KDA HKDF", func(t *testing.T) {
   410  		ensureServiceIndicator(t)
   411  		key := hkdf.Key(sha256.New, plaintextSHA256, []byte("salt"), "info", 16)
   412  		t.Logf("HKDF key: %x", key)
   413  	})
   414  
   415  	t.Run("KDA OneStepNoCounter", func(t *testing.T) {
   416  		ensureServiceIndicator(t)
   417  		key := hkdf.Extract(sha256.New, plaintextSHA256, []byte("salt"))
   418  		t.Logf("KDA OneStepNoCounter key: %x", key)
   419  	})
   420  
   421  	t.Run("Feedback KDF", func(t *testing.T) {
   422  		ensureServiceIndicator(t)
   423  		key := hkdf.Expand(sha256.New, plaintextSHA256, "info", 16)
   424  		t.Logf("Feedback KDF key: %x", key)
   425  	})
   426  
   427  	t.Run("PBKDF", func(t *testing.T) {
   428  		ensureServiceIndicator(t)
   429  		key, err := pbkdf2.Key(sha256.New, "password", plaintextSHA256, 2, 16)
   430  		fatalIfErr(t, err)
   431  		t.Logf("PBKDF key: %x", key)
   432  	})
   433  
   434  	t.Run("KDF TLS v1.2 CVL", func(t *testing.T) {
   435  		ensureServiceIndicator(t)
   436  		key := tls12.MasterSecret(sha256.New, plaintextSHA256, []byte("test"))
   437  		t.Logf("TLS v1.2 CVL Master Secret: %x", key)
   438  	})
   439  
   440  	t.Run("KDF TLS v1.3 CVL", func(t *testing.T) {
   441  		ensureServiceIndicator(t)
   442  		es := tls13.NewEarlySecret(sha256.New, plaintextSHA256)
   443  		hs := es.HandshakeSecret(plaintextSHA256)
   444  		ms := hs.MasterSecret()
   445  		client := ms.ClientApplicationTrafficSecret(sha256.New())
   446  		server := ms.ServerApplicationTrafficSecret(sha256.New())
   447  		t.Logf("TLS v1.3 CVL Application Traffic Secrets: client %x, server %x", client, server)
   448  	})
   449  }
   450  
   451  func ensureServiceIndicator(t *testing.T) {
   452  	fips140.ResetServiceIndicator()
   453  	t.Cleanup(func() {
   454  		if fips140.ServiceIndicator() {
   455  			t.Logf("Service indicator is set")
   456  		} else {
   457  			t.Errorf("Service indicator is not set")
   458  		}
   459  	})
   460  }
   461  
   462  func ensureServiceIndicatorFalse(t *testing.T) {
   463  	fips140.ResetServiceIndicator()
   464  	t.Cleanup(func() {
   465  		if !fips140.ServiceIndicator() {
   466  			t.Logf("Service indicator is not set")
   467  		} else {
   468  			t.Errorf("Service indicator is set")
   469  		}
   470  	})
   471  }
   472  
   473  func fatalIfErr(t *testing.T, err error) {
   474  	t.Helper()
   475  	if err != nil {
   476  		t.Fatal(err)
   477  	}
   478  }
   479  
   480  func decodeHex(t *testing.T, s string) []byte {
   481  	t.Helper()
   482  	s = strings.ReplaceAll(s, " ", "")
   483  	b, err := hex.DecodeString(s)
   484  	if err != nil {
   485  		t.Fatal(err)
   486  	}
   487  	return b
   488  }
   489  

View as plain text