]> Cypherpunks repositories - gostls13.git/commitdiff
crypto/cipher: fix CFB mode.
authorAdam Langley <agl@golang.org>
Sun, 15 Dec 2013 17:55:59 +0000 (12:55 -0500)
committerAdam Langley <agl@golang.org>
Sun, 15 Dec 2013 17:55:59 +0000 (12:55 -0500)
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

src/pkg/crypto/cipher/cfb.go
src/pkg/crypto/cipher/cfb_test.go

index acaed007a94d670765a1e0cecb6e2f5a76719866..9b4eebf5b454164c794e6e166f1e2769a1c3adbd 100644 (file)
@@ -16,21 +16,22 @@ type cfb struct {
 }
 
 func (x *cfb) XORKeyStream(dst, src []byte) {
-       for i := 0; i < len(src); i++ {
+       for len(src) > 0 {
                if x.outUsed == len(x.out) {
                        x.b.Encrypt(x.out, x.next)
                        x.outUsed = 0
                }
 
-               n := xorBytes(dst, src, x.out[x.outUsed:])
                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])
-               } else {
-                       copy(x.next[x.outUsed:], dst[:n])
+                       copy(x.next[x.outUsed:], src)
+               }
+               n := xorBytes(dst, src, x.out[x.outUsed:])
+               if !x.decrypt {
+                       copy(x.next[x.outUsed:], dst)
                }
                dst = dst[n:]
                src = src[n:]
index f704b337e4bd006834c6a06f48f1c27b121afc5e..ec708ab2be29c8fff0ce18a0f584d786a0ca13fc 100644 (file)
@@ -19,16 +19,18 @@ func TestCFB(t *testing.T) {
                return
        }
 
-       plaintext := []byte("this is the plaintext")
+       plaintext := []byte("this is the plaintext. this is the plaintext.")
        iv := make([]byte, block.BlockSize())
        rand.Reader.Read(iv)
        cfb := cipher.NewCFBEncrypter(block, iv)
        ciphertext := make([]byte, len(plaintext))
-       cfb.XORKeyStream(ciphertext, plaintext)
+       copy(ciphertext, plaintext)
+       cfb.XORKeyStream(ciphertext, ciphertext)
 
        cfbdec := cipher.NewCFBDecrypter(block, iv)
        plaintextCopy := make([]byte, len(plaintext))
-       cfbdec.XORKeyStream(plaintextCopy, ciphertext)
+       copy(plaintextCopy, ciphertext)
+       cfbdec.XORKeyStream(plaintextCopy, plaintextCopy)
 
        if !bytes.Equal(plaintextCopy, plaintext) {
                t.Errorf("got: %x, want: %x", plaintextCopy, plaintext)