github.com/emmansun/gmsm@v0.29.1/sm4/sm4_xts.go (about)

     1  //go:build (amd64 || arm64) && !purego
     2  
     3  package sm4
     4  
     5  import (
     6  	"crypto/cipher"
     7  
     8  	"github.com/emmansun/gmsm/internal/alias"
     9  )
    10  
    11  // Assert that sm4CipherAsm implements the xtsEncAble and xtsDecAble interfaces.
    12  var _ xtsEncAble = (*sm4CipherAsm)(nil)
    13  var _ xtsDecAble = (*sm4CipherAsm)(nil)
    14  
    15  const xtsEncrypt = 1
    16  const xtsDecrypt = 0
    17  
    18  type xts struct {
    19  	b     *sm4CipherAsm
    20  	tweak [BlockSize]byte
    21  	isGB  bool // if true, follows GB/T 17964-2021
    22  	enc   int
    23  }
    24  
    25  func (b *sm4CipherAsm) NewXTSEncrypter(encryptedTweak *[BlockSize]byte, isGB bool) cipher.BlockMode {
    26  	var c xts
    27  	c.b = b
    28  	c.enc = xtsEncrypt
    29  	c.isGB = isGB
    30  	copy(c.tweak[:], encryptedTweak[:])
    31  	return &c
    32  }
    33  
    34  func (b *sm4CipherAsm) NewXTSDecrypter(encryptedTweak *[BlockSize]byte, isGB bool) cipher.BlockMode {
    35  	var c xts
    36  	c.b = b
    37  	c.enc = xtsDecrypt
    38  	c.isGB = isGB
    39  	copy(c.tweak[:], encryptedTweak[:])
    40  	return &c
    41  }
    42  
    43  func (x *xts) BlockSize() int { return BlockSize }
    44  
    45  //go:noescape
    46  func encryptSm4Xts(xk *uint32, tweak *[BlockSize]byte, dst, src []byte)
    47  
    48  //go:noescape
    49  func encryptSm4XtsGB(xk *uint32, tweak *[BlockSize]byte, dst, src []byte)
    50  
    51  //go:noescape
    52  func decryptSm4Xts(xk *uint32, tweak *[BlockSize]byte, dst, src []byte)
    53  
    54  //go:noescape
    55  func decryptSm4XtsGB(xk *uint32, tweak *[BlockSize]byte, dst, src []byte)
    56  
    57  func validateXtsInput(dst, src []byte) {
    58  	if len(dst) < len(src) {
    59  		panic("cipher: dst is smaller than src")
    60  	}
    61  	if len(src) < BlockSize {
    62  		panic("cipher: src length is smaller than the block size")
    63  	}
    64  	if alias.InexactOverlap(dst[:len(src)], src) {
    65  		panic("cipher: invalid buffer overlap")
    66  	}
    67  }
    68  
    69  func (x *xts) CryptBlocks(dst, src []byte) {
    70  	validateXtsInput(dst, src)
    71  	if x.enc == xtsEncrypt {
    72  		if x.isGB {
    73  			encryptSm4XtsGB(&x.b.enc[0], &x.tweak, dst, src)
    74  		} else {
    75  			encryptSm4Xts(&x.b.enc[0], &x.tweak, dst, src)
    76  		}
    77  	} else {
    78  		if x.isGB {
    79  			decryptSm4XtsGB(&x.b.dec[0], &x.tweak, dst, src)
    80  		} else {
    81  			decryptSm4Xts(&x.b.dec[0], &x.tweak, dst, src)
    82  		}	
    83  	}
    84  }