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

View as plain text