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