github.com/hxx258456/ccgo@v0.0.5-0.20230213014102-48b35f46f66f/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 "github.com/hxx258456/ccgo/internal/subtle" 10 "github.com/hxx258456/ccgo/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 }