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