Source file src/crypto/cipher/cbc.go

     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:       make([]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  

View as plain text