|  | // Copyright 2009 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. | 
|  |  | 
|  | // Counter (CTR) mode. | 
|  |  | 
|  | // CTR converts a block cipher into a stream cipher by | 
|  | // repeatedly encrypting an incrementing counter and | 
|  | // xoring the resulting stream of data with the input. | 
|  |  | 
|  | // See NIST SP 800-38A, pp 13-15 | 
|  |  | 
|  | package cipher | 
|  |  | 
|  | import "crypto/internal/subtle" | 
|  |  | 
|  | type ctr struct { | 
|  | b       Block | 
|  | ctr     []byte | 
|  | out     []byte | 
|  | outUsed int | 
|  | } | 
|  |  | 
|  | const streamBufferSize = 512 | 
|  |  | 
|  | // ctrAble is an interface implemented by ciphers that have a specific optimized | 
|  | // implementation of CTR, like crypto/aes. NewCTR will check for this interface | 
|  | // and return the specific Stream if found. | 
|  | type ctrAble interface { | 
|  | NewCTR(iv []byte) Stream | 
|  | } | 
|  |  | 
|  | // NewCTR returns a Stream which encrypts/decrypts using the given Block in | 
|  | // counter mode. The length of iv must be the same as the Block's block size. | 
|  | func NewCTR(block Block, iv []byte) Stream { | 
|  | if ctr, ok := block.(ctrAble); ok { | 
|  | return ctr.NewCTR(iv) | 
|  | } | 
|  | if len(iv) != block.BlockSize() { | 
|  | panic("cipher.NewCTR: IV length must equal block size") | 
|  | } | 
|  | bufSize := streamBufferSize | 
|  | if bufSize < block.BlockSize() { | 
|  | bufSize = block.BlockSize() | 
|  | } | 
|  | return &ctr{ | 
|  | b:       block, | 
|  | ctr:     dup(iv), | 
|  | out:     make([]byte, 0, bufSize), | 
|  | outUsed: 0, | 
|  | } | 
|  | } | 
|  |  | 
|  | func (x *ctr) refill() { | 
|  | remain := len(x.out) - x.outUsed | 
|  | copy(x.out, x.out[x.outUsed:]) | 
|  | x.out = x.out[:cap(x.out)] | 
|  | bs := x.b.BlockSize() | 
|  | for remain <= len(x.out)-bs { | 
|  | x.b.Encrypt(x.out[remain:], x.ctr) | 
|  | remain += bs | 
|  |  | 
|  | // Increment counter | 
|  | for i := len(x.ctr) - 1; i >= 0; i-- { | 
|  | x.ctr[i]++ | 
|  | if x.ctr[i] != 0 { | 
|  | break | 
|  | } | 
|  | } | 
|  | } | 
|  | x.out = x.out[:remain] | 
|  | x.outUsed = 0 | 
|  | } | 
|  |  | 
|  | func (x *ctr) XORKeyStream(dst, src []byte) { | 
|  | if len(dst) < len(src) { | 
|  | panic("crypto/cipher: output smaller than input") | 
|  | } | 
|  | if subtle.InexactOverlap(dst[:len(src)], src) { | 
|  | panic("crypto/cipher: invalid buffer overlap") | 
|  | } | 
|  | for len(src) > 0 { | 
|  | if x.outUsed >= len(x.out)-x.b.BlockSize() { | 
|  | x.refill() | 
|  | } | 
|  | n := xorBytes(dst, src, x.out[x.outUsed:]) | 
|  | dst = dst[n:] | 
|  | src = src[n:] | 
|  | x.outUsed += n | 
|  | } | 
|  | } |