Source File
gcm.go
Belonging Package
crypto/cipher
package cipher
import (
subtleoverlap
)
NonceSize() int
Overhead() int
type gcmFieldElement struct {
low, high uint64
}
productTable [16]gcmFieldElement
}
func ( Block) (AEAD, error) {
return newGCMWithNonceAndTagSize(, gcmStandardNonceSize, gcmTagSize)
}
func ( Block, int) (AEAD, error) {
return newGCMWithNonceAndTagSize(, , gcmTagSize)
}
func ( Block, int) (AEAD, error) {
return newGCMWithNonceAndTagSize(, gcmStandardNonceSize, )
}
func ( Block, , int) (AEAD, error) {
if < gcmMinimumTagSize || > gcmBlockSize {
return nil, errors.New("cipher: incorrect tag size given to GCM")
}
if <= 0 {
return nil, errors.New("cipher: the nonce can't have zero length, or the security of the key will be immediately compromised")
}
if , := .(gcmAble); {
return .NewGCM(, )
}
if .BlockSize() != gcmBlockSize {
return nil, errors.New("cipher: NewGCM requires 128-bit block cipher")
}
var [gcmBlockSize]byte
.Encrypt([:], [:])
:= &gcm{cipher: , nonceSize: , tagSize: }
:= gcmFieldElement{
binary.BigEndian.Uint64([:8]),
binary.BigEndian.Uint64([8:]),
}
.productTable[reverseBits(1)] =
for := 2; < 16; += 2 {
.productTable[reverseBits()] = gcmDouble(&.productTable[reverseBits(/2)])
.productTable[reverseBits(+1)] = gcmAdd(&.productTable[reverseBits()], &)
}
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 {
if len() != .nonceSize {
panic("crypto/cipher: incorrect nonce length given to GCM")
}
if uint64(len()) > ((1<<32)-2)*uint64(.cipher.BlockSize()) {
panic("crypto/cipher: message too large for GCM")
}
, := sliceForAppend(, len()+.tagSize)
if subtleoverlap.InexactOverlap(, ) {
panic("crypto/cipher: invalid buffer overlap")
}
var , [gcmBlockSize]byte
.deriveCounter(&, )
.cipher.Encrypt([:], [:])
gcmInc32(&)
.counterCrypt(, , &)
var [gcmTagSize]byte
.auth([:], [:len()], , &)
copy([len():], [:])
return
}
var errOpen = errors.New("cipher: message authentication failed")
func ( *gcm) (, , , []byte) ([]byte, error) {
if len() != .nonceSize {
panic("crypto/cipher: incorrect nonce length given to GCM")
if .tagSize < gcmMinimumTagSize {
panic("crypto/cipher: incorrect GCM tag size")
}
if len() < .tagSize {
return nil, errOpen
}
if uint64(len()) > ((1<<32)-2)*uint64(.cipher.BlockSize())+uint64(.tagSize) {
return nil, errOpen
}
:= [len()-.tagSize:]
= [:len()-.tagSize]
var , [gcmBlockSize]byte
.deriveCounter(&, )
.cipher.Encrypt([:], [:])
gcmInc32(&)
var [gcmTagSize]byte
.auth([:], , , &)
, := sliceForAppend(, len())
if subtleoverlap.InexactOverlap(, ) {
panic("crypto/cipher: invalid buffer overlap")
}
for := range {
[] = 0
}
return nil, errOpen
}
.counterCrypt(, , &)
return , nil
}
return gcmFieldElement{.low ^ .low, .high ^ .high}
}
func ( *gcmFieldElement) ( gcmFieldElement) {
:= .high&1 == 1
if {
.low ^= 0xe100000000000000
}
return
}
var gcmReductionTable = []uint16{
0x0000, 0x1c20, 0x3840, 0x2460, 0x7080, 0x6ca0, 0x48c0, 0x54e0,
0xe100, 0xfd20, 0xd940, 0xc560, 0x9180, 0x8da0, 0xa9c0, 0xb5e0,
}
func ( *gcm) ( *gcmFieldElement) {
var gcmFieldElement
for := 0; < 2; ++ {
:= .high
if == 1 {
= .low
}
:= &.productTable[&0xf]
.low ^= .low
.high ^= .high
>>= 4
}
}
* =
}
func ( *gcm) ( *gcmFieldElement, []byte) {
:= (len() >> 4) << 4
.updateBlocks(, [:])
if len() != {
var [gcmBlockSize]byte
copy([:], [:])
.updateBlocks(, [:])
}
}
func ( *gcm) (, []byte, *[gcmBlockSize]byte) {
var [gcmBlockSize]byte
for len() >= gcmBlockSize {
.cipher.Encrypt([:], [:])
gcmInc32()
xorWords(, , [:])
= [gcmBlockSize:]
= [gcmBlockSize:]
}
if len() > 0 {
.cipher.Encrypt([:], [:])
gcmInc32()
xorBytes(, , [:])
}
}
![]() |
The pages are generated with Golds v0.3.2-preview. (GOOS=darwin 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. |