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