1 // Copyright 2016 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 // Package ChaCha20 implements the core ChaCha20 function as specified in https://tools.ietf.org/html/rfc7539#section-2.3.
8 import "encoding/binary"
12 // core applies the ChaCha20 core function to 16-byte input in, 32-byte key k,
13 // and 16-byte constant c, and puts the result into 64-byte array out.
14 func core(out *[64]byte, in *[16]byte, k *[32]byte) {
15 j0 := uint32(0x61707865)
16 j1 := uint32(0x3320646e)
17 j2 := uint32(0x79622d32)
18 j3 := uint32(0x6b206574)
19 j4 := binary.LittleEndian.Uint32(k[0:4])
20 j5 := binary.LittleEndian.Uint32(k[4:8])
21 j6 := binary.LittleEndian.Uint32(k[8:12])
22 j7 := binary.LittleEndian.Uint32(k[12:16])
23 j8 := binary.LittleEndian.Uint32(k[16:20])
24 j9 := binary.LittleEndian.Uint32(k[20:24])
25 j10 := binary.LittleEndian.Uint32(k[24:28])
26 j11 := binary.LittleEndian.Uint32(k[28:32])
27 j12 := binary.LittleEndian.Uint32(in[0:4])
28 j13 := binary.LittleEndian.Uint32(in[4:8])
29 j14 := binary.LittleEndian.Uint32(in[8:12])
30 j15 := binary.LittleEndian.Uint32(in[12:16])
32 x0, x1, x2, x3, x4, x5, x6, x7 := j0, j1, j2, j3, j4, j5, j6, j7
33 x8, x9, x10, x11, x12, x13, x14, x15 := j8, j9, j10, j11, j12, j13, j14, j15
35 for i := 0; i < rounds; i += 2 {
38 x12 = (x12 << 16) | (x12 >> (16))
41 x4 = (x4 << 12) | (x4 >> (20))
44 x12 = (x12 << 8) | (x12 >> (24))
47 x4 = (x4 << 7) | (x4 >> (25))
50 x13 = (x13 << 16) | (x13 >> 16)
53 x5 = (x5 << 12) | (x5 >> 20)
56 x13 = (x13 << 8) | (x13 >> 24)
59 x5 = (x5 << 7) | (x5 >> 25)
62 x14 = (x14 << 16) | (x14 >> 16)
65 x6 = (x6 << 12) | (x6 >> 20)
68 x14 = (x14 << 8) | (x14 >> 24)
71 x6 = (x6 << 7) | (x6 >> 25)
74 x15 = (x15 << 16) | (x15 >> 16)
77 x7 = (x7 << 12) | (x7 >> 20)
80 x15 = (x15 << 8) | (x15 >> 24)
83 x7 = (x7 << 7) | (x7 >> 25)
86 x15 = (x15 << 16) | (x15 >> 16)
89 x5 = (x5 << 12) | (x5 >> 20)
92 x15 = (x15 << 8) | (x15 >> 24)
95 x5 = (x5 << 7) | (x5 >> 25)
98 x12 = (x12 << 16) | (x12 >> 16)
101 x6 = (x6 << 12) | (x6 >> 20)
104 x12 = (x12 << 8) | (x12 >> 24)
107 x6 = (x6 << 7) | (x6 >> 25)
110 x13 = (x13 << 16) | (x13 >> 16)
113 x7 = (x7 << 12) | (x7 >> 20)
116 x13 = (x13 << 8) | (x13 >> 24)
119 x7 = (x7 << 7) | (x7 >> 25)
122 x14 = (x14 << 16) | (x14 >> 16)
125 x4 = (x4 << 12) | (x4 >> 20)
128 x14 = (x14 << 8) | (x14 >> 24)
131 x4 = (x4 << 7) | (x4 >> 25)
151 binary.LittleEndian.PutUint32(out[0:4], x0)
152 binary.LittleEndian.PutUint32(out[4:8], x1)
153 binary.LittleEndian.PutUint32(out[8:12], x2)
154 binary.LittleEndian.PutUint32(out[12:16], x3)
155 binary.LittleEndian.PutUint32(out[16:20], x4)
156 binary.LittleEndian.PutUint32(out[20:24], x5)
157 binary.LittleEndian.PutUint32(out[24:28], x6)
158 binary.LittleEndian.PutUint32(out[28:32], x7)
159 binary.LittleEndian.PutUint32(out[32:36], x8)
160 binary.LittleEndian.PutUint32(out[36:40], x9)
161 binary.LittleEndian.PutUint32(out[40:44], x10)
162 binary.LittleEndian.PutUint32(out[44:48], x11)
163 binary.LittleEndian.PutUint32(out[48:52], x12)
164 binary.LittleEndian.PutUint32(out[52:56], x13)
165 binary.LittleEndian.PutUint32(out[56:60], x14)
166 binary.LittleEndian.PutUint32(out[60:64], x15)
169 // XORKeyStream crypts bytes from in to out using the given key and counters.
170 // In and out may be the same slice but otherwise should not overlap. Counter
171 // contains the raw ChaCha20 counter bytes (i.e. block counter followed by
173 func XORKeyStream(out, in []byte, counter *[16]byte, key *[32]byte) {
175 var counterCopy [16]byte
176 copy(counterCopy[:], counter[:])
179 core(&block, &counterCopy, key)
180 for i, x := range block {
184 for i := 0; i < 4; i++ {
185 u += uint32(counterCopy[i])
186 counterCopy[i] = byte(u)
194 core(&block, &counterCopy, key)
195 for i, v := range in {
196 out[i] = v ^ block[i]