1 /*
2 chacha-merged.c version 20080118
3 D. J. Bernstein
4 Public domain.
5 */
6
7 /* $OpenBSD: chacha.c,v 1.1 2013/11/21 00:45:44 djm Exp $ */
8
9 #include <sys/cdefs.h>
10 __FBSDID("$FreeBSD: stable/12/sys/crypto/chacha20/chacha.c 371611 2022-02-12 22:59:20Z obrien $");
11
12 #include <sys/param.h>
13 #include <sys/types.h>
14
15 #include <crypto/chacha20/chacha.h>
16
17 typedef uint8_t u8;
18 typedef uint32_t u32;
19
20 typedef struct chacha_ctx chacha_ctx;
21
22 #define U8C(v) (v##U)
23 #define U32C(v) (v##U)
24
25 #define U8V(v) ((u8)(v) & U8C(0xFF))
26 #define U32V(v) ((u32)(v) & U32C(0xFFFFFFFF))
27
28 #define ROTL32(v, n) \
29 (U32V((v) << (n)) | ((v) >> (32 - (n))))
30
31 #define U8TO32_LITTLE(p) \
32 (((u32)((p)[0]) ) | \
33 ((u32)((p)[1]) << 8) | \
34 ((u32)((p)[2]) << 16) | \
35 ((u32)((p)[3]) << 24))
36
37 #define U32TO8_LITTLE(p, v) \
38 do { \
39 (p)[0] = U8V((v) ); \
40 (p)[1] = U8V((v) >> 8); \
41 (p)[2] = U8V((v) >> 16); \
42 (p)[3] = U8V((v) >> 24); \
43 } while (0)
44
45 #define ROTATE(v,c) (ROTL32(v,c))
46 #define XOR(v,w) ((v) ^ (w))
47 #define PLUS(v,w) (U32V((v) + (w)))
48 #define PLUSONE(v) (PLUS((v),1))
49
50 #define QUARTERROUND(a,b,c,d) \
51 a = PLUS(a,b); d = ROTATE(XOR(d,a),16); \
52 c = PLUS(c,d); b = ROTATE(XOR(b,c),12); \
53 a = PLUS(a,b); d = ROTATE(XOR(d,a), 8); \
54 c = PLUS(c,d); b = ROTATE(XOR(b,c), 7);
55
56 static const char sigma[16] = "expand 32-byte k";
57 static const char tau[16] = "expand 16-byte k";
58
59 LOCAL void
chacha_keysetup(chacha_ctx * x,const u8 * k,u32 kbits)60 chacha_keysetup(chacha_ctx *x,const u8 *k,u32 kbits)
61 {
62 const char *constants;
63
64 x->input[4] = U8TO32_LITTLE(k + 0);
65 x->input[5] = U8TO32_LITTLE(k + 4);
66 x->input[6] = U8TO32_LITTLE(k + 8);
67 x->input[7] = U8TO32_LITTLE(k + 12);
68 if (kbits == 256) { /* recommended */
69 k += 16;
70 constants = sigma;
71 } else { /* kbits == 128 */
72 constants = tau;
73 }
74 x->input[8] = U8TO32_LITTLE(k + 0);
75 x->input[9] = U8TO32_LITTLE(k + 4);
76 x->input[10] = U8TO32_LITTLE(k + 8);
77 x->input[11] = U8TO32_LITTLE(k + 12);
78 x->input[0] = U8TO32_LITTLE(constants + 0);
79 x->input[1] = U8TO32_LITTLE(constants + 4);
80 x->input[2] = U8TO32_LITTLE(constants + 8);
81 x->input[3] = U8TO32_LITTLE(constants + 12);
82 }
83
84 LOCAL void
chacha_ivsetup(chacha_ctx * x,const u8 * iv,const u8 * counter)85 chacha_ivsetup(chacha_ctx *x, const u8 *iv, const u8 *counter)
86 {
87 #ifndef CHACHA_NONCE0_CTR128
88 x->input[12] = counter == NULL ? 0 : U8TO32_LITTLE(counter + 0);
89 x->input[13] = counter == NULL ? 0 : U8TO32_LITTLE(counter + 4);
90 x->input[14] = U8TO32_LITTLE(iv + 0);
91 x->input[15] = U8TO32_LITTLE(iv + 4);
92 #else
93 // CHACHA_STATELEN
94 (void)iv;
95 x->input[12] = U8TO32_LITTLE(counter + 0);
96 x->input[13] = U8TO32_LITTLE(counter + 4);
97 x->input[14] = U8TO32_LITTLE(counter + 8);
98 x->input[15] = U8TO32_LITTLE(counter + 12);
99 #endif
100 }
101
102 #ifdef CHACHA_NONCE0_CTR128
103 LOCAL void
chacha_ctrsave(const chacha_ctx * x,u8 * counter)104 chacha_ctrsave(const chacha_ctx *x, u8 *counter)
105 {
106 U32TO8_LITTLE(counter + 0, x->input[12]);
107 U32TO8_LITTLE(counter + 4, x->input[13]);
108 U32TO8_LITTLE(counter + 8, x->input[14]);
109 U32TO8_LITTLE(counter + 12, x->input[15]);
110 }
111 #endif
112
113 LOCAL void
chacha_encrypt_bytes(chacha_ctx * x,const u8 * m,u8 * c,u32 bytes)114 chacha_encrypt_bytes(chacha_ctx *x,const u8 *m,u8 *c,u32 bytes)
115 {
116 u32 x0, x1, x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, x12, x13, x14, x15;
117 u32 j0, j1, j2, j3, j4, j5, j6, j7, j8, j9, j10, j11, j12, j13, j14, j15;
118 u8 *ctarget = NULL;
119 u8 tmp[64];
120 u_int i;
121
122 if (!bytes) return;
123
124 j0 = x->input[0];
125 j1 = x->input[1];
126 j2 = x->input[2];
127 j3 = x->input[3];
128 j4 = x->input[4];
129 j5 = x->input[5];
130 j6 = x->input[6];
131 j7 = x->input[7];
132 j8 = x->input[8];
133 j9 = x->input[9];
134 j10 = x->input[10];
135 j11 = x->input[11];
136 j12 = x->input[12];
137 j13 = x->input[13];
138 j14 = x->input[14];
139 j15 = x->input[15];
140
141 for (;;) {
142 if (bytes < 64) {
143 for (i = 0;i < bytes;++i) tmp[i] = m[i];
144 m = tmp;
145 ctarget = c;
146 c = tmp;
147 }
148 x0 = j0;
149 x1 = j1;
150 x2 = j2;
151 x3 = j3;
152 x4 = j4;
153 x5 = j5;
154 x6 = j6;
155 x7 = j7;
156 x8 = j8;
157 x9 = j9;
158 x10 = j10;
159 x11 = j11;
160 x12 = j12;
161 x13 = j13;
162 x14 = j14;
163 x15 = j15;
164 for (i = 20;i > 0;i -= 2) {
165 QUARTERROUND( x0, x4, x8,x12)
166 QUARTERROUND( x1, x5, x9,x13)
167 QUARTERROUND( x2, x6,x10,x14)
168 QUARTERROUND( x3, x7,x11,x15)
169 QUARTERROUND( x0, x5,x10,x15)
170 QUARTERROUND( x1, x6,x11,x12)
171 QUARTERROUND( x2, x7, x8,x13)
172 QUARTERROUND( x3, x4, x9,x14)
173 }
174 x0 = PLUS(x0,j0);
175 x1 = PLUS(x1,j1);
176 x2 = PLUS(x2,j2);
177 x3 = PLUS(x3,j3);
178 x4 = PLUS(x4,j4);
179 x5 = PLUS(x5,j5);
180 x6 = PLUS(x6,j6);
181 x7 = PLUS(x7,j7);
182 x8 = PLUS(x8,j8);
183 x9 = PLUS(x9,j9);
184 x10 = PLUS(x10,j10);
185 x11 = PLUS(x11,j11);
186 x12 = PLUS(x12,j12);
187 x13 = PLUS(x13,j13);
188 x14 = PLUS(x14,j14);
189 x15 = PLUS(x15,j15);
190
191 #ifndef KEYSTREAM_ONLY
192 x0 = XOR(x0,U8TO32_LITTLE(m + 0));
193 x1 = XOR(x1,U8TO32_LITTLE(m + 4));
194 x2 = XOR(x2,U8TO32_LITTLE(m + 8));
195 x3 = XOR(x3,U8TO32_LITTLE(m + 12));
196 x4 = XOR(x4,U8TO32_LITTLE(m + 16));
197 x5 = XOR(x5,U8TO32_LITTLE(m + 20));
198 x6 = XOR(x6,U8TO32_LITTLE(m + 24));
199 x7 = XOR(x7,U8TO32_LITTLE(m + 28));
200 x8 = XOR(x8,U8TO32_LITTLE(m + 32));
201 x9 = XOR(x9,U8TO32_LITTLE(m + 36));
202 x10 = XOR(x10,U8TO32_LITTLE(m + 40));
203 x11 = XOR(x11,U8TO32_LITTLE(m + 44));
204 x12 = XOR(x12,U8TO32_LITTLE(m + 48));
205 x13 = XOR(x13,U8TO32_LITTLE(m + 52));
206 x14 = XOR(x14,U8TO32_LITTLE(m + 56));
207 x15 = XOR(x15,U8TO32_LITTLE(m + 60));
208 #endif
209
210 j12 = PLUSONE(j12);
211 if (!j12) {
212 j13 = PLUSONE(j13);
213 #ifndef CHACHA_NONCE0_CTR128
214 /* stopping at 2^70 bytes per nonce is user's responsibility */
215 #else
216 if (!j13) {
217 j14 = PLUSONE(j14);
218 if (!j14) {
219 j15 = PLUSONE(j15);
220 }
221 }
222 #endif
223 }
224
225 U32TO8_LITTLE(c + 0,x0);
226 U32TO8_LITTLE(c + 4,x1);
227 U32TO8_LITTLE(c + 8,x2);
228 U32TO8_LITTLE(c + 12,x3);
229 U32TO8_LITTLE(c + 16,x4);
230 U32TO8_LITTLE(c + 20,x5);
231 U32TO8_LITTLE(c + 24,x6);
232 U32TO8_LITTLE(c + 28,x7);
233 U32TO8_LITTLE(c + 32,x8);
234 U32TO8_LITTLE(c + 36,x9);
235 U32TO8_LITTLE(c + 40,x10);
236 U32TO8_LITTLE(c + 44,x11);
237 U32TO8_LITTLE(c + 48,x12);
238 U32TO8_LITTLE(c + 52,x13);
239 U32TO8_LITTLE(c + 56,x14);
240 U32TO8_LITTLE(c + 60,x15);
241
242 if (bytes <= 64) {
243 if (bytes < 64) {
244 for (i = 0;i < bytes;++i) ctarget[i] = c[i];
245 }
246 x->input[12] = j12;
247 x->input[13] = j13;
248 #ifdef CHACHA_NONCE0_CTR128
249 x->input[14] = j14;
250 x->input[15] = j15;
251 #endif
252 return;
253 }
254 bytes -= 64;
255 c += 64;
256 #ifndef KEYSTREAM_ONLY
257 m += 64;
258 #endif
259 }
260 }
261