package aes
import (
subtleoverlap
)
func ( *[256]byte, []uint32)
func ( *[256]byte, []byte, *[16]byte)
func ( *[256]byte, , []byte, , *[16]byte, []uint32)
func ( *[256]byte, , []byte, , *[16]byte, []uint32)
func ( *[256]byte, , *[16]byte, , uint64)
const (
gcmBlockSize = 16
gcmTagSize = 16
gcmMinimumTagSize = 12
gcmStandardNonceSize = 12
)
var errOpen = errors.New("cipher: message authentication failed")
type aesCipherGCM struct {
aesCipherAsm
}
var _ gcmAble = (*aesCipherGCM)(nil)
func ( *aesCipherGCM) (, int) (cipher.AEAD, error) {
:= &gcmAsm{ks: .enc, nonceSize: , tagSize: }
gcmAesInit(&.productTable, .ks)
return , nil
}
type gcmAsm struct {
ks []uint32
productTable [256]byte
nonceSize int
tagSize int
}
func ( *gcmAsm) () int {
return .nonceSize
}
func ( *gcmAsm) () int {
return .tagSize
}
func ( []byte, int) (, []byte) {
if := len() + ; cap() >= {
= [:]
} else {
= make([]byte, )
copy(, )
}
= [len():]
return
}
func ( *gcmAsm) (, , , []byte) []byte {
if len() != .nonceSize {
panic("crypto/cipher: incorrect nonce length given to GCM")
}
if uint64(len()) > ((1<<32)-2)*BlockSize {
panic("crypto/cipher: message too large for GCM")
}
var , [gcmBlockSize]byte
if len() == gcmStandardNonceSize {
copy([:], )
[gcmBlockSize-1] = 1
} else {
gcmAesData(&.productTable, , &)
gcmAesFinish(&.productTable, &, &, uint64(len()), uint64(0))
}
encryptBlockAsm(len(.ks)/4-1, &.ks[0], &[0], &[0])
var [gcmTagSize]byte
gcmAesData(&.productTable, , &)
, := sliceForAppend(, len()+.tagSize)
if subtleoverlap.InexactOverlap([:len()], ) {
panic("crypto/cipher: invalid buffer overlap")
}
if len() > 0 {
gcmAesEnc(&.productTable, , , &, &, .ks)
}
gcmAesFinish(&.productTable, &, &, uint64(len()), uint64(len()))
copy([len():], [:])
return
}
func ( *gcmAsm) (, , , []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(BlockSize)+uint64(.tagSize) {
return nil, errOpen
}
:= [len()-.tagSize:]
= [:len()-.tagSize]
var , [gcmBlockSize]byte
if len() == gcmStandardNonceSize {
copy([:], )
[gcmBlockSize-1] = 1
} else {
gcmAesData(&.productTable, , &)
gcmAesFinish(&.productTable, &, &, uint64(len()), uint64(0))
}
encryptBlockAsm(len(.ks)/4-1, &.ks[0], &[0], &[0])
var [gcmTagSize]byte
gcmAesData(&.productTable, , &)
, := sliceForAppend(, len())
if subtleoverlap.InexactOverlap(, ) {
panic("crypto/cipher: invalid buffer overlap")
}
if len() > 0 {
gcmAesDec(&.productTable, , , &, &, .ks)
}
gcmAesFinish(&.productTable, &, &, uint64(len()), uint64(len()))
if subtle.ConstantTimeCompare([:.tagSize], ) != 1 {
for := range {
[] = 0
}
return nil, errOpen
}
return , nil
}