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 type cbc struct { 15 b Block 16 blockSize int 17 iv []byte 18 tmp []byte 19 } 20 21 func newCBC(b Block, iv []byte) *cbc { 22 return &cbc{ 23 b: b, 24 blockSize: b.BlockSize(), 25 iv: dup(iv), 26 tmp: make([]byte, b.BlockSize()), 27 } 28 } 29 30 type cbcEncrypter cbc 31 32 // NewCBCEncrypter returns a BlockMode which encrypts in cipher block chaining 33 // mode, using the given Block. The length of iv must be the same as the 34 // Block's block size. 35 func NewCBCEncrypter(b Block, iv []byte) BlockMode { 36 if len(iv) != b.BlockSize() { 37 panic("cipher.NewCBCEncrypter: IV length must equal block size") 38 } 39 return (*cbcEncrypter)(newCBC(b, iv)) 40 } 41 42 func (x *cbcEncrypter) BlockSize() int { return x.blockSize } 43 44 func (x *cbcEncrypter) CryptBlocks(dst, src []byte) { 45 if len(src)%x.blockSize != 0 { 46 panic("crypto/cipher: input not full blocks") 47 } 48 if len(dst) < len(src) { 49 panic("crypto/cipher: output smaller than input") 50 } 51 52 iv := x.iv 53 54 for len(src) > 0 { 55 // Write the xor to dst, then encrypt in place. 56 xorBytes(dst[:x.blockSize], src[:x.blockSize], iv) 57 x.b.Encrypt(dst[:x.blockSize], dst[:x.blockSize]) 58 59 // Move to the next block with this block as the next iv. 60 iv = dst[:x.blockSize] 61 src = src[x.blockSize:] 62 dst = dst[x.blockSize:] 63 } 64 65 // Save the iv for the next CryptBlocks call. 66 copy(x.iv, iv) 67 } 68 69 func (x *cbcEncrypter) SetIV(iv []byte) { 70 if len(iv) != len(x.iv) { 71 panic("cipher: incorrect length IV") 72 } 73 copy(x.iv, iv) 74 } 75 76 type cbcDecrypter cbc 77 78 // NewCBCDecrypter returns a BlockMode which decrypts in cipher block chaining 79 // mode, using the given Block. The length of iv must be the same as the 80 // Block's block size and must match the iv used to encrypt the data. 81 func NewCBCDecrypter(b Block, iv []byte) BlockMode { 82 if len(iv) != b.BlockSize() { 83 panic("cipher.NewCBCDecrypter: IV length must equal block size") 84 } 85 return (*cbcDecrypter)(newCBC(b, iv)) 86 } 87 88 func (x *cbcDecrypter) BlockSize() int { return x.blockSize } 89 90 func (x *cbcDecrypter) CryptBlocks(dst, src []byte) { 91 if len(src)%x.blockSize != 0 { 92 panic("crypto/cipher: input not full blocks") 93 } 94 if len(dst) < len(src) { 95 panic("crypto/cipher: output smaller than input") 96 } 97 if len(src) == 0 { 98 return 99 } 100 101 // For each block, we need to xor the decrypted data with the previous block's ciphertext (the iv). 102 // To avoid making a copy each time, we loop over the blocks BACKWARDS. 103 end := len(src) 104 start := end - x.blockSize 105 prev := start - x.blockSize 106 107 // Copy the last block of ciphertext in preparation as the new iv. 108 copy(x.tmp, src[start:end]) 109 110 // Loop over all but the first block. 111 for start > 0 { 112 x.b.Decrypt(dst[start:end], src[start:end]) 113 xorBytes(dst[start:end], dst[start:end], src[prev:start]) 114 115 end = start 116 start = prev 117 prev -= x.blockSize 118 } 119 120 // The first block is special because it uses the saved iv. 121 x.b.Decrypt(dst[start:end], src[start:end]) 122 xorBytes(dst[start:end], dst[start:end], x.iv) 123 124 // Set the new iv to the first block we copied earlier. 125 x.iv, x.tmp = x.tmp, x.iv 126 } 127 128 func (x *cbcDecrypter) SetIV(iv []byte) { 129 if len(iv) != len(x.iv) { 130 panic("cipher: incorrect length IV") 131 } 132 copy(x.iv, iv) 133 } 134