//go:build (amd64 || arm64) && !purego package sm4 import ( "crypto/cipher" "github.com/emmansun/gmsm/internal/alias" ) // Assert that sm4CipherAsm implements the xtsEncAble and xtsDecAble interfaces. var _ xtsEncAble = (*sm4CipherAsm)(nil) var _ xtsDecAble = (*sm4CipherAsm)(nil) const xtsEncrypt = 1 const xtsDecrypt = 0 type xts struct { b *sm4CipherAsm tweak [BlockSize]byte isGB bool // if true, follows GB/T 17964-2021 enc int } func (b *sm4CipherAsm) NewXTSEncrypter(encryptedTweak *[BlockSize]byte, isGB bool) cipher.BlockMode { var c xts c.b = b c.enc = xtsEncrypt c.isGB = isGB copy(c.tweak[:], encryptedTweak[:]) return &c } func (b *sm4CipherAsm) NewXTSDecrypter(encryptedTweak *[BlockSize]byte, isGB bool) cipher.BlockMode { var c xts c.b = b c.enc = xtsDecrypt c.isGB = isGB copy(c.tweak[:], encryptedTweak[:]) return &c } func (x *xts) BlockSize() int { return BlockSize } //go:noescape func encryptSm4Xts(xk *uint32, tweak *[BlockSize]byte, dst, src []byte) //go:noescape func encryptSm4XtsGB(xk *uint32, tweak *[BlockSize]byte, dst, src []byte) //go:noescape func decryptSm4Xts(xk *uint32, tweak *[BlockSize]byte, dst, src []byte) //go:noescape func decryptSm4XtsGB(xk *uint32, tweak *[BlockSize]byte, dst, src []byte) func validateXtsInput(dst, src []byte) { if len(dst) < len(src) { panic("cipher: dst is smaller than src") } if len(src) < BlockSize { panic("cipher: src length is smaller than the block size") } if alias.InexactOverlap(dst[:len(src)], src) { panic("cipher: invalid buffer overlap") } } func (x *xts) CryptBlocks(dst, src []byte) { validateXtsInput(dst, src) if x.enc == xtsEncrypt { if x.isGB { encryptSm4XtsGB(&x.b.enc[0], &x.tweak, dst, src) } else { encryptSm4Xts(&x.b.enc[0], &x.tweak, dst, src) } } else { if x.isGB { decryptSm4XtsGB(&x.b.dec[0], &x.tweak, dst, src) } else { decryptSm4Xts(&x.b.dec[0], &x.tweak, dst, src) } } }