cbc.mx raw

   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 (
  15  	"bytes"
  16  	"crypto/internal/fips140/aes"
  17  	"crypto/internal/fips140/alias"
  18  	"crypto/internal/fips140only"
  19  	"crypto/subtle"
  20  )
  21  
  22  type cbc struct {
  23  	b         Block
  24  	blockSize int
  25  	iv        []byte
  26  	tmp       []byte
  27  }
  28  
  29  func newCBC(b Block, iv []byte) *cbc {
  30  	return &cbc{
  31  		b:         b,
  32  		blockSize: b.BlockSize(),
  33  		iv:        bytes.Clone(iv),
  34  		tmp:       []byte{:b.BlockSize()},
  35  	}
  36  }
  37  
  38  type cbcEncrypter cbc
  39  
  40  // cbcEncAble is an interface implemented by ciphers that have a specific
  41  // optimized implementation of CBC encryption. crypto/aes doesn't use this
  42  // anymore, and we'd like to eventually remove it.
  43  type cbcEncAble interface {
  44  	NewCBCEncrypter(iv []byte) BlockMode
  45  }
  46  
  47  // NewCBCEncrypter returns a BlockMode which encrypts in cipher block chaining
  48  // mode, using the given Block. The length of iv must be the same as the
  49  // Block's block size.
  50  func NewCBCEncrypter(b Block, iv []byte) BlockMode {
  51  	if len(iv) != b.BlockSize() {
  52  		panic("cipher.NewCBCEncrypter: IV length must equal block size")
  53  	}
  54  	if b, ok := b.(*aes.Block); ok {
  55  		return aes.NewCBCEncrypter(b, [16]byte(iv))
  56  	}
  57  	if fips140only.Enabled {
  58  		panic("crypto/cipher: use of CBC with non-AES ciphers is not allowed in FIPS 140-only mode")
  59  	}
  60  	if cbc, ok := b.(cbcEncAble); ok {
  61  		return cbc.NewCBCEncrypter(iv)
  62  	}
  63  	return (*cbcEncrypter)(newCBC(b, iv))
  64  }
  65  
  66  // newCBCGenericEncrypter returns a BlockMode which encrypts in cipher block chaining
  67  // mode, using the given Block. The length of iv must be the same as the
  68  // Block's block size. This always returns the generic non-asm encrypter for use
  69  // in fuzz testing.
  70  func newCBCGenericEncrypter(b Block, iv []byte) BlockMode {
  71  	if len(iv) != b.BlockSize() {
  72  		panic("cipher.NewCBCEncrypter: IV length must equal block size")
  73  	}
  74  	return (*cbcEncrypter)(newCBC(b, iv))
  75  }
  76  
  77  func (x *cbcEncrypter) BlockSize() int { return x.blockSize }
  78  
  79  func (x *cbcEncrypter) CryptBlocks(dst, src []byte) {
  80  	if len(src)%x.blockSize != 0 {
  81  		panic("crypto/cipher: input not full blocks")
  82  	}
  83  	if len(dst) < len(src) {
  84  		panic("crypto/cipher: output smaller than input")
  85  	}
  86  	if alias.InexactOverlap(dst[:len(src)], src) {
  87  		panic("crypto/cipher: invalid buffer overlap")
  88  	}
  89  	if _, ok := x.b.(*aes.Block); ok {
  90  		panic("crypto/cipher: internal error: generic CBC used with AES")
  91  	}
  92  
  93  	iv := x.iv
  94  
  95  	for len(src) > 0 {
  96  		// Write the xor to dst, then encrypt in place.
  97  		subtle.XORBytes(dst[:x.blockSize], src[:x.blockSize], iv)
  98  		x.b.Encrypt(dst[:x.blockSize], dst[:x.blockSize])
  99  
 100  		// Move to the next block with this block as the next iv.
 101  		iv = dst[:x.blockSize]
 102  		src = src[x.blockSize:]
 103  		dst = dst[x.blockSize:]
 104  	}
 105  
 106  	// Save the iv for the next CryptBlocks call.
 107  	copy(x.iv, iv)
 108  }
 109  
 110  func (x *cbcEncrypter) SetIV(iv []byte) {
 111  	if len(iv) != len(x.iv) {
 112  		panic("cipher: incorrect length IV")
 113  	}
 114  	copy(x.iv, iv)
 115  }
 116  
 117  type cbcDecrypter cbc
 118  
 119  // cbcDecAble is an interface implemented by ciphers that have a specific
 120  // optimized implementation of CBC decryption. crypto/aes doesn't use this
 121  // anymore, and we'd like to eventually remove it.
 122  type cbcDecAble interface {
 123  	NewCBCDecrypter(iv []byte) BlockMode
 124  }
 125  
 126  // NewCBCDecrypter returns a BlockMode which decrypts in cipher block chaining
 127  // mode, using the given Block. The length of iv must be the same as the
 128  // Block's block size and must match the iv used to encrypt the data.
 129  func NewCBCDecrypter(b Block, iv []byte) BlockMode {
 130  	if len(iv) != b.BlockSize() {
 131  		panic("cipher.NewCBCDecrypter: IV length must equal block size")
 132  	}
 133  	if b, ok := b.(*aes.Block); ok {
 134  		return aes.NewCBCDecrypter(b, [16]byte(iv))
 135  	}
 136  	if fips140only.Enabled {
 137  		panic("crypto/cipher: use of CBC with non-AES ciphers is not allowed in FIPS 140-only mode")
 138  	}
 139  	if cbc, ok := b.(cbcDecAble); ok {
 140  		return cbc.NewCBCDecrypter(iv)
 141  	}
 142  	return (*cbcDecrypter)(newCBC(b, iv))
 143  }
 144  
 145  // newCBCGenericDecrypter returns a BlockMode which encrypts in cipher block chaining
 146  // mode, using the given Block. The length of iv must be the same as the
 147  // Block's block size. This always returns the generic non-asm decrypter for use in
 148  // fuzz testing.
 149  func newCBCGenericDecrypter(b Block, iv []byte) BlockMode {
 150  	if len(iv) != b.BlockSize() {
 151  		panic("cipher.NewCBCDecrypter: IV length must equal block size")
 152  	}
 153  	return (*cbcDecrypter)(newCBC(b, iv))
 154  }
 155  
 156  func (x *cbcDecrypter) BlockSize() int { return x.blockSize }
 157  
 158  func (x *cbcDecrypter) CryptBlocks(dst, src []byte) {
 159  	if len(src)%x.blockSize != 0 {
 160  		panic("crypto/cipher: input not full blocks")
 161  	}
 162  	if len(dst) < len(src) {
 163  		panic("crypto/cipher: output smaller than input")
 164  	}
 165  	if alias.InexactOverlap(dst[:len(src)], src) {
 166  		panic("crypto/cipher: invalid buffer overlap")
 167  	}
 168  	if _, ok := x.b.(*aes.Block); ok {
 169  		panic("crypto/cipher: internal error: generic CBC used with AES")
 170  	}
 171  	if len(src) == 0 {
 172  		return
 173  	}
 174  
 175  	// For each block, we need to xor the decrypted data with the previous block's ciphertext (the iv).
 176  	// To avoid making a copy each time, we loop over the blocks BACKWARDS.
 177  	end := len(src)
 178  	start := end - x.blockSize
 179  	prev := start - x.blockSize
 180  
 181  	// Copy the last block of ciphertext in preparation as the new iv.
 182  	copy(x.tmp, src[start:end])
 183  
 184  	// Loop over all but the first block.
 185  	for start > 0 {
 186  		x.b.Decrypt(dst[start:end], src[start:end])
 187  		subtle.XORBytes(dst[start:end], dst[start:end], src[prev:start])
 188  
 189  		end = start
 190  		start = prev
 191  		prev -= x.blockSize
 192  	}
 193  
 194  	// The first block is special because it uses the saved iv.
 195  	x.b.Decrypt(dst[start:end], src[start:end])
 196  	subtle.XORBytes(dst[start:end], dst[start:end], x.iv)
 197  
 198  	// Set the new iv to the first block we copied earlier.
 199  	x.iv, x.tmp = x.tmp, x.iv
 200  }
 201  
 202  func (x *cbcDecrypter) SetIV(iv []byte) {
 203  	if len(iv) != len(x.iv) {
 204  		panic("cipher: incorrect length IV")
 205  	}
 206  	copy(x.iv, iv)
 207  }
 208