| // Copyright 2010 The Go Authors. All rights reserved. | |
| // Use of this source code is governed by a BSD-style | |
| // license that can be found in the LICENSE file. | |
| // CFB (Cipher Feedback) Mode. | |
| package cipher | |
| import ( | |
| "crypto/internal/fips140/alias" | |
| "crypto/internal/fips140only" | |
| "crypto/subtle" | |
| ) | |
| type cfb struct { | |
| b Block | |
| next []byte | |
| out []byte | |
| outUsed int | |
| decrypt bool | |
| } | |
| func (x *cfb) XORKeyStream(dst, src []byte) { | |
| if len(dst) < len(src) { | |
| panic("crypto/cipher: output smaller than input") | |
| } | |
| if alias.InexactOverlap(dst[:len(src)], src) { | |
| panic("crypto/cipher: invalid buffer overlap") | |
| } | |
| for len(src) > 0 { | |
| if x.outUsed == len(x.out) { | |
| x.b.Encrypt(x.out, x.next) | |
| x.outUsed = 0 | |
| } | |
| if x.decrypt { | |
| // We can precompute a larger segment of the | |
| // keystream on decryption. This will allow | |
| // larger batches for xor, and we should be | |
| // able to match CTR/OFB performance. | |
| copy(x.next[x.outUsed:], src) | |
| } | |
| n := subtle.XORBytes(dst, src, x.out[x.outUsed:]) | |
| if !x.decrypt { | |
| copy(x.next[x.outUsed:], dst) | |
| } | |
| dst = dst[n:] | |
| src = src[n:] | |
| x.outUsed += n | |
| } | |
| } | |
| // NewCFBEncrypter returns a [Stream] which encrypts with cipher feedback mode, | |
| // using the given [Block]. The iv must be the same length as the [Block]'s block | |
| // size. | |
| // | |
| // Deprecated: CFB mode is not authenticated, which generally enables active | |
| // attacks to manipulate and recover the plaintext. It is recommended that | |
| // applications use [AEAD] modes instead. The standard library implementation of | |
| // CFB is also unoptimized and not validated as part of the FIPS 140-3 module. | |
| // If an unauthenticated [Stream] mode is required, use [NewCTR] instead. | |
| func NewCFBEncrypter(block Block, iv []byte) Stream { | |
| if fips140only.Enforced() { | |
| panic("crypto/cipher: use of CFB is not allowed in FIPS 140-only mode") | |
| } | |
| return newCFB(block, iv, false) | |
| } | |
| // NewCFBDecrypter returns a [Stream] which decrypts with cipher feedback mode, | |
| // using the given [Block]. The iv must be the same length as the [Block]'s block | |
| // size. | |
| // | |
| // Deprecated: CFB mode is not authenticated, which generally enables active | |
| // attacks to manipulate and recover the plaintext. It is recommended that | |
| // applications use [AEAD] modes instead. The standard library implementation of | |
| // CFB is also unoptimized and not validated as part of the FIPS 140-3 module. | |
| // If an unauthenticated [Stream] mode is required, use [NewCTR] instead. | |
| func NewCFBDecrypter(block Block, iv []byte) Stream { | |
| if fips140only.Enforced() { | |
| panic("crypto/cipher: use of CFB is not allowed in FIPS 140-only mode") | |
| } | |
| return newCFB(block, iv, true) | |
| } | |
| func newCFB(block Block, iv []byte, decrypt bool) Stream { | |
| blockSize := block.BlockSize() | |
| if len(iv) != blockSize { | |
| // Stack trace will indicate whether it was de- or en-cryption. | |
| panic("cipher.newCFB: IV length must equal block size") | |
| } | |
| x := &cfb{ | |
| b: block, | |
| out: make([]byte, blockSize), | |
| next: make([]byte, blockSize), | |
| outUsed: blockSize, | |
| decrypt: decrypt, | |
| } | |
| copy(x.next, iv) | |
| return x | |
| } | |