mirror of
https://github.com/golang/go
synced 2024-11-27 00:11:19 -07:00
crypto/cipher: fix CTR infinite loop with large block sizes
Additionally, add a test for CTR mode to cover a range of block sizes. Fixes #12975 Change-Id: I458aac1616228747e62f92f823768d55e874877a Reviewed-on: https://go-review.googlesource.com/16050 Reviewed-by: Adam Langley <agl@golang.org>
This commit is contained in:
parent
55ecda4ffd
commit
2bf91afd2b
@ -41,13 +41,10 @@ func NewCTR(block Block, iv []byte) Stream {
|
||||
|
||||
func (x *ctr) refill() {
|
||||
remain := len(x.out) - x.outUsed
|
||||
if remain > x.outUsed {
|
||||
return
|
||||
}
|
||||
copy(x.out, x.out[x.outUsed:])
|
||||
x.out = x.out[:cap(x.out)]
|
||||
bs := x.b.BlockSize()
|
||||
for remain < len(x.out)-bs {
|
||||
for remain <= len(x.out)-bs {
|
||||
x.b.Encrypt(x.out[remain:], x.ctr)
|
||||
remain += bs
|
||||
|
||||
|
55
src/crypto/cipher/ctr_test.go
Normal file
55
src/crypto/cipher/ctr_test.go
Normal file
@ -0,0 +1,55 @@
|
||||
// Copyright 2015 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 (
|
||||
"bytes"
|
||||
"crypto/cipher"
|
||||
"testing"
|
||||
)
|
||||
|
||||
type noopBlock int
|
||||
|
||||
func (b noopBlock) BlockSize() int { return int(b) }
|
||||
func (noopBlock) Encrypt(dst, src []byte) { copy(dst, src) }
|
||||
func (noopBlock) Decrypt(dst, src []byte) { copy(dst, src) }
|
||||
|
||||
func inc(b []byte) {
|
||||
for i := len(b) - 1; i >= 0; i++ {
|
||||
b[i]++
|
||||
if b[i] != 0 {
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func xor(a, b []byte) {
|
||||
for i := range a {
|
||||
a[i] ^= b[i]
|
||||
}
|
||||
}
|
||||
|
||||
func TestCTR(t *testing.T) {
|
||||
for size := 64; size <= 1024; size *= 2 {
|
||||
iv := make([]byte, size)
|
||||
ctr := cipher.NewCTR(noopBlock(size), iv)
|
||||
src := make([]byte, 1024)
|
||||
for i := range src {
|
||||
src[i] = 0xff
|
||||
}
|
||||
want := make([]byte, 1024)
|
||||
copy(want, src)
|
||||
counter := make([]byte, size)
|
||||
for i := 1; i < len(want)/size; i++ {
|
||||
inc(counter)
|
||||
xor(want[i*size:(i+1)*size], counter)
|
||||
}
|
||||
dst := make([]byte, 1024)
|
||||
ctr.XORKeyStream(dst, src)
|
||||
if !bytes.Equal(dst, want) {
|
||||
t.Errorf("for size %d\nhave %x\nwant %x", size, dst, want)
|
||||
}
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user