cfb.mx raw

   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/fips140/alias"
  11  	"crypto/internal/fips140only"
  12  	"crypto/subtle"
  13  )
  14  
  15  type cfb struct {
  16  	b       Block
  17  	next    []byte
  18  	out     []byte
  19  	outUsed int
  20  
  21  	decrypt bool
  22  }
  23  
  24  func (x *cfb) XORKeyStream(dst, src []byte) {
  25  	if len(dst) < len(src) {
  26  		panic("crypto/cipher: output smaller than input")
  27  	}
  28  	if alias.InexactOverlap(dst[:len(src)], src) {
  29  		panic("crypto/cipher: invalid buffer overlap")
  30  	}
  31  	for len(src) > 0 {
  32  		if x.outUsed == len(x.out) {
  33  			x.b.Encrypt(x.out, x.next)
  34  			x.outUsed = 0
  35  		}
  36  
  37  		if x.decrypt {
  38  			// We can precompute a larger segment of the
  39  			// keystream on decryption. This will allow
  40  			// larger batches for xor, and we should be
  41  			// able to match CTR/OFB performance.
  42  			copy(x.next[x.outUsed:], src)
  43  		}
  44  		n := subtle.XORBytes(dst, src, x.out[x.outUsed:])
  45  		if !x.decrypt {
  46  			copy(x.next[x.outUsed:], dst)
  47  		}
  48  		dst = dst[n:]
  49  		src = src[n:]
  50  		x.outUsed += n
  51  	}
  52  }
  53  
  54  // NewCFBEncrypter returns a [Stream] which encrypts with cipher feedback mode,
  55  // using the given [Block]. The iv must be the same length as the [Block]'s block
  56  // size.
  57  //
  58  // Deprecated: CFB mode is not authenticated, which generally enables active
  59  // attacks to manipulate and recover the plaintext. It is recommended that
  60  // applications use [AEAD] modes instead. The standard library implementation of
  61  // CFB is also unoptimized and not validated as part of the FIPS 140-3 module.
  62  // If an unauthenticated [Stream] mode is required, use [NewCTR] instead.
  63  func NewCFBEncrypter(block Block, iv []byte) Stream {
  64  	if fips140only.Enabled {
  65  		panic("crypto/cipher: use of CFB is not allowed in FIPS 140-only mode")
  66  	}
  67  	return newCFB(block, iv, false)
  68  }
  69  
  70  // NewCFBDecrypter returns a [Stream] which decrypts with cipher feedback mode,
  71  // using the given [Block]. The iv must be the same length as the [Block]'s block
  72  // size.
  73  //
  74  // Deprecated: CFB mode is not authenticated, which generally enables active
  75  // attacks to manipulate and recover the plaintext. It is recommended that
  76  // applications use [AEAD] modes instead. The standard library implementation of
  77  // CFB is also unoptimized and not validated as part of the FIPS 140-3 module.
  78  // If an unauthenticated [Stream] mode is required, use [NewCTR] instead.
  79  func NewCFBDecrypter(block Block, iv []byte) Stream {
  80  	if fips140only.Enabled {
  81  		panic("crypto/cipher: use of CFB is not allowed in FIPS 140-only mode")
  82  	}
  83  	return newCFB(block, iv, true)
  84  }
  85  
  86  func newCFB(block Block, iv []byte, decrypt bool) Stream {
  87  	blockSize := block.BlockSize()
  88  	if len(iv) != blockSize {
  89  		// Stack trace will indicate whether it was de- or en-cryption.
  90  		panic("cipher.newCFB: IV length must equal block size")
  91  	}
  92  	x := &cfb{
  93  		b:       block,
  94  		out:     []byte{:blockSize},
  95  		next:    []byte{:blockSize},
  96  		outUsed: blockSize,
  97  		decrypt: decrypt,
  98  	}
  99  	copy(x.next, iv)
 100  
 101  	return x
 102  }
 103