github.com/mad-day/Yawning-crypto@v0.0.0-20190711051033-5a5f8cca32ec/bsaes/internal/modes/cbc.go (about)

     1  // Copyright (c) 2017 Yawning Angel <yawning at schwanenlied dot me>
     2  //
     3  // Permission is hereby granted, free of charge, to any person obtaining
     4  // a copy of this software and associated documentation files (the
     5  // "Software"), to deal in the Software without restriction, including
     6  // without limitation the rights to use, copy, modify, merge, publish,
     7  // distribute, sublicense, and/or sell copies of the Software, and to
     8  // permit persons to whom the Software is furnished to do so, subject to
     9  // the following conditions:
    10  //
    11  // The above copyright notice and this permission notice shall be
    12  // included in all copies or substantial portions of the Software.
    13  //
    14  // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
    15  // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
    16  // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
    17  // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
    18  // BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
    19  // ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
    20  // CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
    21  // SOFTWARE.
    22  
    23  package modes
    24  
    25  import "crypto/cipher"
    26  
    27  func (m *BlockModesImpl) NewCBCDecrypter(iv []byte) cipher.BlockMode {
    28  	ecb := m.b.(bulkECBAble)
    29  	if len(iv) != ecb.BlockSize() {
    30  		panic("bsaes/NewCBCDecrypter: iv size does not match block size")
    31  	}
    32  
    33  	return newCBCDecImpl(ecb, iv)
    34  }
    35  
    36  type cbcDecImpl struct {
    37  	ecb bulkECBAble
    38  	iv  []byte
    39  	buf []byte
    40  	tmp [blockSize]byte
    41  
    42  	stride int
    43  }
    44  
    45  func (c *cbcDecImpl) BlockSize() int {
    46  	return blockSize
    47  }
    48  
    49  func (c *cbcDecImpl) CryptBlocks(dst, src []byte) {
    50  	sLen := len(src)
    51  	if sLen == 0 {
    52  		return
    53  	}
    54  	n := sLen / blockSize
    55  
    56  	for n >= c.stride { // Stride blocks at a time.
    57  		copy(c.iv[blockSize:], src)
    58  		copy(c.tmp[:], src[(c.stride-1)*blockSize:])
    59  
    60  		c.ecb.BulkDecrypt(c.buf, src)
    61  		for i, v := range c.iv {
    62  			dst[i] = c.buf[i] ^ v
    63  		}
    64  
    65  		copy(c.iv, c.tmp[:])
    66  		dst, src = dst[c.stride*blockSize:], src[c.stride*blockSize:]
    67  		n -= c.stride
    68  	}
    69  	for n > 0 { // Process the remainder one block at a time.
    70  		copy(c.tmp[:], src[:blockSize])
    71  
    72  		c.ecb.Decrypt(c.buf, src[:blockSize])
    73  		for i, v := range c.iv[:blockSize] {
    74  			dst[i] = c.buf[i] ^ v
    75  		}
    76  
    77  		copy(c.iv, c.tmp[:])
    78  		dst, src = dst[blockSize:], src[blockSize:]
    79  		n--
    80  	}
    81  }
    82  
    83  func newCBCDecImpl(ecb bulkECBAble, iv []byte) cipher.BlockMode {
    84  	c := new(cbcDecImpl)
    85  	c.ecb = ecb
    86  	c.stride = ecb.Stride()
    87  	c.iv = make([]byte, c.stride*blockSize)
    88  	copy(c.iv, iv)
    89  	c.buf = make([]byte, c.stride*blockSize)
    90  
    91  	return c
    92  }