1 /*
2 Copyright (c) 1996, David Mazieres <dm@uun.org>
3 Copyright (c) 2008, Damien Miller <djm@openbsd.org>
4 Copyright (c) 2013, Markus Friedl <markus@openbsd.org>
5 Copyright (c) 2014, Theo de Raadt <deraadt@openbsd.org>
6 
7 Permission to use, copy, modify, and distribute this software for any
8 purpose with or without fee is hereby granted, provided that the above
9 copyright notice and this permission notice appear in all copies.
10 
11 THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
12 WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
13 MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
14 ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
15 WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
16 ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
17 OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
18  */
19 /*
20 chacha-merged.c version 20080118
21 D. J. Bernstein
22 Public domain.
23 */
24 
25 /* $OpenBSD: chacha_private.h,v 1.3 2022/02/28 21:56:29 dtucker Exp $ */
26 
27 #include <stdint.h>
28 
29 typedef uint8_t u8;
30 typedef uint32_t u32;
31 
32 typedef struct
33 {
34   u32 input[16]; /* could be compressed */
35 } chacha_ctx;
36 
37 #define U8V(v) ((u8)(v))
38 #define U32V(v) ((u32)(v))
39 
40 #define ROTL32(v, n) \
41   (U32V((v) << (n)) | ((v) >> (32 - (n))))
42 
43 #define U8TO32_LITTLE(p) \
44   (((u32)((p)[0])      ) | \
45    ((u32)((p)[1]) <<  8) | \
46    ((u32)((p)[2]) << 16) | \
47    ((u32)((p)[3]) << 24))
48 
49 #define U32TO8_LITTLE(p, v) \
50   do { \
51     (p)[0] = U8V((v)      ); \
52     (p)[1] = U8V((v) >>  8); \
53     (p)[2] = U8V((v) >> 16); \
54     (p)[3] = U8V((v) >> 24); \
55   } while (0)
56 
57 #define ROTATE(v,c) (ROTL32(v,c))
58 #define XOR(v,w) ((v) ^ (w))
59 #define PLUS(v,w) (U32V((v) + (w)))
60 #define PLUSONE(v) (PLUS((v),1))
61 
62 #define QUARTERROUND(a,b,c,d) \
63   a = PLUS(a,b); d = ROTATE(XOR(d,a),16); \
64   c = PLUS(c,d); b = ROTATE(XOR(b,c),12); \
65   a = PLUS(a,b); d = ROTATE(XOR(d,a), 8); \
66   c = PLUS(c,d); b = ROTATE(XOR(b,c), 7);
67 
68 static const char sigma[16] = "expand 32-byte k";
69 static const char tau[16] = "expand 16-byte k";
70 
71 static void
chacha_keysetup(chacha_ctx * x,const u8 * k,u32 kbits)72 chacha_keysetup(chacha_ctx *x,const u8 *k,u32 kbits)
73 {
74   const char *constants;
75 
76   x->input[4] = U8TO32_LITTLE(k + 0);
77   x->input[5] = U8TO32_LITTLE(k + 4);
78   x->input[6] = U8TO32_LITTLE(k + 8);
79   x->input[7] = U8TO32_LITTLE(k + 12);
80   if (kbits == 256) { /* recommended */
81     k += 16;
82     constants = sigma;
83   } else { /* kbits == 128 */
84     constants = tau;
85   }
86   x->input[8] = U8TO32_LITTLE(k + 0);
87   x->input[9] = U8TO32_LITTLE(k + 4);
88   x->input[10] = U8TO32_LITTLE(k + 8);
89   x->input[11] = U8TO32_LITTLE(k + 12);
90   x->input[0] = U8TO32_LITTLE(constants + 0);
91   x->input[1] = U8TO32_LITTLE(constants + 4);
92   x->input[2] = U8TO32_LITTLE(constants + 8);
93   x->input[3] = U8TO32_LITTLE(constants + 12);
94 }
95 
96 static void
chacha_ivsetup(chacha_ctx * x,const u8 * iv)97 chacha_ivsetup(chacha_ctx *x,const u8 *iv)
98 {
99   x->input[12] = 0;
100   x->input[13] = 0;
101   x->input[14] = U8TO32_LITTLE(iv + 0);
102   x->input[15] = U8TO32_LITTLE(iv + 4);
103 }
104 
105 static void
chacha_encrypt_bytes(chacha_ctx * x,const u8 * m,u8 * c,u32 bytes)106 chacha_encrypt_bytes(chacha_ctx *x,const u8 *m,u8 *c,u32 bytes)
107 {
108   u32 x0, x1, x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, x12, x13, x14, x15;
109   u32 j0, j1, j2, j3, j4, j5, j6, j7, j8, j9, j10, j11, j12, j13, j14, j15;
110   u8 *ctarget = NULL;
111   u8 tmp[64];
112   u_int i;
113 
114   if (!bytes) return;
115 
116   j0 = x->input[0];
117   j1 = x->input[1];
118   j2 = x->input[2];
119   j3 = x->input[3];
120   j4 = x->input[4];
121   j5 = x->input[5];
122   j6 = x->input[6];
123   j7 = x->input[7];
124   j8 = x->input[8];
125   j9 = x->input[9];
126   j10 = x->input[10];
127   j11 = x->input[11];
128   j12 = x->input[12];
129   j13 = x->input[13];
130   j14 = x->input[14];
131   j15 = x->input[15];
132 
133   for (;;) {
134     if (bytes < 64) {
135       for (i = 0;i < bytes;++i) tmp[i] = m[i];
136       m = tmp;
137       ctarget = c;
138       c = tmp;
139     }
140     x0 = j0;
141     x1 = j1;
142     x2 = j2;
143     x3 = j3;
144     x4 = j4;
145     x5 = j5;
146     x6 = j6;
147     x7 = j7;
148     x8 = j8;
149     x9 = j9;
150     x10 = j10;
151     x11 = j11;
152     x12 = j12;
153     x13 = j13;
154     x14 = j14;
155     x15 = j15;
156     for (i = 20;i > 0;i -= 2) {
157       QUARTERROUND( x0, x4, x8,x12)
158       QUARTERROUND( x1, x5, x9,x13)
159       QUARTERROUND( x2, x6,x10,x14)
160       QUARTERROUND( x3, x7,x11,x15)
161       QUARTERROUND( x0, x5,x10,x15)
162       QUARTERROUND( x1, x6,x11,x12)
163       QUARTERROUND( x2, x7, x8,x13)
164       QUARTERROUND( x3, x4, x9,x14)
165     }
166     x0 = PLUS(x0,j0);
167     x1 = PLUS(x1,j1);
168     x2 = PLUS(x2,j2);
169     x3 = PLUS(x3,j3);
170     x4 = PLUS(x4,j4);
171     x5 = PLUS(x5,j5);
172     x6 = PLUS(x6,j6);
173     x7 = PLUS(x7,j7);
174     x8 = PLUS(x8,j8);
175     x9 = PLUS(x9,j9);
176     x10 = PLUS(x10,j10);
177     x11 = PLUS(x11,j11);
178     x12 = PLUS(x12,j12);
179     x13 = PLUS(x13,j13);
180     x14 = PLUS(x14,j14);
181     x15 = PLUS(x15,j15);
182 
183 #ifndef KEYSTREAM_ONLY
184     x0 = XOR(x0,U8TO32_LITTLE(m + 0));
185     x1 = XOR(x1,U8TO32_LITTLE(m + 4));
186     x2 = XOR(x2,U8TO32_LITTLE(m + 8));
187     x3 = XOR(x3,U8TO32_LITTLE(m + 12));
188     x4 = XOR(x4,U8TO32_LITTLE(m + 16));
189     x5 = XOR(x5,U8TO32_LITTLE(m + 20));
190     x6 = XOR(x6,U8TO32_LITTLE(m + 24));
191     x7 = XOR(x7,U8TO32_LITTLE(m + 28));
192     x8 = XOR(x8,U8TO32_LITTLE(m + 32));
193     x9 = XOR(x9,U8TO32_LITTLE(m + 36));
194     x10 = XOR(x10,U8TO32_LITTLE(m + 40));
195     x11 = XOR(x11,U8TO32_LITTLE(m + 44));
196     x12 = XOR(x12,U8TO32_LITTLE(m + 48));
197     x13 = XOR(x13,U8TO32_LITTLE(m + 52));
198     x14 = XOR(x14,U8TO32_LITTLE(m + 56));
199     x15 = XOR(x15,U8TO32_LITTLE(m + 60));
200 #endif
201 
202     j12 = PLUSONE(j12);
203     if (!j12) {
204       j13 = PLUSONE(j13);
205       /* stopping at 2^70 bytes per nonce is user's responsibility */
206     }
207 
208     U32TO8_LITTLE(c + 0,x0);
209     U32TO8_LITTLE(c + 4,x1);
210     U32TO8_LITTLE(c + 8,x2);
211     U32TO8_LITTLE(c + 12,x3);
212     U32TO8_LITTLE(c + 16,x4);
213     U32TO8_LITTLE(c + 20,x5);
214     U32TO8_LITTLE(c + 24,x6);
215     U32TO8_LITTLE(c + 28,x7);
216     U32TO8_LITTLE(c + 32,x8);
217     U32TO8_LITTLE(c + 36,x9);
218     U32TO8_LITTLE(c + 40,x10);
219     U32TO8_LITTLE(c + 44,x11);
220     U32TO8_LITTLE(c + 48,x12);
221     U32TO8_LITTLE(c + 52,x13);
222     U32TO8_LITTLE(c + 56,x14);
223     U32TO8_LITTLE(c + 60,x15);
224 
225     if (bytes <= 64) {
226       if (bytes < 64) {
227         for (i = 0;i < bytes;++i) ctarget[i] = c[i];
228       }
229       x->input[12] = j12;
230       x->input[13] = j13;
231       return;
232     }
233     bytes -= 64;
234     c += 64;
235 #ifndef KEYSTREAM_ONLY
236     m += 64;
237 #endif
238   }
239 }
240