Source file src/crypto/cipher/gcm_fips140v2.0_test.go

     1  // Copyright 2025 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  //go:build !fips140v1.0
     6  
     7  package cipher_test
     8  
     9  import (
    10  	"crypto/cipher"
    11  	"crypto/internal/cryptotest"
    12  	"crypto/internal/fips140"
    13  	fipsaes "crypto/internal/fips140/aes"
    14  	"crypto/internal/fips140/aes/gcm"
    15  	"encoding/binary"
    16  	"internal/testenv"
    17  	"math"
    18  	"testing"
    19  )
    20  
    21  func TestGCMNoncesFIPSV2(t *testing.T) {
    22  	cryptotest.MustSupportFIPS140(t)
    23  	if !fips140.Enabled {
    24  		cmd := testenv.Command(t, testenv.Executable(t), "-test.run=^TestGCMNoncesFIPSV2$", "-test.v")
    25  		cmd.Env = append(cmd.Environ(), "GODEBUG=fips140=on")
    26  		out, err := cmd.CombinedOutput()
    27  		t.Logf("running with GODEBUG=fips140=on:\n%s", out)
    28  		if err != nil {
    29  			t.Errorf("fips140=on subprocess failed: %v", err)
    30  		}
    31  		return
    32  	}
    33  
    34  	tryNonce := func(aead cipher.AEAD, nonce []byte) bool {
    35  		fips140.ResetServiceIndicator()
    36  		aead.Seal(nil, nonce, []byte("x"), nil)
    37  		return fips140.ServiceIndicator()
    38  	}
    39  	expectOK := func(t *testing.T, aead cipher.AEAD, nonce []byte) {
    40  		t.Helper()
    41  		if !tryNonce(aead, nonce) {
    42  			t.Errorf("expected service indicator true for %x", nonce)
    43  		}
    44  	}
    45  	expectPanic := func(t *testing.T, aead cipher.AEAD, nonce []byte) {
    46  		t.Helper()
    47  		defer func() {
    48  			t.Helper()
    49  			if recover() == nil {
    50  				t.Errorf("expected panic for %x", nonce)
    51  			}
    52  		}()
    53  		tryNonce(aead, nonce)
    54  	}
    55  
    56  	t.Run("NewGCMWithXORCounterNonce", func(t *testing.T) {
    57  		newGCM := func() *gcm.GCMWithXORCounterNonce {
    58  			key := make([]byte, 16)
    59  			block, _ := fipsaes.New(key)
    60  			aead, _ := gcm.NewGCMWithXORCounterNonce(block)
    61  			return aead
    62  		}
    63  		nonce := func(mask []byte, counter uint64) []byte {
    64  			nonce := make([]byte, 12)
    65  			copy(nonce, mask)
    66  			n := binary.BigEndian.AppendUint64(nil, counter)
    67  			for i, b := range n {
    68  				nonce[4+i] ^= b
    69  			}
    70  			return nonce
    71  		}
    72  
    73  		for _, mask := range [][]byte{
    74  			decodeHex(t, "ffffffffffffffffffffffff"),
    75  			decodeHex(t, "aabbccddeeff001122334455"),
    76  			decodeHex(t, "000000000000000000000000"),
    77  		} {
    78  			g := newGCM()
    79  			// Mask is derived from first invocation with zero nonce.
    80  			expectOK(t, g, nonce(mask, 0))
    81  			expectOK(t, g, nonce(mask, 1))
    82  			expectOK(t, g, nonce(mask, 100))
    83  			expectPanic(t, g, nonce(mask, 100))
    84  			expectPanic(t, g, nonce(mask, 99))
    85  			expectOK(t, g, nonce(mask, math.MaxUint64-2))
    86  			expectOK(t, g, nonce(mask, math.MaxUint64-1))
    87  			expectPanic(t, g, nonce(mask, math.MaxUint64))
    88  			expectPanic(t, g, nonce(mask, 0))
    89  
    90  			g = newGCM()
    91  			g.SetNoncePrefixAndMask(mask)
    92  			expectOK(t, g, nonce(mask, 0xFFFFFFFF))
    93  			expectOK(t, g, nonce(mask, math.MaxUint64-2))
    94  			expectOK(t, g, nonce(mask, math.MaxUint64-1))
    95  			expectPanic(t, g, nonce(mask, math.MaxUint64))
    96  			expectPanic(t, g, nonce(mask, 0))
    97  
    98  			g = newGCM()
    99  			g.SetNoncePrefixAndMask(mask)
   100  			expectOK(t, g, nonce(mask, math.MaxUint64-1))
   101  			expectPanic(t, g, nonce(mask, math.MaxUint64))
   102  			expectPanic(t, g, nonce(mask, 0))
   103  		}
   104  	})
   105  }
   106  

View as plain text