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