//go:build amd64 || arm64 // +build amd64 arm64 package sm4 import ( "crypto/cipher" "golang.org/x/sys/cpu" "xdx.jelly/xgcl/internal/subtle" ) type sm4CipherAsm struct { sm4Cipher } var supportsAES = cpu.X86.HasAES || cpu.ARM64.HasSM4 var supportsGFMUL = cpu.X86.HasPCLMULQDQ || cpu.ARM64.HasPMULL func newCipher(key []byte) (cipher.Block, error) { if !supportsAES { return newCipherGeneric(key) } c := sm4CipherAsm{sm4Cipher{}} expandKeyAsm(key, c.encKey[:], c.decKey[:]) if supportsAES && supportsGFMUL { return &sm4CipherGCM{c}, nil } return &c, nil } func (c *sm4CipherAsm) BlockSize() int { return BlockSize } func (c *sm4CipherAsm) Encrypt(dst, src []byte) { if len(src) < BlockSize { panic("gcl/sm/sm4/Encrypt: input not full block") } if len(dst) < BlockSize { panic("gcl/sm/sm4/Encrypt: output not full block") } if subtle.InexactOverlap(dst[:BlockSize], src[:BlockSize]) { panic("gcl/sm/sm4/Encrypt: invalid buffer overlap") } encryptBlockAsm(c.encKey[:], dst, src) } func (c *sm4CipherAsm) Decrypt(dst, src []byte) { if len(src) < BlockSize { panic("gcl/sm/sm4/Encrypt: input not full block") } if len(dst) < BlockSize { panic("gcl/sm/sm4/Encrypt: output not full block") } if subtle.InexactOverlap(dst[:BlockSize], src[:BlockSize]) { panic("gcl/sm/sm4/Encrypt: invalid buffer overlap") } decryptBlockAsm(c.decKey[:], dst, src) } // expandKey is used by BenchmarkExpand to ensure that the asm implementation // of key expansion is used for the benchmark when it is available. func expandKey(key []byte, enc, dec []uint32) { if supportsAES { expandKeyAsm(key, enc, dec) } else { expandKeyGo(key, enc, dec) } }