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