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