Home | History | Annotate | Download | only in cipher
      1 // Copyright 2010 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 // CFB (Cipher Feedback) Mode.
      6 
      7 package cipher
      8 
      9 type cfb struct {
     10 	b       Block
     11 	next    []byte
     12 	out     []byte
     13 	outUsed int
     14 
     15 	decrypt bool
     16 }
     17 
     18 func (x *cfb) XORKeyStream(dst, src []byte) {
     19 	for len(src) > 0 {
     20 		if x.outUsed == len(x.out) {
     21 			x.b.Encrypt(x.out, x.next)
     22 			x.outUsed = 0
     23 		}
     24 
     25 		if x.decrypt {
     26 			// We can precompute a larger segment of the
     27 			// keystream on decryption. This will allow
     28 			// larger batches for xor, and we should be
     29 			// able to match CTR/OFB performance.
     30 			copy(x.next[x.outUsed:], src)
     31 		}
     32 		n := xorBytes(dst, src, x.out[x.outUsed:])
     33 		if !x.decrypt {
     34 			copy(x.next[x.outUsed:], dst)
     35 		}
     36 		dst = dst[n:]
     37 		src = src[n:]
     38 		x.outUsed += n
     39 	}
     40 }
     41 
     42 // NewCFBEncrypter returns a Stream which encrypts with cipher feedback mode,
     43 // using the given Block. The iv must be the same length as the Block's block
     44 // size.
     45 func NewCFBEncrypter(block Block, iv []byte) Stream {
     46 	return newCFB(block, iv, false)
     47 }
     48 
     49 // NewCFBDecrypter returns a Stream which decrypts with cipher feedback mode,
     50 // using the given Block. The iv must be the same length as the Block's block
     51 // size.
     52 func NewCFBDecrypter(block Block, iv []byte) Stream {
     53 	return newCFB(block, iv, true)
     54 }
     55 
     56 func newCFB(block Block, iv []byte, decrypt bool) Stream {
     57 	blockSize := block.BlockSize()
     58 	if len(iv) != blockSize {
     59 		// stack trace will indicate whether it was de or encryption
     60 		panic("cipher.newCFB: IV length must equal block size")
     61 	}
     62 	x := &cfb{
     63 		b:       block,
     64 		out:     make([]byte, blockSize),
     65 		next:    make([]byte, blockSize),
     66 		outUsed: blockSize,
     67 		decrypt: decrypt,
     68 	}
     69 	copy(x.next, iv)
     70 
     71 	return x
     72 }
     73