From fa2acad60379f59712cc15ea1c4192b982e69a35 Mon Sep 17 00:00:00 2001 From: Russ Cox Date: Wed, 30 Jan 2013 12:45:13 -0800 Subject: [PATCH] crypto/cipher: avoid out of bounds error in CryptBlocks Fixes #4699. R=golang-dev, agl CC=golang-dev https://golang.org/cl/7231065 --- src/pkg/crypto/cipher/cbc.go | 12 ++++++++++ src/pkg/crypto/cipher/cipher_test.go | 36 ++++++++++++++++++++++++++++ 2 files changed, 48 insertions(+) create mode 100644 src/pkg/crypto/cipher/cipher_test.go diff --git a/src/pkg/crypto/cipher/cbc.go b/src/pkg/crypto/cipher/cbc.go index 6fab9b4213..913a5643f2 100644 --- a/src/pkg/crypto/cipher/cbc.go +++ b/src/pkg/crypto/cipher/cbc.go @@ -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 index 0000000000..8da5bce93f --- /dev/null +++ b/src/pkg/crypto/cipher/cipher_test.go @@ -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() +} -- 2.48.1