...

Source file src/crypto/cipher/cbc.go

Documentation: crypto/cipher

		 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  }
	 164  

View as plain text