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