Commit 1d546005 authored by Adam Langley's avatar Adam Langley

crypto/cipher: fix CFB mode.

a073d65e6f8c had a couple of bugs in the CFB mode that I missed in code review:
        1) The loop condition wasn't updated from the old version.
        2) It wasn't safe when src and dst aliased.

Fixes #6950.

R=golang-dev, hanwen
CC=golang-dev
https://golang.org/cl/42110043
parent be51b961
...@@ -16,21 +16,22 @@ type cfb struct { ...@@ -16,21 +16,22 @@ type cfb struct {
} }
func (x *cfb) XORKeyStream(dst, src []byte) { func (x *cfb) XORKeyStream(dst, src []byte) {
for i := 0; i < len(src); i++ { for len(src) > 0 {
if x.outUsed == len(x.out) { if x.outUsed == len(x.out) {
x.b.Encrypt(x.out, x.next) x.b.Encrypt(x.out, x.next)
x.outUsed = 0 x.outUsed = 0
} }
n := xorBytes(dst, src, x.out[x.outUsed:])
if x.decrypt { if x.decrypt {
// We can precompute a larger segment of the // We can precompute a larger segment of the
// keystream on decryption. This will allow // keystream on decryption. This will allow
// larger batches for xor, and we should be // larger batches for xor, and we should be
// able to match CTR/OFB performance. // able to match CTR/OFB performance.
copy(x.next[x.outUsed:], src[:n]) copy(x.next[x.outUsed:], src)
} else { }
copy(x.next[x.outUsed:], dst[:n]) n := xorBytes(dst, src, x.out[x.outUsed:])
if !x.decrypt {
copy(x.next[x.outUsed:], dst)
} }
dst = dst[n:] dst = dst[n:]
src = src[n:] src = src[n:]
......
...@@ -19,16 +19,18 @@ func TestCFB(t *testing.T) { ...@@ -19,16 +19,18 @@ func TestCFB(t *testing.T) {
return return
} }
plaintext := []byte("this is the plaintext") plaintext := []byte("this is the plaintext. this is the plaintext.")
iv := make([]byte, block.BlockSize()) iv := make([]byte, block.BlockSize())
rand.Reader.Read(iv) rand.Reader.Read(iv)
cfb := cipher.NewCFBEncrypter(block, iv) cfb := cipher.NewCFBEncrypter(block, iv)
ciphertext := make([]byte, len(plaintext)) ciphertext := make([]byte, len(plaintext))
cfb.XORKeyStream(ciphertext, plaintext) copy(ciphertext, plaintext)
cfb.XORKeyStream(ciphertext, ciphertext)
cfbdec := cipher.NewCFBDecrypter(block, iv) cfbdec := cipher.NewCFBDecrypter(block, iv)
plaintextCopy := make([]byte, len(plaintext)) plaintextCopy := make([]byte, len(plaintext))
cfbdec.XORKeyStream(plaintextCopy, ciphertext) copy(plaintextCopy, ciphertext)
cfbdec.XORKeyStream(plaintextCopy, plaintextCopy)
if !bytes.Equal(plaintextCopy, plaintext) { if !bytes.Equal(plaintextCopy, plaintext) {
t.Errorf("got: %x, want: %x", plaintextCopy, plaintext) t.Errorf("got: %x, want: %x", plaintextCopy, plaintext)
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment