]> Cypherpunks repositories - gostls13.git/commitdiff
crypto/cipher: avoid out of bounds error in CryptBlocks
authorRuss Cox <rsc@golang.org>
Wed, 30 Jan 2013 20:45:13 +0000 (12:45 -0800)
committerRuss Cox <rsc@golang.org>
Wed, 30 Jan 2013 20:45:13 +0000 (12:45 -0800)
Fixes #4699.

R=golang-dev, agl
CC=golang-dev
https://golang.org/cl/7231065

src/pkg/crypto/cipher/cbc.go
src/pkg/crypto/cipher/cipher_test.go [new file with mode: 0644]

index 6fab9b42131e364d2c0c2ab73614bfaedeeecc4a..913a5643f22cc7af0cdc69c9b1facbb4940cccfd 100644 (file)
@@ -42,6 +42,12 @@ func NewCBCEncrypter(b Block, iv []byte) BlockMode {
 func (x *cbcEncrypter) BlockSize() int { return x.blockSize }
 
 func (x *cbcEncrypter) CryptBlocks(dst, src []byte) {
+       if len(src)%x.blockSize != 0 {
+               panic("crypto/cipher: input not full blocks")
+       }
+       if len(dst) < len(src) {
+               panic("crypto/cipher: output smaller than input")
+       }
        for len(src) > 0 {
                for i := 0; i < x.blockSize; i++ {
                        x.iv[i] ^= src[i]
@@ -70,6 +76,12 @@ func NewCBCDecrypter(b Block, iv []byte) BlockMode {
 func (x *cbcDecrypter) BlockSize() int { return x.blockSize }
 
 func (x *cbcDecrypter) CryptBlocks(dst, src []byte) {
+       if len(src)%x.blockSize != 0 {
+               panic("crypto/cipher: input not full blocks")
+       }
+       if len(dst) < len(src) {
+               panic("crypto/cipher: output smaller than input")
+       }
        for len(src) > 0 {
                x.b.Decrypt(x.tmp, src[:x.blockSize])
                for i := 0; i < x.blockSize; i++ {
diff --git a/src/pkg/crypto/cipher/cipher_test.go b/src/pkg/crypto/cipher/cipher_test.go
new file mode 100644 (file)
index 0000000..8da5bce
--- /dev/null
@@ -0,0 +1,36 @@
+// Copyright 2013 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.
+
+package cipher_test
+
+import (
+       "crypto/aes"
+       "crypto/cipher"
+       "testing"
+)
+
+func TestCryptBlocks(t *testing.T) {
+       buf := make([]byte, 16)
+       block, _ := aes.NewCipher(buf)
+
+       mode := cipher.NewCBCDecrypter(block, buf)
+       mustPanic(t, "crypto/cipher: input not full blocks", func() { mode.CryptBlocks(buf, buf[:3]) })
+       mustPanic(t, "crypto/cipher: output smaller than input", func() { mode.CryptBlocks(buf[:3], buf) })
+
+       mode = cipher.NewCBCEncrypter(block, buf)
+       mustPanic(t, "crypto/cipher: input not full blocks", func() { mode.CryptBlocks(buf, buf[:3]) })
+       mustPanic(t, "crypto/cipher: output smaller than input", func() { mode.CryptBlocks(buf[:3], buf) })
+}
+
+func mustPanic(t *testing.T, msg string, f func()) {
+       defer func() {
+               err := recover()
+               if err == nil {
+                       t.Errorf("function did not panic, wanted %q", msg)
+               } else if err != msg {
+                       t.Errorf("got panic %v, wanted %q", err, msg)
+               }
+       }()
+       f()
+}