Black Lives Matter. Support the Equal Justice Initiative.

Source file src/crypto/cipher/cbc.go

Documentation: crypto/cipher

     1  // Copyright 2009 The Go Authors. All rights reserved.
     2  // Use of this source code is governed by a BSD-style
     3  // license that can be found in the LICENSE file.
     4  
     5  // Cipher block chaining (CBC) mode.
     6  
     7  // CBC provides confidentiality by xoring (chaining) each plaintext block
     8  // with the previous ciphertext block before applying the block cipher.
     9  
    10  // See NIST SP 800-38A, pp 10-11
    11  
    12  package cipher
    13  
    14  import "crypto/internal/subtle"
    15  
    16  type cbc struct {
    17  	b         Block
    18  	blockSize int
    19  	iv        []byte
    20  	tmp       []byte
    21  }
    22  
    23  func newCBC(b Block, iv []byte) *cbc {
    24  	return &cbc{
    25  		b:         b,
    26  		blockSize: b.BlockSize(),
    27  		iv:        dup(iv),
    28  		tmp:       make([]byte, b.BlockSize()),
    29  	}
    30  }
    31  
    32  type cbcEncrypter cbc
    33  
    34  // cbcEncAble is an interface implemented by ciphers that have a specific
    35  // optimized implementation of CBC encryption, like crypto/aes.
    36  // NewCBCEncrypter will check for this interface and return the specific
    37  // BlockMode if found.
    38  type cbcEncAble interface {
    39  	NewCBCEncrypter(iv []byte) BlockMode
    40  }
    41  
    42  // NewCBCEncrypter returns a BlockMode which encrypts in cipher block chaining
    43  // mode, using the given Block. The length of iv must be the same as the
    44  // Block's block size.
    45  func NewCBCEncrypter(b Block, iv []byte) BlockMode {
    46  	if len(iv) != b.BlockSize() {
    47  		panic("cipher.NewCBCEncrypter: IV length must equal block size")
    48  	}
    49  	if cbc, ok := b.(cbcEncAble); ok {
    50  		return cbc.NewCBCEncrypter(iv)
    51  	}
    52  	return (*cbcEncrypter)(newCBC(b, iv))
    53  }
    54  
    55  func (x *cbcEncrypter) BlockSize() int { return x.blockSize }
    56  
    57  func (x *cbcEncrypter) CryptBlocks(dst, src []byte) {
    58  	if len(src)%x.blockSize != 0 {
    59  		panic("crypto/cipher: input not full blocks")
    60  	}
    61  	if len(dst) < len(src) {
    62  		panic("crypto/cipher: output smaller than input")
    63  	}
    64  	if subtle.InexactOverlap(dst[:len(src)], src) {
    65  		panic("crypto/cipher: invalid buffer overlap")
    66  	}
    67  
    68  	iv := x.iv
    69  
    70  	for len(src) > 0 {
    71  		// Write the xor to dst, then encrypt in place.
    72  		xorBytes(dst[:x.blockSize], src[:x.blockSize], iv)
    73  		x.b.Encrypt(dst[:x.blockSize], dst[:x.blockSize])
    74  
    75  		// Move to the next block with this block as the next iv.
    76  		iv = dst[:x.blockSize]
    77  		src = src[x.blockSize:]
    78  		dst = dst[x.blockSize:]
    79  	}
    80  
    81  	// Save the iv for the next CryptBlocks call.
    82  	copy(x.iv, iv)
    83  }
    84  
    85  func (x *cbcEncrypter) SetIV(iv []byte) {
    86  	if len(iv) != len(x.iv) {
    87  		panic("cipher: incorrect length IV")
    88  	}
    89  	copy(x.iv, iv)
    90  }
    91  
    92  type cbcDecrypter cbc
    93  
    94  // cbcDecAble is an interface implemented by ciphers that have a specific
    95  // optimized implementation of CBC decryption, like crypto/aes.
    96  // NewCBCDecrypter will check for this interface and return the specific
    97  // BlockMode if found.
    98  type cbcDecAble interface {
    99  	NewCBCDecrypter(iv []byte) BlockMode
   100  }
   101  
   102  // NewCBCDecrypter returns a BlockMode which decrypts in cipher block chaining
   103  // mode, using the given Block. The length of iv must be the same as the
   104  // Block's block size and must match the iv used to encrypt the data.
   105  func NewCBCDecrypter(b Block, iv []byte) BlockMode {
   106  	if len(iv) != b.BlockSize() {
   107  		panic("cipher.NewCBCDecrypter: IV length must equal block size")
   108  	}
   109  	if cbc, ok := b.(cbcDecAble); ok {
   110  		return cbc.NewCBCDecrypter(iv)
   111  	}
   112  	return (*cbcDecrypter)(newCBC(b, iv))
   113  }
   114  
   115  func (x *cbcDecrypter) BlockSize() int { return x.blockSize }
   116  
   117  func (x *cbcDecrypter) CryptBlocks(dst, src []byte) {
   118  	if len(src)%x.blockSize != 0 {
   119  		panic("crypto/cipher: input not full blocks")
   120  	}
   121  	if len(dst) < len(src) {
   122  		panic("crypto/cipher: output smaller than input")
   123  	}
   124  	if subtle.InexactOverlap(dst[:len(src)], src) {
   125  		panic("crypto/cipher: invalid buffer overlap")
   126  	}
   127  	if len(src) == 0 {
   128  		return
   129  	}
   130  
   131  	// For each block, we need to xor the decrypted data with the previous block's ciphertext (the iv).
   132  	// To avoid making a copy each time, we loop over the blocks BACKWARDS.
   133  	end := len(src)
   134  	start := end - x.blockSize
   135  	prev := start - x.blockSize
   136  
   137  	// Copy the last block of ciphertext in preparation as the new iv.
   138  	copy(x.tmp, src[start:end])
   139  
   140  	// Loop over all but the first block.
   141  	for start > 0 {
   142  		x.b.Decrypt(dst[start:end], src[start:end])
   143  		xorBytes(dst[start:end], dst[start:end], src[prev:start])
   144  
   145  		end = start
   146  		start = prev
   147  		prev -= x.blockSize
   148  	}
   149  
   150  	// The first block is special because it uses the saved iv.
   151  	x.b.Decrypt(dst[start:end], src[start:end])
   152  	xorBytes(dst[start:end], dst[start:end], x.iv)
   153  
   154  	// Set the new iv to the first block we copied earlier.
   155  	x.iv, x.tmp = x.tmp, x.iv
   156  }
   157  
   158  func (x *cbcDecrypter) SetIV(iv []byte) {
   159  	if len(iv) != len(x.iv) {
   160  		panic("cipher: incorrect length IV")
   161  	}
   162  	copy(x.iv, iv)
   163  }
   164  

View as plain text