crypto/cipher: avoid out of bounds error in CryptBlocks

Fixes #4699.

R=golang-dev, agl
CC=golang-dev
https://golang.org/cl/7231065
This commit is contained in:
Russ Cox 2013-01-30 12:45:13 -08:00
parent 7e9f00c80c
commit fa2acad603
2 changed files with 48 additions and 0 deletions

View 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++ {

View file

@ -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()
}