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/debug"
    40  	"strings"
    41  	"testing"
    42  )
    43  
    44  func moduleStatus(t *testing.T) {
    45  	if fips140.Enabled {
    46  		t.Log("FIPS 140-3 mode enabled")
    47  	} else {
    48  		t.Log("FIPS 140-3 mode not enabled")
    49  	}
    50  
    51  	t.Logf("Module name: %s", fips140.Name())
    52  	t.Logf("Module version: %s", fips140.Version())
    53  
    54  	if noPAAPAI {
    55  		t.Log("PAA/PAI disabled")
    56  	} else {
    57  		t.Log("PAA/PAI enabled")
    58  	}
    59  
    60  	if check.Verified {
    61  		t.Log("FIPS 140-3 integrity self-check succeeded")
    62  	} else {
    63  		t.Log("FIPS 140-3 integrity self-check not succeeded")
    64  	}
    65  }
    66  
    67  func TestVersion(t *testing.T) {
    68  	bi, ok := debug.ReadBuildInfo()
    69  	if !ok {
    70  		t.Skip("no build info")
    71  	}
    72  	for _, setting := range bi.Settings {
    73  		if setting.Key != "GOFIPS140" {
    74  			continue
    75  		}
    76  		exp := setting.Value
    77  		if exp == "v1.0.0" {
    78  			// Unfortunately we enshrined the version of the first module as
    79  			// v1.0 before deciding to go for full versions.
    80  			exp = "v1.0"
    81  		}
    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  	t.Run("AES-CTR", func(t *testing.T) {
   107  		ensureServiceIndicator(t)
   108  		ctr := aes.NewCTR(aesBlock, aesIV)
   109  		ciphertext := make([]byte, len(plaintext))
   110  		ctr.XORKeyStream(ciphertext, plaintext)
   111  		t.Logf("AES-CTR ciphertext: %x", ciphertext)
   112  		out := make([]byte, len(plaintext))
   113  		ctr = aes.NewCTR(aesBlock, aesIV)
   114  		ctr.XORKeyStream(out, ciphertext)
   115  		t.Logf("AES-CTR decrypted plaintext: %s", out)
   116  		if !bytes.Equal(plaintext, out) {
   117  			t.Errorf("AES-CTR round trip failed")
   118  		}
   119  	})
   120  
   121  	t.Run("AES-CBC", func(t *testing.T) {
   122  		ensureServiceIndicator(t)
   123  		cbcEnc := aes.NewCBCEncrypter(aesBlock, [16]byte(aesIV))
   124  		ciphertext := make([]byte, len(plaintext))
   125  		cbcEnc.CryptBlocks(ciphertext, plaintext)
   126  		t.Logf("AES-CBC ciphertext: %x", ciphertext)
   127  		cbcDec := aes.NewCBCDecrypter(aesBlock, [16]byte(aesIV))
   128  		out := make([]byte, len(plaintext))
   129  		cbcDec.CryptBlocks(out, ciphertext)
   130  		t.Logf("AES-CBC decrypted plaintext: %s", out)
   131  		if !bytes.Equal(plaintext, out) {
   132  			t.Errorf("AES-CBC round trip failed")
   133  		}
   134  	})
   135  
   136  	t.Run("AES-GCM", func(t *testing.T) {
   137  		ensureServiceIndicator(t)
   138  		g, err := gcm.New(aesBlock, 12, 16)
   139  		fatalIfErr(t, err)
   140  		nonce := make([]byte, 12)
   141  		ciphertext := make([]byte, len(plaintext)+g.Overhead())
   142  		gcm.SealWithRandomNonce(g, nonce, ciphertext, plaintext, nil)
   143  		t.Logf("AES-GCM ciphertext: %x", ciphertext)
   144  		out, err := g.Open(nil, nonce, ciphertext, nil)
   145  		fatalIfErr(t, err)
   146  		t.Logf("AES-GCM decrypted plaintext: %s", out)
   147  		if !bytes.Equal(plaintext, out) {
   148  			t.Errorf("AES-GCM round trip failed")
   149  		}
   150  	})
   151  
   152  	t.Run("Counter KDF", func(t *testing.T) {
   153  		ensureServiceIndicator(t)
   154  		k := gcm.NewCounterKDF(aesBlock)
   155  		context := [12]byte{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12}
   156  		key := k.DeriveKey(0x01, context)
   157  		t.Logf("Counter KDF key: %x", key)
   158  	})
   159  
   160  	t.Run("KAS-ECC-SSC ephemeralUnified", func(t *testing.T) {
   161  		ensureServiceIndicator(t)
   162  		k, err := ecdh.GenerateKey(ecdh.P256(), rand.Reader)
   163  		fatalIfErr(t, err)
   164  		pk := k.PublicKey()
   165  		shared, err := ecdh.ECDH(ecdh.P256(), k, pk)
   166  		fatalIfErr(t, err)
   167  		t.Logf("KAS-ECC-SSC shared secret: %x", shared)
   168  	})
   169  
   170  	t.Run("ECDSA KeyGen, SigGen, SigVer", func(t *testing.T) {
   171  		ensureServiceIndicator(t)
   172  		k, err := ecdsa.GenerateKey(ecdsa.P256(), rand.Reader)
   173  		fatalIfErr(t, err)
   174  
   175  		sig, err := ecdsa.Sign(ecdsa.P256(), sha256.New, k, rand.Reader, plaintextSHA256)
   176  		fatalIfErr(t, err)
   177  		t.Logf("ECDSA signature: %x", sig)
   178  		err = ecdsa.Verify(ecdsa.P256(), k.PublicKey(), plaintextSHA256, sig)
   179  		if err != nil {
   180  			t.Errorf("ECDSA signature verification failed")
   181  		}
   182  
   183  		sig, err = ecdsa.SignDeterministic(ecdsa.P256(), sha256.New, k, plaintextSHA256)
   184  		fatalIfErr(t, err)
   185  		t.Logf("ECDSA deterministic signature: %x", sig)
   186  		err = ecdsa.Verify(ecdsa.P256(), k.PublicKey(), plaintextSHA256, sig)
   187  		if err != nil {
   188  			t.Errorf("ECDSA deterministic signature verification failed")
   189  		}
   190  	})
   191  
   192  	t.Run("EDDSA KeyGen, SigGen, SigVer", func(t *testing.T) {
   193  		ensureServiceIndicator(t)
   194  		k, err := ed25519.GenerateKey()
   195  		fatalIfErr(t, err)
   196  
   197  		sig := ed25519.Sign(k, plaintext)
   198  		t.Logf("EDDSA signature: %x", sig)
   199  
   200  		pk, err := ed25519.NewPublicKey(k.PublicKey())
   201  		fatalIfErr(t, err)
   202  		err = ed25519.Verify(pk, plaintext, sig)
   203  		if err != nil {
   204  			t.Errorf("EDDSA signature verification failed")
   205  		}
   206  	})
   207  
   208  	t.Run("ctrDRBG", func(t *testing.T) {
   209  		ensureServiceIndicator(t)
   210  		r := drbg.NewCounter((*[48]byte)(plaintext))
   211  		r.Reseed((*[48]byte)(plaintext), (*[48]byte)(plaintext))
   212  		out := make([]byte, 16)
   213  		r.Generate(out, (*[48]byte)(plaintext))
   214  		t.Logf("ctrDRBG output: %x", out)
   215  	})
   216  
   217  	t.Run("HMAC", func(t *testing.T) {
   218  		ensureServiceIndicator(t)
   219  		h := hmac.New(sha256.New, plaintext)
   220  		h.Write(plaintext)
   221  		out := h.Sum(nil)
   222  		t.Logf("HMAC output: %x", out)
   223  	})
   224  
   225  	t.Run("ML-KEM KeyGen, Encap, Decap", func(t *testing.T) {
   226  		ensureServiceIndicator(t)
   227  		k, err := mlkem.GenerateKey768()
   228  		fatalIfErr(t, err)
   229  
   230  		ss, c := k.EncapsulationKey().Encapsulate()
   231  		t.Logf("ML-KEM encapsulation: %x", c)
   232  
   233  		ss2, err := k.Decapsulate(c)
   234  		fatalIfErr(t, err)
   235  		t.Logf("ML-KEM shared secret: %x", ss)
   236  		if !bytes.Equal(ss, ss2) {
   237  			t.Errorf("ML-KEM round trip failed")
   238  		}
   239  	})
   240  
   241  	var rsaKey *rsa.PrivateKey
   242  	t.Run("RSA KeyGen", func(t *testing.T) {
   243  		ensureServiceIndicator(t)
   244  		var err error
   245  		rsaKey, err = rsa.GenerateKey(rand.Reader, 2048)
   246  		fatalIfErr(t, err)
   247  		t.Log("RSA key generated")
   248  	})
   249  
   250  	t.Run("RSA SigGen, SigVer PKCS 1.5", func(t *testing.T) {
   251  		ensureServiceIndicator(t)
   252  		sig, err := rsa.SignPKCS1v15(rsaKey, "SHA-256", plaintextSHA256)
   253  		fatalIfErr(t, err)
   254  		t.Logf("RSA PKCS1v15 signature: %x", sig)
   255  
   256  		err = rsa.VerifyPKCS1v15(rsaKey.PublicKey(), "SHA-256", plaintextSHA256, sig)
   257  		fatalIfErr(t, err)
   258  	})
   259  
   260  	t.Run("RSA SigGen, SigVer PSS", func(t *testing.T) {
   261  		ensureServiceIndicator(t)
   262  		sig, err := rsa.SignPSS(rand.Reader, rsaKey, sha256.New(), plaintextSHA256, 16)
   263  		fatalIfErr(t, err)
   264  		t.Logf("RSA PSS signature: %x", sig)
   265  
   266  		err = rsa.VerifyPSS(rsaKey.PublicKey(), sha256.New(), plaintextSHA256, sig)
   267  		fatalIfErr(t, err)
   268  	})
   269  
   270  	t.Run("RSA KeyGen w/ small key [NOT APPROVED]", func(t *testing.T) {
   271  		ensureServiceIndicatorFalse(t)
   272  		_, err := rsa.GenerateKey(rand.Reader, 512)
   273  		fatalIfErr(t, err)
   274  		t.Log("RSA key generated")
   275  	})
   276  
   277  	t.Run("KTS IFC OAEP", func(t *testing.T) {
   278  		ensureServiceIndicator(t)
   279  		c, err := rsa.EncryptOAEP(sha256.New(), sha256.New(), rand.Reader, rsaKey.PublicKey(), plaintextSHA256, nil)
   280  		fatalIfErr(t, err)
   281  		t.Logf("RSA OAEP ciphertext: %x", c)
   282  
   283  		out, err := rsa.DecryptOAEP(sha256.New(), sha256.New(), rsaKey, c, nil)
   284  		fatalIfErr(t, err)
   285  		t.Logf("RSA OAEP decrypted plaintext: %x", out)
   286  		if !bytes.Equal(plaintextSHA256, out) {
   287  			t.Errorf("RSA OAEP round trip failed")
   288  		}
   289  	})
   290  
   291  	t.Run("SHA2-224", func(t *testing.T) {
   292  		ensureServiceIndicator(t)
   293  		h := sha256.New224()
   294  		h.Write(plaintext)
   295  		out := h.Sum(nil)
   296  		t.Logf("SHA2-224 output: %x", out)
   297  	})
   298  
   299  	t.Run("SHA2-256", func(t *testing.T) {
   300  		ensureServiceIndicator(t)
   301  		h := sha256.New()
   302  		h.Write(plaintext)
   303  		out := h.Sum(nil)
   304  		t.Logf("SHA2-256 output: %x", out)
   305  	})
   306  
   307  	t.Run("SHA2-384", func(t *testing.T) {
   308  		ensureServiceIndicator(t)
   309  		h := sha512.New384()
   310  		h.Write(plaintext)
   311  		out := h.Sum(nil)
   312  		t.Logf("SHA2-384 output: %x", out)
   313  	})
   314  
   315  	t.Run("SHA2-512", func(t *testing.T) {
   316  		ensureServiceIndicator(t)
   317  		h := sha512.New()
   318  		h.Write(plaintext)
   319  		out := h.Sum(nil)
   320  		t.Logf("SHA2-512 output: %x", out)
   321  	})
   322  
   323  	t.Run("SHA2-512/224", func(t *testing.T) {
   324  		ensureServiceIndicator(t)
   325  		h := sha512.New512_224()
   326  		h.Write(plaintext)
   327  		out := h.Sum(nil)
   328  		t.Logf("SHA2-512/224 output: %x", out)
   329  	})
   330  
   331  	t.Run("SHA2-512/256", func(t *testing.T) {
   332  		ensureServiceIndicator(t)
   333  		h := sha512.New512_256()
   334  		h.Write(plaintext)
   335  		out := h.Sum(nil)
   336  		t.Logf("SHA2-512/256 output: %x", out)
   337  	})
   338  
   339  	t.Run("SHA3-224", func(t *testing.T) {
   340  		ensureServiceIndicator(t)
   341  		h := sha3.New224()
   342  		h.Write(plaintext)
   343  		out := h.Sum(nil)
   344  		t.Logf("SHA3-224 output: %x", out)
   345  	})
   346  
   347  	t.Run("SHA3-256", func(t *testing.T) {
   348  		ensureServiceIndicator(t)
   349  		h := sha3.New256()
   350  		h.Write(plaintext)
   351  		out := h.Sum(nil)
   352  		t.Logf("SHA3-256 output: %x", out)
   353  	})
   354  
   355  	t.Run("SHA3-384", func(t *testing.T) {
   356  		ensureServiceIndicator(t)
   357  		h := sha3.New384()
   358  		h.Write(plaintext)
   359  		out := h.Sum(nil)
   360  		t.Logf("SHA3-384 output: %x", out)
   361  	})
   362  
   363  	t.Run("SHA3-512", func(t *testing.T) {
   364  		ensureServiceIndicator(t)
   365  		h := sha3.New512()
   366  		h.Write(plaintext)
   367  		out := h.Sum(nil)
   368  		t.Logf("SHA3-512 output: %x", out)
   369  	})
   370  
   371  	t.Run("SHAKE-128", func(t *testing.T) {
   372  		ensureServiceIndicator(t)
   373  		h := sha3.NewShake128()
   374  		h.Write(plaintext)
   375  		out := make([]byte, 16)
   376  		h.Read(out)
   377  		t.Logf("SHAKE-128 output: %x", out)
   378  	})
   379  
   380  	t.Run("SHAKE-256", func(t *testing.T) {
   381  		ensureServiceIndicator(t)
   382  		h := sha3.NewShake256()
   383  		h.Write(plaintext)
   384  		out := make([]byte, 16)
   385  		h.Read(out)
   386  		t.Logf("SHAKE-256 output: %x", out)
   387  	})
   388  
   389  	t.Run("cSHAKE-128", func(t *testing.T) {
   390  		ensureServiceIndicator(t)
   391  		h := sha3.NewCShake128(nil, []byte("test"))
   392  		h.Write(plaintext)
   393  		out := make([]byte, 16)
   394  		h.Read(out)
   395  		t.Logf("cSHAKE-128 output: %x", out)
   396  	})
   397  
   398  	t.Run("cSHAKE-256", func(t *testing.T) {
   399  		ensureServiceIndicator(t)
   400  		h := sha3.NewCShake256(nil, []byte("test"))
   401  		h.Write(plaintext)
   402  		out := make([]byte, 16)
   403  		h.Read(out)
   404  		t.Logf("cSHAKE-256 output: %x", out)
   405  	})
   406  
   407  	t.Run("KDA HKDF", func(t *testing.T) {
   408  		ensureServiceIndicator(t)
   409  		key := hkdf.Key(sha256.New, plaintextSHA256, []byte("salt"), "info", 16)
   410  		t.Logf("HKDF key: %x", key)
   411  	})
   412  
   413  	t.Run("KDA OneStepNoCounter", func(t *testing.T) {
   414  		ensureServiceIndicator(t)
   415  		key := hkdf.Extract(sha256.New, plaintextSHA256, []byte("salt"))
   416  		t.Logf("KDA OneStepNoCounter key: %x", key)
   417  	})
   418  
   419  	t.Run("Feedback KDF", func(t *testing.T) {
   420  		ensureServiceIndicator(t)
   421  		key := hkdf.Expand(sha256.New, plaintextSHA256, "info", 16)
   422  		t.Logf("Feedback KDF key: %x", key)
   423  	})
   424  
   425  	t.Run("PBKDF", func(t *testing.T) {
   426  		ensureServiceIndicator(t)
   427  		key, err := pbkdf2.Key(sha256.New, "password", plaintextSHA256, 2, 16)
   428  		fatalIfErr(t, err)
   429  		t.Logf("PBKDF key: %x", key)
   430  	})
   431  
   432  	t.Run("KDF TLS v1.2 CVL", func(t *testing.T) {
   433  		ensureServiceIndicator(t)
   434  		key := tls12.MasterSecret(sha256.New, plaintextSHA256, []byte("test"))
   435  		t.Logf("TLS v1.2 CVL Master Secret: %x", key)
   436  	})
   437  
   438  	t.Run("KDF TLS v1.3 CVL", func(t *testing.T) {
   439  		ensureServiceIndicator(t)
   440  		es := tls13.NewEarlySecret(sha256.New, plaintextSHA256)
   441  		hs := es.HandshakeSecret(plaintextSHA256)
   442  		ms := hs.MasterSecret()
   443  		client := ms.ClientApplicationTrafficSecret(sha256.New())
   444  		server := ms.ServerApplicationTrafficSecret(sha256.New())
   445  		t.Logf("TLS v1.3 CVL Application Traffic Secrets: client %x, server %x", client, server)
   446  	})
   447  }
   448  
   449  func ensureServiceIndicator(t *testing.T) {
   450  	fips140.ResetServiceIndicator()
   451  	t.Cleanup(func() {
   452  		if fips140.ServiceIndicator() {
   453  			t.Logf("Service indicator is set")
   454  		} else {
   455  			t.Errorf("Service indicator is not set")
   456  		}
   457  	})
   458  }
   459  
   460  func ensureServiceIndicatorFalse(t *testing.T) {
   461  	fips140.ResetServiceIndicator()
   462  	t.Cleanup(func() {
   463  		if !fips140.ServiceIndicator() {
   464  			t.Logf("Service indicator is not set")
   465  		} else {
   466  			t.Errorf("Service indicator is set")
   467  		}
   468  	})
   469  }
   470  
   471  func fatalIfErr(t *testing.T, err error) {
   472  	t.Helper()
   473  	if err != nil {
   474  		t.Fatal(err)
   475  	}
   476  }
   477  
   478  func decodeHex(t *testing.T, s string) []byte {
   479  	t.Helper()
   480  	s = strings.ReplaceAll(s, " ", "")
   481  	b, err := hex.DecodeString(s)
   482  	if err != nil {
   483  		t.Fatal(err)
   484  	}
   485  	return b
   486  }
   487  

View as plain text