// Copyright 2013 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 ()// GCM represents a Galois Counter Mode with a specific key.typeGCMstruct { cipher aes.Block nonceSize int tagSize intgcmPlatformData}func ( *aes.Block, , int) (*GCM, error) {// This function is outlined to let the allocation happen on the parent stack.returnnewGCM(&GCM{}, , , )}// newGCM is marked go:noinline to avoid it inlining into New, and making New// too complex to inline itself.////go:noinlinefunc newGCM( *GCM, *aes.Block, , int) (*GCM, error) {if < gcmMinimumTagSize || > gcmBlockSize {returnnil, errors.New("cipher: incorrect tag size given to GCM") }if <= 0 {returnnil, errors.New("cipher: the nonce can't have zero length") }if .BlockSize() != gcmBlockSize {returnnil, errors.New("cipher: NewGCM requires 128-bit block cipher") } .cipher = * .nonceSize = .tagSize = initGCM()return , nil}const ( gcmBlockSize = 16 gcmTagSize = 16 gcmMinimumTagSize = 12// NIST SP 800-38D recommends tags with 12 or more bytes. gcmStandardNonceSize = 12)func ( *GCM) () int {return .nonceSize}func ( *GCM) () int {return .tagSize}func ( *GCM) (, , , []byte) []byte {fips140.RecordNonApproved()return .sealAfterIndicator(, , , )}func ( *GCM) (, , , []byte) []byte {iflen() != .nonceSize {panic("crypto/cipher: incorrect nonce length given to GCM") }if .nonceSize == 0 {panic("crypto/cipher: incorrect GCM nonce size") }ifuint64(len()) > uint64((1<<32)-2)*gcmBlockSize {panic("crypto/cipher: message too large for GCM") } , := sliceForAppend(, len()+.tagSize)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") }seal(, , , , )return}var errOpen = errors.New("cipher: message authentication failed")func ( *GCM) (, , , []byte) ([]byte, error) {iflen() != .nonceSize {panic("crypto/cipher: incorrect nonce length given to GCM") }// Sanity check to prevent the authentication from always succeeding if an // implementation leaves tagSize uninitialized, for example.if .tagSize < gcmMinimumTagSize {panic("crypto/cipher: incorrect GCM tag size") }iflen() < .tagSize {returnnil, errOpen }ifuint64(len()) > uint64((1<<32)-2)*gcmBlockSize+uint64(.tagSize) {returnnil, errOpen } , := sliceForAppend(, len()-.tagSize)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()if := open(, , , , ); != nil {// We sometimes decrypt and authenticate concurrently, so we overwrite // dst in the event of a tag mismatch. To be consistent across platforms // and to avoid releasing unauthenticated plaintext, we clear the buffer // in the event of an error.clear()returnnil, }return , nil}// sliceForAppend takes a slice and a requested number of bytes. It returns a// slice with the contents of the given slice followed by that many bytes and a// second slice that aliases into it and contains only the extra bytes. If the// original slice has sufficient capacity then no allocation is performed.func sliceForAppend( []byte, int) (, []byte) {if := len() + ; cap() >= { = [:] } else { = make([]byte, )copy(, ) } = [len():]return}
The pages are generated with Goldsv0.7.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.