// Copyright 2024 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package gcm

import (
	
	
	
	
	
	
	
)

// SealWithRandomNonce encrypts plaintext to out, and writes a random nonce to
// nonce. nonce must be 12 bytes, and out must be 16 bytes longer than plaintext.
// out and plaintext may overlap exactly or not at all. additionalData and out
// must not overlap.
//
// This complies with FIPS 140-3 IG C.H Scenario 2.
//
// Note that this is NOT a [cipher.AEAD].Seal method.
func ( *GCM, , , ,  []byte) {
	if uint64(len()) > uint64((1<<32)-2)*gcmBlockSize {
		panic("crypto/cipher: message too large for GCM")
	}
	if len() != gcmStandardNonceSize {
		panic("crypto/cipher: incorrect nonce length given to GCMWithRandomNonce")
	}
	if len() != len()+gcmTagSize {
		panic("crypto/cipher: incorrect output length given to GCMWithRandomNonce")
	}
	if alias.InexactOverlap(, ) {
		panic("crypto/cipher: invalid buffer overlap of output and input")
	}
	if alias.AnyOverlap(, ) {
		panic("crypto/cipher: invalid buffer overlap of output and additional data")
	}
	fips140.RecordApproved()
	drbg.Read()
	seal(, , , , )
}

// NewGCMWithCounterNonce returns a new AEAD that works like GCM, but enforces
// the construction of deterministic nonces. The nonce must be 96 bits, the
// first 32 bits must be an encoding of the module name, and the last 64 bits
// must be a counter. The starting value of the counter is set on the first call
// to Seal, and each subsequent call must increment it as a big-endian uint64.
// If the counter reaches the starting value minus one, Seal will panic.
//
// This complies with FIPS 140-3 IG C.H Scenario 3.
func ( *aes.Block) (*GCMWithCounterNonce, error) {
	,  := newGCM(&GCM{}, , gcmStandardNonceSize, gcmTagSize)
	if  != nil {
		return nil, 
	}
	return &GCMWithCounterNonce{g: *}, nil
}

// NewGCMForTLS12 returns a new AEAD that works like GCM, but enforces the
// construction of nonces as specified in RFC 5288, Section 3 and RFC 9325,
// Section 7.2.1.
//
// This complies with FIPS 140-3 IG C.H Scenario 1.a.
func ( *aes.Block) (*GCMWithCounterNonce, error) {
	,  := newGCM(&GCM{}, , gcmStandardNonceSize, gcmTagSize)
	if  != nil {
		return nil, 
	}
	// TLS 1.2 counters always start at zero.
	return &GCMWithCounterNonce{g: *, startReady: true}, nil
}

// NewGCMForSSH returns a new AEAD that works like GCM, but enforces the
// construction of nonces as specified in RFC 5647.
//
// This complies with FIPS 140-3 IG C.H Scenario 1.d.
func ( *aes.Block) (*GCMWithCounterNonce, error) {
	,  := newGCM(&GCM{}, , gcmStandardNonceSize, gcmTagSize)
	if  != nil {
		return nil, 
	}
	return &GCMWithCounterNonce{g: *}, nil
}

type GCMWithCounterNonce struct {
	g           GCM
	prefixReady bool
	prefix      uint32
	startReady  bool
	start       uint64
	next        uint64
}

func ( *GCMWithCounterNonce) () int { return gcmStandardNonceSize }

func ( *GCMWithCounterNonce) () int { return gcmTagSize }

// Seal implements the [cipher.AEAD] interface, checking that the nonce prefix
// is stable and that the counter is strictly increasing.
//
// It is not safe for concurrent use.
func ( *GCMWithCounterNonce) (, , ,  []byte) []byte {
	if len() != gcmStandardNonceSize {
		panic("crypto/cipher: incorrect nonce length given to GCM")
	}

	if fips140.Enabled {
		if !.prefixReady {
			// The first invocation sets the fixed prefix.
			.prefixReady = true
			.prefix = byteorder.BEUint32([:4])
		}
		if .prefix != byteorder.BEUint32([:4]) {
			panic("crypto/cipher: GCM nonce prefix changed")
		}

		 := byteorder.BEUint64([len()-8:])
		if !.startReady {
			// The first invocation sets the starting counter, if not fixed.
			.startReady = true
			.start = 
		}
		 -= .start

		// Ensure the counter is strictly increasing.
		if  == math.MaxUint64 {
			panic("crypto/cipher: counter exhausted")
		}
		if  < .next {
			panic("crypto/cipher: counter decreased or remained the same")
		}
		.next =  + 1
	}

	fips140.RecordApproved()
	return .g.sealAfterIndicator(, , , )
}

func ( *GCMWithCounterNonce) (, , ,  []byte) ([]byte, error) {
	fips140.RecordApproved()
	return .g.Open(, , , )
}

