Source file src/pkg/vendor/golang.org/x/crypto/internal/chacha20/chacha_generic.go
1
2
3
4
5
6
7 package chacha20
8
9 import (
10 "crypto/cipher"
11 "encoding/binary"
12
13 "golang.org/x/crypto/internal/subtle"
14 )
15
16
17 var _ cipher.Stream = (*Cipher)(nil)
18
19
20
21 type Cipher struct {
22 key [8]uint32
23 counter uint32
24 nonce [3]uint32
25 buf [bufSize]byte
26 len int
27 }
28
29
30
31 func New(key [8]uint32, nonce [3]uint32) *Cipher {
32 return &Cipher{key: key, nonce: nonce}
33 }
34
35
36 const (
37 j0 uint32 = 0x61707865
38 j1 uint32 = 0x3320646e
39 j2 uint32 = 0x79622d32
40 j3 uint32 = 0x6b206574
41 )
42
43 func quarterRound(a, b, c, d uint32) (uint32, uint32, uint32, uint32) {
44 a += b
45 d ^= a
46 d = (d << 16) | (d >> 16)
47 c += d
48 b ^= c
49 b = (b << 12) | (b >> 20)
50 a += b
51 d ^= a
52 d = (d << 8) | (d >> 24)
53 c += d
54 b ^= c
55 b = (b << 7) | (b >> 25)
56 return a, b, c, d
57 }
58
59
60
61
62
63
64
65
66
67
68
69 func (s *Cipher) XORKeyStream(dst, src []byte) {
70 if len(dst) < len(src) {
71 panic("chacha20: output smaller than input")
72 }
73 if subtle.InexactOverlap(dst[:len(src)], src) {
74 panic("chacha20: invalid buffer overlap")
75 }
76
77
78 if s.len != 0 {
79 buf := s.buf[len(s.buf)-s.len:]
80 if len(src) < len(buf) {
81 buf = buf[:len(src)]
82 }
83 td, ts := dst[:len(buf)], src[:len(buf)]
84 for i, b := range buf {
85 td[i] = ts[i] ^ b
86 }
87 s.len -= len(buf)
88 if s.len != 0 {
89 return
90 }
91 s.buf = [len(s.buf)]byte{}
92 src = src[len(buf):]
93 dst = dst[len(buf):]
94 }
95
96 if len(src) == 0 {
97 return
98 }
99 if haveAsm {
100 if uint64(len(src))+uint64(s.counter)*64 > (1<<38)-64 {
101 panic("chacha20: counter overflow")
102 }
103 s.xorKeyStreamAsm(dst, src)
104 return
105 }
106
107
108
109 rem := len(src) % 64
110 fin := len(src) - rem
111 if rem > 0 {
112 copy(s.buf[len(s.buf)-64:], src[fin:])
113 }
114
115
116 s1, s5, s9, s13 := quarterRound(j1, s.key[1], s.key[5], s.nonce[0])
117 s2, s6, s10, s14 := quarterRound(j2, s.key[2], s.key[6], s.nonce[1])
118 s3, s7, s11, s15 := quarterRound(j3, s.key[3], s.key[7], s.nonce[2])
119
120 n := len(src)
121 src, dst = src[:n:n], dst[:n:n]
122 for i := 0; i < n; i += 64 {
123
124 s0, s4, s8, s12 := quarterRound(j0, s.key[0], s.key[4], s.counter)
125
126
127 x0, x5, x10, x15 := quarterRound(s0, s5, s10, s15)
128 x1, x6, x11, x12 := quarterRound(s1, s6, s11, s12)
129 x2, x7, x8, x13 := quarterRound(s2, s7, s8, s13)
130 x3, x4, x9, x14 := quarterRound(s3, s4, s9, s14)
131
132
133 for i := 0; i < 9; i++ {
134 x0, x4, x8, x12 = quarterRound(x0, x4, x8, x12)
135 x1, x5, x9, x13 = quarterRound(x1, x5, x9, x13)
136 x2, x6, x10, x14 = quarterRound(x2, x6, x10, x14)
137 x3, x7, x11, x15 = quarterRound(x3, x7, x11, x15)
138
139 x0, x5, x10, x15 = quarterRound(x0, x5, x10, x15)
140 x1, x6, x11, x12 = quarterRound(x1, x6, x11, x12)
141 x2, x7, x8, x13 = quarterRound(x2, x7, x8, x13)
142 x3, x4, x9, x14 = quarterRound(x3, x4, x9, x14)
143 }
144
145 x0 += j0
146 x1 += j1
147 x2 += j2
148 x3 += j3
149
150 x4 += s.key[0]
151 x5 += s.key[1]
152 x6 += s.key[2]
153 x7 += s.key[3]
154 x8 += s.key[4]
155 x9 += s.key[5]
156 x10 += s.key[6]
157 x11 += s.key[7]
158
159 x12 += s.counter
160 x13 += s.nonce[0]
161 x14 += s.nonce[1]
162 x15 += s.nonce[2]
163
164
165 s.counter += 1
166 if s.counter == 0 {
167 panic("chacha20: counter overflow")
168 }
169
170
171 in, out := src[i:], dst[i:]
172 if i == fin {
173
174
175 in, out = s.buf[len(s.buf)-64:], s.buf[len(s.buf)-64:]
176 }
177 in, out = in[:64], out[:64]
178
179
180 xor(out[0:], in[0:], x0)
181 xor(out[4:], in[4:], x1)
182 xor(out[8:], in[8:], x2)
183 xor(out[12:], in[12:], x3)
184 xor(out[16:], in[16:], x4)
185 xor(out[20:], in[20:], x5)
186 xor(out[24:], in[24:], x6)
187 xor(out[28:], in[28:], x7)
188 xor(out[32:], in[32:], x8)
189 xor(out[36:], in[36:], x9)
190 xor(out[40:], in[40:], x10)
191 xor(out[44:], in[44:], x11)
192 xor(out[48:], in[48:], x12)
193 xor(out[52:], in[52:], x13)
194 xor(out[56:], in[56:], x14)
195 xor(out[60:], in[60:], x15)
196 }
197
198 if rem != 0 {
199 s.len = 64 - rem
200 copy(dst[fin:], s.buf[len(s.buf)-64:])
201 }
202 }
203
204
205
206
207
208 func (s *Cipher) Advance() {
209 s.len -= s.len % 64
210 if s.len == 0 {
211 s.buf = [len(s.buf)]byte{}
212 }
213 }
214
215
216
217
218 func XORKeyStream(out, in []byte, counter *[16]byte, key *[32]byte) {
219 s := Cipher{
220 key: [8]uint32{
221 binary.LittleEndian.Uint32(key[0:4]),
222 binary.LittleEndian.Uint32(key[4:8]),
223 binary.LittleEndian.Uint32(key[8:12]),
224 binary.LittleEndian.Uint32(key[12:16]),
225 binary.LittleEndian.Uint32(key[16:20]),
226 binary.LittleEndian.Uint32(key[20:24]),
227 binary.LittleEndian.Uint32(key[24:28]),
228 binary.LittleEndian.Uint32(key[28:32]),
229 },
230 nonce: [3]uint32{
231 binary.LittleEndian.Uint32(counter[4:8]),
232 binary.LittleEndian.Uint32(counter[8:12]),
233 binary.LittleEndian.Uint32(counter[12:16]),
234 },
235 counter: binary.LittleEndian.Uint32(counter[0:4]),
236 }
237 s.XORKeyStream(out, in)
238 }
239
240
241
242 func HChaCha20(key *[8]uint32, nonce *[4]uint32) [8]uint32 {
243 x0, x1, x2, x3 := j0, j1, j2, j3
244 x4, x5, x6, x7 := key[0], key[1], key[2], key[3]
245 x8, x9, x10, x11 := key[4], key[5], key[6], key[7]
246 x12, x13, x14, x15 := nonce[0], nonce[1], nonce[2], nonce[3]
247
248 for i := 0; i < 10; i++ {
249 x0, x4, x8, x12 = quarterRound(x0, x4, x8, x12)
250 x1, x5, x9, x13 = quarterRound(x1, x5, x9, x13)
251 x2, x6, x10, x14 = quarterRound(x2, x6, x10, x14)
252 x3, x7, x11, x15 = quarterRound(x3, x7, x11, x15)
253
254 x0, x5, x10, x15 = quarterRound(x0, x5, x10, x15)
255 x1, x6, x11, x12 = quarterRound(x1, x6, x11, x12)
256 x2, x7, x8, x13 = quarterRound(x2, x7, x8, x13)
257 x3, x4, x9, x14 = quarterRound(x3, x4, x9, x14)
258 }
259
260 var out [8]uint32
261 out[0], out[1], out[2], out[3] = x0, x1, x2, x3
262 out[4], out[5], out[6], out[7] = x12, x13, x14, x15
263 return out
264 }
265
View as plain text