// Copyright 2015 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.//go:build amd64 || arm64package aesimport (subtleoverlap)// The following functions are defined in gcm_*.s.//go:noescapefunc gcmAesInit( *[256]byte, []uint32)//go:noescapefunc gcmAesData( *[256]byte, []byte, *[16]byte)//go:noescapefunc gcmAesEnc( *[256]byte, , []byte, , *[16]byte, []uint32)//go:noescapefunc gcmAesDec( *[256]byte, , []byte, , *[16]byte, []uint32)//go:noescapefunc gcmAesFinish( *[256]byte, , *[16]byte, , uint64)const ( gcmBlockSize = 16 gcmTagSize = 16 gcmMinimumTagSize = 12// NIST SP 800-38D recommends tags with 12 or more bytes. gcmStandardNonceSize = 12)var errOpen = errors.New("cipher: message authentication failed")// aesCipherGCM implements crypto/cipher.gcmAble so that crypto/cipher.NewGCM// will use the optimised implementation in this file when possible. Instances// of this type only exist when hasGCMAsm returns true.type aesCipherGCM struct {aesCipherAsm}// Assert that aesCipherGCM implements the gcmAble interface.var _ gcmAble = (*aesCipherGCM)(nil)// NewGCM returns the AES cipher wrapped in Galois Counter Mode. This is only// called by crypto/cipher.NewGCM via the gcmAble interface.func ( *aesCipherGCM) (, int) (cipher.AEAD, error) { := &gcmAsm{ks: .enc, nonceSize: , tagSize: }gcmAesInit(&.productTable, .ks)return , nil}type gcmAsm struct {// ks is the key schedule, the length of which depends on the size of // the AES key. ks []uint32// productTable contains pre-computed multiples of the binary-field // element used in GHASH. productTable [256]byte// nonceSize contains the expected size of the nonce, in bytes. nonceSize int// tagSize contains the size of the tag, in bytes. tagSize int}func ( *gcmAsm) () int {return .nonceSize}func ( *gcmAsm) () int {return .tagSize}// 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}// Seal encrypts and authenticates plaintext. See the cipher.AEAD interface for// details.func ( *gcmAsm) (, , , []byte) []byte {iflen() != .nonceSize {panic("crypto/cipher: incorrect nonce length given to GCM") }ifuint64(len()) > ((1<<32)-2)*BlockSize {panic("crypto/cipher: message too large for GCM") }var , [gcmBlockSize]byteiflen() == gcmStandardNonceSize {// Init counter to nonce||1copy([:], ) [gcmBlockSize-1] = 1 } else {// Otherwise counter = GHASH(nonce)gcmAesData(&.productTable, , &)gcmAesFinish(&.productTable, &, &, uint64(len()), uint64(0)) }encryptBlockAsm(len(.ks)/4-1, &.ks[0], &[0], &[0])var [gcmTagSize]bytegcmAesData(&.productTable, , &) , := sliceForAppend(, len()+.tagSize)ifsubtleoverlap.InexactOverlap([:len()], ) {panic("crypto/cipher: invalid buffer overlap") }iflen() > 0 {gcmAesEnc(&.productTable, , , &, &, .ks) }gcmAesFinish(&.productTable, &, &, uint64(len()), uint64(len()))copy([len():], [:])return}// Open authenticates and decrypts ciphertext. See the cipher.AEAD interface// for details.func ( *gcmAsm) (, , , []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()) > ((1<<32)-2)*uint64(BlockSize)+uint64(.tagSize) {returnnil, errOpen } := [len()-.tagSize:] = [:len()-.tagSize]// See GCM spec, section 7.1.var , [gcmBlockSize]byteiflen() == gcmStandardNonceSize {// Init counter to nonce||1copy([:], ) [gcmBlockSize-1] = 1 } else {// Otherwise counter = GHASH(nonce)gcmAesData(&.productTable, , &)gcmAesFinish(&.productTable, &, &, uint64(len()), uint64(0)) }encryptBlockAsm(len(.ks)/4-1, &.ks[0], &[0], &[0])var [gcmTagSize]bytegcmAesData(&.productTable, , &) , := sliceForAppend(, len())ifsubtleoverlap.InexactOverlap(, ) {panic("crypto/cipher: invalid buffer overlap") }iflen() > 0 {gcmAesDec(&.productTable, , , &, &, .ks) }gcmAesFinish(&.productTable, &, &, uint64(len()), uint64(len()))ifsubtle.ConstantTimeCompare([:.tagSize], ) != 1 {for := range { [] = 0 }returnnil, errOpen }return , nil}
The pages are generated with Goldsv0.4.5. (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 @Go100and1 (reachable from the left QR code) to get the latest news of Golds.