// NewGCMWithXORCounterNonce returns a new AEAD that works like GCM, but
// enforces the construction of deterministic nonces. The nonce must be 96 bits,
// the first 32 bits must be an encoding of the module name, and the last 64
// bits must be a counter XOR'd with a fixed value. The module name and XOR mask
// can be set with [GCMWithCounterNonce.SetNoncePrefixAndMask], or they are set
// on the first call to Seal, assuming the counter starts at zero. Each
// subsequent call must increment the counter as a big-endian uint64. If the
// counter reaches 2⁶⁴ minus one, Seal will panic.
//
// This complies with FIPS 140-3 IG C.H Scenario 3.
func ( *aes.Block) (*GCMWithXORCounterNonce, error) {
	,  := newGCM(&GCM{}, , gcmStandardNonceSize, gcmTagSize)
	if  != nil {
		return nil, 
	}
	return &GCMWithXORCounterNonce{g: *}, nil
}

// NewGCMForTLS13 returns a new AEAD that works like GCM, but enforces the
// construction of nonces as specified in RFC 8446, Section 5.3.
//
// This complies with FIPS 140-3 IG C.H Scenario 1.a.
func ( *aes.Block) (*GCMWithXORCounterNonce, error) {
	,  := newGCM(&GCM{}, , gcmStandardNonceSize, gcmTagSize)
	if  != nil {
		return nil, 
	}
	return &GCMWithXORCounterNonce{g: *}, nil
}

// NewGCMForHPKE returns a new AEAD that works like GCM, but enforces the
// construction of nonces as specified in RFC 9180, Section 5.2.
//
// This complies with FIPS 140-3 IG C.H Scenario 5.
func ( *aes.Block) (*GCMWithXORCounterNonce, error) {
	,  := newGCM(&GCM{}, , gcmStandardNonceSize, gcmTagSize)
	if  != nil {
		return nil, 
	}
	return &GCMWithXORCounterNonce{g: *}, nil
}

// NewGCMForQUIC returns a new AEAD that works like GCM, but enforces the
// construction of nonces as specified in RFC 9001, Section 5.3.
//
// Unlike in TLS 1.3, the QUIC nonce counter does not always start at zero, as
// the packet number does not reset on key updates, so the XOR mask must be
// provided explicitly instead of being learned on the first Seal call. Note
// that the nonce passed to Seal must already be XOR'd with the IV, the IV is
// provided here only to allow Seal to enforce that the counter is strictly
// increasing.
//
// This complies with FIPS 140-3 IG C.H Scenario 5.
func ( *aes.Block,  []byte) (*GCMWithXORCounterNonce, error) {
	,  := newGCM(&GCM{}, , gcmStandardNonceSize, gcmTagSize)
	if  != nil {
		return nil, 
	}
	 := &GCMWithXORCounterNonce{g: *}
	if  := .SetNoncePrefixAndMask();  != nil {
		return nil, 
	}
	return , nil
}

type GCMWithXORCounterNonce struct {
	g      GCM
	ready  bool
	prefix uint32
	mask   uint64
	next   uint64
}

// SetNoncePrefixAndMask sets the fixed prefix and XOR mask for the nonces used
// in Seal. It must be called before the first call to Seal.
//
// The first 32 bits of nonce are used as the fixed prefix, and the last 64 bits
// are used as the XOR mask.
//
// Note that Seal expects the nonce to be already XOR'd with the mask. The mask
// is provided here only to allow Seal to enforce that the counter is strictly
// increasing.
func ( *GCMWithXORCounterNonce) ( []byte) error {
	if len() != gcmStandardNonceSize {
		return errors.New("crypto/cipher: incorrect nonce length given to SetNoncePrefixAndMask")
	}
	if .ready {
		return errors.New("crypto/cipher: SetNoncePrefixAndMask called twice or after first Seal")
	}
	.prefix = byteorder.BEUint32([:4])
	.mask = byteorder.BEUint64([4:])
	.ready = true
	return nil
}

func ( *GCMWithXORCounterNonce) () int { return gcmStandardNonceSize }

func ( *GCMWithXORCounterNonce) () int { return gcmTagSize }

// Seal implements the [cipher.AEAD] interface, checking that the nonce prefix
// is stable and that the counter is strictly increasing.
//
// It is not safe for concurrent use.
func ( *GCMWithXORCounterNonce) (, , ,  []byte) []byte {
	if len() != gcmStandardNonceSize {
		panic("crypto/cipher: incorrect nonce length given to GCM")
	}

	if fips140.Enabled {
		 := byteorder.BEUint64([len()-8:])
		if !.ready {
			// In the first call, if [GCMWithXORCounterNonce.SetNoncePrefixAndMask]
			// wasn't used, we assume the counter is zero to learn the XOR mask and
			// fixed prefix.
			.ready = true
			.mask = 
			.prefix = byteorder.BEUint32([:4])
		}
		if .prefix != byteorder.BEUint32([:4]) {
			panic("crypto/cipher: GCM nonce prefix changed")
		}
		 ^= .mask

		// Ensure the counter is strictly increasing.
		if  == math.MaxUint64 {
			panic("crypto/cipher: counter exhausted")
		}
		if  < .next {
			panic("crypto/cipher: counter decreased or remained the same")
		}
		.next =  + 1
	}

	fips140.RecordApproved()
	return .g.sealAfterIndicator(, , , )
}

func ( *GCMWithXORCounterNonce) (, , ,  []byte) ([]byte, error) {
	fips140.RecordApproved()
	return .g.Open(, , , )
}