package gcm
import (
"crypto/internal/fips140/aes"
"crypto/internal/fips140/subtle"
"crypto/internal/fips140deps/cpu"
"crypto/internal/impl"
)
func gcmAesInit(productTable *[256 ]byte , ks []uint32 )
func gcmAesData(productTable *[256 ]byte , data []byte , T *[16 ]byte )
func gcmAesEnc(productTable *[256 ]byte , dst , src []byte , ctr , T *[16 ]byte , ks []uint32 )
func gcmAesDec(productTable *[256 ]byte , dst , src []byte , ctr , T *[16 ]byte , ks []uint32 )
func gcmAesFinish(productTable *[256 ]byte , tagMask , T *[16 ]byte , pLen , dLen uint64 )
var supportsAESGCM = cpu .X86HasAES && cpu .X86HasPCLMULQDQ && cpu .X86HasSSE41 && cpu .X86HasSSSE3 ||
cpu .ARM64HasAES && cpu .ARM64HasPMULL
func init() {
if cpu .AMD64 {
impl .Register ("gcm" , "AES-NI" , &supportsAESGCM )
}
if cpu .ARM64 {
impl .Register ("gcm" , "Armv8.0" , &supportsAESGCM )
}
}
func checkGenericIsExpected() {
if supportsAESGCM {
panic ("gcm: internal error: using generic implementation despite hardware support" )
}
}
type gcmPlatformData struct {
productTable [256 ]byte
}
func initGCM(g *GCM ) {
if !supportsAESGCM {
return
}
gcmAesInit (&g .productTable , aes .EncryptionKeySchedule (&g .cipher ))
}
func seal(out []byte , g *GCM , nonce , plaintext , data []byte ) {
if !supportsAESGCM {
sealGeneric (out , g , nonce , plaintext , data )
return
}
var counter , tagMask [gcmBlockSize ]byte
if len (nonce ) == gcmStandardNonceSize {
copy (counter [:], nonce )
counter [gcmBlockSize -1 ] = 1
} else {
gcmAesData (&g .productTable , nonce , &counter )
gcmAesFinish (&g .productTable , &tagMask , &counter , uint64 (len (nonce )), uint64 (0 ))
}
g .cipher .Encrypt (tagMask [:], counter [:])
var tagOut [gcmTagSize ]byte
gcmAesData (&g .productTable , data , &tagOut )
if len (plaintext ) > 0 {
gcmAesEnc (&g .productTable , out , plaintext , &counter , &tagOut , aes .EncryptionKeySchedule (&g .cipher ))
}
gcmAesFinish (&g .productTable , &tagMask , &tagOut , uint64 (len (plaintext )), uint64 (len (data )))
copy (out [len (plaintext ):], tagOut [:])
}
func open(out []byte , g *GCM , nonce , ciphertext , data []byte ) error {
if !supportsAESGCM {
return openGeneric (out , g , nonce , ciphertext , data )
}
tag := ciphertext [len (ciphertext )-g .tagSize :]
ciphertext = ciphertext [:len (ciphertext )-g .tagSize ]
var counter , tagMask [gcmBlockSize ]byte
if len (nonce ) == gcmStandardNonceSize {
copy (counter [:], nonce )
counter [gcmBlockSize -1 ] = 1
} else {
gcmAesData (&g .productTable , nonce , &counter )
gcmAesFinish (&g .productTable , &tagMask , &counter , uint64 (len (nonce )), uint64 (0 ))
}
g .cipher .Encrypt (tagMask [:], counter [:])
var expectedTag [gcmTagSize ]byte
gcmAesData (&g .productTable , data , &expectedTag )
if len (ciphertext ) > 0 {
gcmAesDec (&g .productTable , out , ciphertext , &counter , &expectedTag , aes .EncryptionKeySchedule (&g .cipher ))
}
gcmAesFinish (&g .productTable , &tagMask , &expectedTag , uint64 (len (ciphertext )), uint64 (len (data )))
if subtle .ConstantTimeCompare (expectedTag [:g .tagSize ], tag ) != 1 {
return errOpen
}
return nil
}
The pages are generated with Golds v0.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 .