Files
xgcl/sm/sm4/cipher_asm.go
2026-05-27 23:03:00 +08:00

71 lines
1.6 KiB
Go

//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)
}
}