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