gmsm/sm4/sm4_xts.go
2024-03-05 09:47:49 +08:00

85 lines
2.0 KiB
Go

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