1
2
3
4
5
6
7
8
9
10
11
12
13 package cipher
14
15 import (
16 "bytes"
17 "crypto/internal/alias"
18 "crypto/subtle"
19 )
20
21 type ctr struct {
22 b Block
23 ctr []byte
24 out []byte
25 outUsed int
26 }
27
28 const streamBufferSize = 512
29
30
31
32
33 type ctrAble interface {
34 NewCTR(iv []byte) Stream
35 }
36
37
38
39 func NewCTR(block Block, iv []byte) Stream {
40 if ctr, ok := block.(ctrAble); ok {
41 return ctr.NewCTR(iv)
42 }
43 if len(iv) != block.BlockSize() {
44 panic("cipher.NewCTR: IV length must equal block size")
45 }
46 bufSize := streamBufferSize
47 if bufSize < block.BlockSize() {
48 bufSize = block.BlockSize()
49 }
50 return &ctr{
51 b: block,
52 ctr: bytes.Clone(iv),
53 out: make([]byte, 0, bufSize),
54 outUsed: 0,
55 }
56 }
57
58 func (x *ctr) refill() {
59 remain := len(x.out) - x.outUsed
60 copy(x.out, x.out[x.outUsed:])
61 x.out = x.out[:cap(x.out)]
62 bs := x.b.BlockSize()
63 for remain <= len(x.out)-bs {
64 x.b.Encrypt(x.out[remain:], x.ctr)
65 remain += bs
66
67
68 for i := len(x.ctr) - 1; i >= 0; i-- {
69 x.ctr[i]++
70 if x.ctr[i] != 0 {
71 break
72 }
73 }
74 }
75 x.out = x.out[:remain]
76 x.outUsed = 0
77 }
78
79 func (x *ctr) XORKeyStream(dst, src []byte) {
80 if len(dst) < len(src) {
81 panic("crypto/cipher: output smaller than input")
82 }
83 if alias.InexactOverlap(dst[:len(src)], src) {
84 panic("crypto/cipher: invalid buffer overlap")
85 }
86 for len(src) > 0 {
87 if x.outUsed >= len(x.out)-x.b.BlockSize() {
88 x.refill()
89 }
90 n := subtle.XORBytes(dst, src, x.out[x.outUsed:])
91 dst = dst[n:]
92 src = src[n:]
93 x.outUsed += n
94 }
95 }
96
View as plain text