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