// 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 gcmimport ()// 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) {ifuint64(len()) > uint64((1<<32)-2)*gcmBlockSize {panic("crypto/cipher: message too large for GCM") }iflen() != gcmStandardNonceSize {panic("crypto/cipher: incorrect nonce length given to GCMWithRandomNonce") }iflen() != len()+gcmTagSize {panic("crypto/cipher: incorrect output length given to GCMWithRandomNonce") }ifalias.InexactOverlap(, ) {panic("crypto/cipher: invalid buffer overlap of output and input") }ifalias.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 {returnnil, }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 {returnnil, }// 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 {returnnil, }return &GCMWithCounterNonce{g: *}, nil}typeGCMWithCounterNoncestruct { g GCM prefixReady bool prefix uint32 startReady bool start uint64 next uint64}func ( *GCMWithCounterNonce) () int { returngcmStandardNonceSize }func ( *GCMWithCounterNonce) () int { returngcmTagSize }// 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 {iflen() != gcmStandardNonceSize {panic("crypto/cipher: incorrect nonce length given to GCM") }iffips140.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 {returnnil, }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 {returnnil, }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 {returnnil, }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 {returnnil, } := &GCMWithXORCounterNonce{g: *}if := .SetNoncePrefixAndMask(); != nil {returnnil, }return , nil}typeGCMWithXORCounterNoncestruct { 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 {iflen() != gcmStandardNonceSize {returnerrors.New("crypto/cipher: incorrect nonce length given to SetNoncePrefixAndMask") }if .ready {returnerrors.New("crypto/cipher: SetNoncePrefixAndMask called twice or after first Seal") } .prefix = byteorder.BEUint32([:4]) .mask = byteorder.BEUint64([4:]) .ready = truereturnnil}func ( *GCMWithXORCounterNonce) () int { returngcmStandardNonceSize }func ( *GCMWithXORCounterNonce) () int { returngcmTagSize }// 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 {iflen() != gcmStandardNonceSize {panic("crypto/cipher: incorrect nonce length given to GCM") }iffips140.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(, , , )}
The pages are generated with Goldsv0.8.3-preview. (GOOS=linux GOARCH=amd64)
Golds is a Go 101 project developed by Tapir Liu.
PR and bug reports are welcome and can be submitted to the issue list.
Please follow @zigo_101 (reachable from the left QR code) to get the latest news of Golds.