...

Source file src/pkg/crypto/cipher/cbc.go

     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