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

View as plain text