1
2
3
4
5 package aes
6
7 import (
8 "crypto/internal/fips140/alias"
9 "crypto/internal/fips140/subtle"
10 "crypto/internal/fips140deps/byteorder"
11 "math/bits"
12 )
13
14 type CTR struct {
15 b Block
16 ivlo, ivhi uint64
17 offset uint64
18 }
19
20 func NewCTR(b *Block, iv []byte) *CTR {
21
22
23
24 c := newCTR(b, iv)
25 return &c
26 }
27 func newCTR(b *Block, iv []byte) CTR {
28 if len(iv) != BlockSize {
29 panic("bad IV length")
30 }
31
32 return CTR{
33 b: *b,
34 ivlo: byteorder.BEUint64(iv[8:16]),
35 ivhi: byteorder.BEUint64(iv[0:8]),
36 offset: 0,
37 }
38 }
39
40 func (c *CTR) XORKeyStream(dst, src []byte) {
41 c.XORKeyStreamAt(dst, src, c.offset)
42
43 var carry uint64
44 c.offset, carry = bits.Add64(c.offset, uint64(len(src)), 0)
45 if carry != 0 {
46 panic("crypto/aes: counter overflow")
47 }
48 }
49
50
51
52 func RoundToBlock(c *CTR) {
53 if remainder := c.offset % BlockSize; remainder != 0 {
54 var carry uint64
55 c.offset, carry = bits.Add64(c.offset, BlockSize-remainder, 0)
56 if carry != 0 {
57 panic("crypto/aes: counter overflow")
58 }
59 }
60 }
61
62
63
64
65
66 func (c *CTR) XORKeyStreamAt(dst, src []byte, offset uint64) {
67 if len(dst) < len(src) {
68 panic("crypto/aes: len(dst) < len(src)")
69 }
70 dst = dst[:len(src)]
71 if alias.InexactOverlap(dst, src) {
72 panic("crypto/aes: invalid buffer overlap")
73 }
74
75 ivlo, ivhi := add128(c.ivlo, c.ivhi, offset/BlockSize)
76
77 if blockOffset := offset % BlockSize; blockOffset != 0 {
78
79 var in, out [BlockSize]byte
80 copy(in[blockOffset:], src)
81 ctrBlocks1(&c.b, &out, &in, ivlo, ivhi)
82 n := copy(dst, out[blockOffset:])
83 src = src[n:]
84 dst = dst[n:]
85 ivlo, ivhi = add128(ivlo, ivhi, 1)
86 }
87
88 for len(src) >= 8*BlockSize {
89 ctrBlocks8(&c.b, (*[8 * BlockSize]byte)(dst), (*[8 * BlockSize]byte)(src), ivlo, ivhi)
90 src = src[8*BlockSize:]
91 dst = dst[8*BlockSize:]
92 ivlo, ivhi = add128(ivlo, ivhi, 8)
93 }
94
95
96 if len(src) >= 4*BlockSize {
97 ctrBlocks4(&c.b, (*[4 * BlockSize]byte)(dst), (*[4 * BlockSize]byte)(src), ivlo, ivhi)
98 src = src[4*BlockSize:]
99 dst = dst[4*BlockSize:]
100 ivlo, ivhi = add128(ivlo, ivhi, 4)
101 }
102 if len(src) >= 2*BlockSize {
103 ctrBlocks2(&c.b, (*[2 * BlockSize]byte)(dst), (*[2 * BlockSize]byte)(src), ivlo, ivhi)
104 src = src[2*BlockSize:]
105 dst = dst[2*BlockSize:]
106 ivlo, ivhi = add128(ivlo, ivhi, 2)
107 }
108 if len(src) >= 1*BlockSize {
109 ctrBlocks1(&c.b, (*[1 * BlockSize]byte)(dst), (*[1 * BlockSize]byte)(src), ivlo, ivhi)
110 src = src[1*BlockSize:]
111 dst = dst[1*BlockSize:]
112 ivlo, ivhi = add128(ivlo, ivhi, 1)
113 }
114
115 if len(src) != 0 {
116
117 var in, out [BlockSize]byte
118 copy(in[:], src)
119 ctrBlocks1(&c.b, &out, &in, ivlo, ivhi)
120 copy(dst, out[:])
121 }
122 }
123
124
125
126
127
128
129 func ctrBlocks(b *Block, dst, src []byte, ivlo, ivhi uint64) {
130 buf := make([]byte, len(src), 8*BlockSize)
131 for i := 0; i < len(buf); i += BlockSize {
132 byteorder.BEPutUint64(buf[i:], ivhi)
133 byteorder.BEPutUint64(buf[i+8:], ivlo)
134 ivlo, ivhi = add128(ivlo, ivhi, 1)
135 encryptBlock(b, buf[i:], buf[i:])
136 }
137
138 subtle.XORBytes(buf, src, buf)
139 copy(dst, buf)
140 }
141
142 func add128(lo, hi uint64, x uint64) (uint64, uint64) {
143 lo, c := bits.Add64(lo, x, 0)
144 hi, _ = bits.Add64(hi, 0, c)
145 return lo, hi
146 }
147
View as plain text