Source file src/crypto/cipher/cfb.go

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

View as plain text