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