1 // Copyright 2009 The Go Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style
3 // license that can be found in the LICENSE file.
7 // CTR converts a block cipher into a stream cipher by
8 // repeatedly encrypting an incrementing counter and
9 // xoring the resulting stream of data with the input.
11 // See NIST SP 800-38A, pp 13-15
15 import "crypto/internal/subtle"
24 const streamBufferSize
= 512
26 // ctrAble is an interface implemented by ciphers that have a specific optimized
27 // implementation of CTR, like crypto/aes. NewCTR will check for this interface
28 // and return the specific Stream if found.
29 type ctrAble
interface {
30 NewCTR(iv
[]byte) Stream
33 // NewCTR returns a Stream which encrypts/decrypts using the given Block in
34 // counter mode. The length of iv must be the same as the Block's block size.
35 func NewCTR(block Block
, iv
[]byte) Stream
{
36 if ctr
, ok
:= block
.(ctrAble
); ok
{
39 if len(iv
) != block
.BlockSize() {
40 panic("cipher.NewCTR: IV length must equal block size")
42 bufSize
:= streamBufferSize
43 if bufSize
< block
.BlockSize() {
44 bufSize
= block
.BlockSize()
49 out
: make([]byte, 0, bufSize
),
54 func (x
*ctr
) refill() {
55 remain
:= len(x
.out
) - x
.outUsed
56 copy(x
.out
, x
.out
[x
.outUsed
:])
57 x
.out
= x
.out
[:cap(x
.out
)]
59 for remain
<= len(x
.out
)-bs
{
60 x
.b
.Encrypt(x
.out
[remain
:], x
.ctr
)
64 for i
:= len(x
.ctr
) - 1; i
>= 0; i
-- {
71 x
.out
= x
.out
[:remain
]
75 func (x
*ctr
) XORKeyStream(dst
, src
[]byte) {
76 if len(dst
) < len(src
) {
77 panic("crypto/cipher: output smaller than input")
79 if subtle
.InexactOverlap(dst
[:len(src
)], src
) {
80 panic("crypto/cipher: invalid buffer overlap")
83 if x
.outUsed
>= len(x
.out
)-x
.b
.BlockSize() {
86 n
:= xorBytes(dst
, src
, x
.out
[x
.outUsed
:])