gitee.com/ks-custle/core-gm@v0.0.0-20230922171213-b83bdd97b62c/sm4/cbc_cipher_asm.go (about)

     1  //go:build amd64 || arm64
     2  // +build amd64 arm64
     3  
     4  package sm4
     5  
     6  import (
     7  	"crypto/cipher"
     8  
     9  	"gitee.com/ks-custle/core-gm/internal/subtle"
    10  	"gitee.com/ks-custle/core-gm/internal/xor"
    11  )
    12  
    13  // Assert that sm4CipherAsm implements the cbcDecAble interfaces.
    14  var _ cbcDecAble = (*sm4CipherAsm)(nil)
    15  
    16  type cbc struct {
    17  	b   *sm4CipherAsm
    18  	iv  []byte
    19  	tmp []byte
    20  }
    21  
    22  func (sm4c *sm4CipherAsm) NewCBCDecrypter(iv []byte) cipher.BlockMode {
    23  	// fmt.Println("sm4.NewCBCDecrypter in sm4/cbc_cipher_asm.go")
    24  	var c cbc
    25  	c.b = sm4c
    26  	c.iv = make([]byte, BlockSize)
    27  	c.tmp = make([]byte, BlockSize)
    28  	copy(c.iv, iv)
    29  	return &c
    30  }
    31  
    32  func (x *cbc) BlockSize() int { return BlockSize }
    33  
    34  func (x *cbc) CryptBlocks(dst, src []byte) {
    35  	// fmt.Println("sm4.CryptBlocks in sm4/cbc_cipher_asm.go")
    36  	if len(src)%BlockSize != 0 {
    37  		panic("cipher: input not full blocks")
    38  	}
    39  	if len(dst) < len(src) {
    40  		panic("cipher: output smaller than input")
    41  	}
    42  	if subtle.InexactOverlap(dst[:len(src)], src) {
    43  		panic("cipher: invalid buffer overlap")
    44  	}
    45  	if len(src) == 0 {
    46  		return
    47  	}
    48  	end := len(src)
    49  	copy(x.tmp, src[end-BlockSize:end])
    50  	start := end - x.b.blocksSize
    51  	var temp = make([]byte, x.b.blocksSize)
    52  	var batchSrc = make([]byte, x.b.blocksSize)
    53  	for start > 0 {
    54  		x.b.DecryptBlocks(temp, src[start:end])
    55  		for i := 0; i < x.b.batchBlocks; i++ {
    56  			xor.XorBytes(dst[end-(i+1)*BlockSize:end-i*BlockSize], temp[x.b.blocksSize-(i+1)*BlockSize:x.b.blocksSize-i*BlockSize], src[end-(i+2)*BlockSize:end-(i+1)*BlockSize])
    57  		}
    58  		end = start
    59  		start -= x.b.blocksSize
    60  	}
    61  
    62  	copy(batchSrc, src[:end])
    63  	x.b.DecryptBlocks(temp, batchSrc)
    64  	count := end / BlockSize
    65  	for i := count; i > 1; i-- {
    66  		xor.XorBytes(dst[end-BlockSize:end], temp[end-BlockSize:end], src[end-2*BlockSize:end-BlockSize])
    67  		end -= BlockSize
    68  	}
    69  	xor.XorBytes(dst[0:end], temp[0:end], x.iv[:])
    70  	// Set the new iv to the first block we copied earlier.
    71  	x.iv, x.tmp = x.tmp, x.iv
    72  }
    73  
    74  func (x *cbc) SetIV(iv []byte) {
    75  	if len(iv) != BlockSize {
    76  		panic("cipher: incorrect length IV")
    77  	}
    78  	copy(x.iv[:], iv)
    79  }