libgo: Merge from revision 18783:00cce3a34d7e of master library.
[official-gcc.git] / libgo / go / crypto / cipher / ctr.go
blob70ac40f6a7afbd32d58658bd57120c3bc685c899
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.
5 // Counter (CTR) mode.
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
13 package cipher
15 type ctr struct {
16 b Block
17 ctr []byte
18 out []byte
19 outUsed int
22 const streamBufferSize = 512
24 // NewCTR returns a Stream which encrypts/decrypts using the given Block in
25 // counter mode. The length of iv must be the same as the Block's block size.
26 func NewCTR(block Block, iv []byte) Stream {
27 if len(iv) != block.BlockSize() {
28 panic("cipher.NewCTR: IV length must equal block size")
30 bufSize := streamBufferSize
31 if bufSize < block.BlockSize() {
32 bufSize = block.BlockSize()
34 return &ctr{
35 b: block,
36 ctr: dup(iv),
37 out: make([]byte, 0, bufSize),
38 outUsed: 0,
42 func (x *ctr) refill() {
43 remain := len(x.out) - x.outUsed
44 if remain > x.outUsed {
45 return
47 copy(x.out, x.out[x.outUsed:])
48 x.out = x.out[:cap(x.out)]
49 bs := x.b.BlockSize()
50 for remain < len(x.out)-bs {
51 x.b.Encrypt(x.out[remain:], x.ctr)
52 remain += bs
54 // Increment counter
55 for i := len(x.ctr) - 1; i >= 0; i-- {
56 x.ctr[i]++
57 if x.ctr[i] != 0 {
58 break
62 x.out = x.out[:remain]
63 x.outUsed = 0
66 func (x *ctr) XORKeyStream(dst, src []byte) {
67 for len(src) > 0 {
68 if x.outUsed >= len(x.out)-x.b.BlockSize() {
69 x.refill()
71 n := xorBytes(dst, src, x.out[x.outUsed:])
72 dst = dst[n:]
73 src = src[n:]
74 x.outUsed += n