1 /*
2  * Copyright (c) 2014 Joel Sing <jsing@openbsd.org>
3  *
4  * Permission to use, copy, modify, and distribute this software for any
5  * purpose with or without fee is hereby granted, provided that the above
6  * copyright notice and this permission notice appear in all copies.
7  *
8  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
9  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
10  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
11  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
12  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
13  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
14  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
15  */
16 
17 #include <err.h>
18 #include <stdio.h>
19 #include <stdlib.h>
20 #include <string.h>
21 
22 #include <openssl/chacha.h>
23 
24 struct chacha_tv {
25 	const char *desc;
26 	const unsigned char key[32];
27 	const unsigned char iv[8];
28 	const size_t len;
29 	const unsigned char out[512];
30 };
31 
32 /*
33  * Test vectors from:
34  *   http://tools.ietf.org/html/draft-strombergson-chacha-test-vectors-01
35  */
36 struct chacha_tv chacha_test_vectors[] = {
37 	{
38 		"TC1: All zero key and IV",
39 		{
40 			0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
41 			0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
42 			0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
43 			0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
44 		},
45 		{
46 			0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
47 		},
48 		64,
49 		{
50 			0x76, 0xb8, 0xe0, 0xad, 0xa0, 0xf1, 0x3d, 0x90,
51 			0x40, 0x5d, 0x6a, 0xe5, 0x53, 0x86, 0xbd, 0x28,
52 			0xbd, 0xd2, 0x19, 0xb8, 0xa0, 0x8d, 0xed, 0x1a,
53 			0xa8, 0x36, 0xef, 0xcc, 0x8b, 0x77, 0x0d, 0xc7,
54 			0xda, 0x41, 0x59, 0x7c, 0x51, 0x57, 0x48, 0x8d,
55 			0x77, 0x24, 0xe0, 0x3f, 0xb8, 0xd8, 0x4a, 0x37,
56 			0x6a, 0x43, 0xb8, 0xf4, 0x15, 0x18, 0xa1, 0x1c,
57 			0xc3, 0x87, 0xb6, 0x69, 0xb2, 0xee, 0x65, 0x86,
58 		},
59 	},
60 	{
61 		"TC2: Single bit in key set, all zero IV",
62 		{
63 			0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
64 			0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
65 			0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
66 			0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
67 		},
68 		{
69 			0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
70 		},
71 		64,
72 		{
73 			0xc5, 0xd3, 0x0a, 0x7c, 0xe1, 0xec, 0x11, 0x93,
74 			0x78, 0xc8, 0x4f, 0x48, 0x7d, 0x77, 0x5a, 0x85,
75 			0x42, 0xf1, 0x3e, 0xce, 0x23, 0x8a, 0x94, 0x55,
76 			0xe8, 0x22, 0x9e, 0x88, 0x8d, 0xe8, 0x5b, 0xbd,
77 			0x29, 0xeb, 0x63, 0xd0, 0xa1, 0x7a, 0x5b, 0x99,
78 			0x9b, 0x52, 0xda, 0x22, 0xbe, 0x40, 0x23, 0xeb,
79 			0x07, 0x62, 0x0a, 0x54, 0xf6, 0xfa, 0x6a, 0xd8,
80 			0x73, 0x7b, 0x71, 0xeb, 0x04, 0x64, 0xda, 0xc0,
81 		},
82 	},
83 	{
84 		"TC3: Single bit in IV set, all zero key",
85 		{
86 			0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
87 			0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
88 			0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
89 			0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
90 		},
91 		{
92 			0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
93 		},
94 		64,
95 		{
96 			0xd9, 0xbf, 0x3f, 0x6b, 0xce, 0x6e, 0xd0, 0xb5,
97 			0x42, 0x54, 0x55, 0x77, 0x67, 0xfb, 0x57, 0x44,
98 			0x3d, 0xd4, 0x77, 0x89, 0x11, 0xb6, 0x06, 0x05,
99 			0x5c, 0x39, 0xcc, 0x25, 0xe6, 0x74, 0xb8, 0x36,
100 			0x3f, 0xea, 0xbc, 0x57, 0xfd, 0xe5, 0x4f, 0x79,
101 			0x0c, 0x52, 0xc8, 0xae, 0x43, 0x24, 0x0b, 0x79,
102 			0xd4, 0x90, 0x42, 0xb7, 0x77, 0xbf, 0xd6, 0xcb,
103 			0x80, 0xe9, 0x31, 0x27, 0x0b, 0x7f, 0x50, 0xeb,
104 		},
105 	},
106 	{
107 		"TC4: All bits in key and IV are set",
108 		{
109 			0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55,
110 			0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55,
111 			0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55,
112 			0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55,
113 		},
114 		{
115 			0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
116 		},
117 		64,
118 		{
119 			0xaf, 0xf7, 0x41, 0x82, 0x93, 0xf3, 0xa5, 0x53,
120 			0x89, 0x4b, 0x1e, 0x74, 0x84, 0xbd, 0x1e, 0x8e,
121 			0xde, 0x19, 0x6e, 0xce, 0xd5, 0xa1, 0xd6, 0x81,
122 			0x4d, 0xe3, 0x70, 0x91, 0xe0, 0x7e, 0x07, 0x6e,
123 			0x34, 0xbb, 0xba, 0x81, 0x07, 0xa6, 0x86, 0xc9,
124 			0x82, 0x85, 0x0f, 0x0a, 0x73, 0x53, 0x94, 0x0d,
125 			0x40, 0xdb, 0x1a, 0xb0, 0xb5, 0x76, 0x5b, 0x78,
126 			0xb4, 0xcf, 0x47, 0x3d, 0x94, 0x85, 0xa3, 0xdd,
127 		},
128 	},
129 	{
130 		"TC5: Every even bit set in key and IV",
131 		{
132 			0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55,
133 			0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55,
134 			0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55,
135 			0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55,
136 		},
137 		{
138 			0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55,
139 		},
140 		64,
141 		{
142 			0xbe, 0xa9, 0x41, 0x1a, 0xa4, 0x53, 0xc5, 0x43,
143 			0x4a, 0x5a, 0xe8, 0xc9, 0x28, 0x62, 0xf5, 0x64,
144 			0x39, 0x68, 0x55, 0xa9, 0xea, 0x6e, 0x22, 0xd6,
145 			0xd3, 0xb5, 0x0a, 0xe1, 0xb3, 0x66, 0x33, 0x11,
146 			0xa4, 0xa3, 0x60, 0x6c, 0x67, 0x1d, 0x60, 0x5c,
147 			0xe1, 0x6c, 0x3a, 0xec, 0xe8, 0xe6, 0x1e, 0xa1,
148 			0x45, 0xc5, 0x97, 0x75, 0x01, 0x7b, 0xee, 0x2f,
149 			0xa6, 0xf8, 0x8a, 0xfc, 0x75, 0x80, 0x69, 0xf7,
150 		},
151 	},
152 	{
153 		"TC6: Every odd bit set in key and IV",
154 		{
155 			0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
156 			0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
157 			0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
158 			0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
159 		},
160 		{
161 			0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
162 		},
163 		64,
164 		{
165 			0x9a, 0xa2, 0xa9, 0xf6, 0x56, 0xef, 0xde, 0x5a,
166 			0xa7, 0x59, 0x1c, 0x5f, 0xed, 0x4b, 0x35, 0xae,
167 			0xa2, 0x89, 0x5d, 0xec, 0x7c, 0xb4, 0x54, 0x3b,
168 			0x9e, 0x9f, 0x21, 0xf5, 0xe7, 0xbc, 0xbc, 0xf3,
169 			0xc4, 0x3c, 0x74, 0x8a, 0x97, 0x08, 0x88, 0xf8,
170 			0x24, 0x83, 0x93, 0xa0, 0x9d, 0x43, 0xe0, 0xb7,
171 			0xe1, 0x64, 0xbc, 0x4d, 0x0b, 0x0f, 0xb2, 0x40,
172 			0xa2, 0xd7, 0x21, 0x15, 0xc4, 0x80, 0x89, 0x06,
173 		},
174 	},
175 	{
176 		"TC7: Sequence patterns in key and IV",
177 		{
178 			0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77,
179 			0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff,
180 			0xff, 0xee, 0xdd, 0xcc, 0xbb, 0xaa, 0x99, 0x88,
181 			0x77, 0x66, 0x55, 0x44, 0x33, 0x22, 0x11, 0x00,
182 		},
183 		{
184 			0x0f, 0x1e, 0x2d, 0x3c, 0x4b, 0x5a, 0x69, 0x78,
185 		},
186 		64,
187 		{
188 			0x9f, 0xad, 0xf4, 0x09, 0xc0, 0x08, 0x11, 0xd0,
189 			0x04, 0x31, 0xd6, 0x7e, 0xfb, 0xd8, 0x8f, 0xba,
190 			0x59, 0x21, 0x8d, 0x5d, 0x67, 0x08, 0xb1, 0xd6,
191 			0x85, 0x86, 0x3f, 0xab, 0xbb, 0x0e, 0x96, 0x1e,
192 			0xea, 0x48, 0x0f, 0xd6, 0xfb, 0x53, 0x2b, 0xfd,
193 			0x49, 0x4b, 0x21, 0x51, 0x01, 0x50, 0x57, 0x42,
194 			0x3a, 0xb6, 0x0a, 0x63, 0xfe, 0x4f, 0x55, 0xf7,
195 			0xa2, 0x12, 0xe2, 0x16, 0x7c, 0xca, 0xb9, 0x31,
196 		},
197 	},
198 	{
199 		"TC8: key: 'All your base are belong to us!, IV: 'IETF2013'",
200 		{
201 			0xc4, 0x6e, 0xc1, 0xb1, 0x8c, 0xe8, 0xa8, 0x78,
202 			0x72, 0x5a, 0x37, 0xe7, 0x80, 0xdf, 0xb7, 0x35,
203 			0x1f, 0x68, 0xed, 0x2e, 0x19, 0x4c, 0x79, 0xfb,
204 			0xc6, 0xae, 0xbe, 0xe1, 0xa6, 0x67, 0x97, 0x5d,
205 		},
206 		{
207 			0x1a, 0xda, 0x31, 0xd5, 0xcf, 0x68, 0x82, 0x21,
208 		},
209 		64,
210 		{
211 			0xf6, 0x3a, 0x89, 0xb7, 0x5c, 0x22, 0x71, 0xf9,
212 			0x36, 0x88, 0x16, 0x54, 0x2b, 0xa5, 0x2f, 0x06,
213 			0xed, 0x49, 0x24, 0x17, 0x92, 0x30, 0x2b, 0x00,
214 			0xb5, 0xe8, 0xf8, 0x0a, 0xe9, 0xa4, 0x73, 0xaf,
215 			0xc2, 0x5b, 0x21, 0x8f, 0x51, 0x9a, 0xf0, 0xfd,
216 			0xd4, 0x06, 0x36, 0x2e, 0x8d, 0x69, 0xde, 0x7f,
217 			0x54, 0xc6, 0x04, 0xa6, 0xe0, 0x0f, 0x35, 0x3f,
218 			0x11, 0x0f, 0x77, 0x1b, 0xdc, 0xa8, 0xab, 0x92,
219 		},
220 	},
221 };
222 
223 #define N_VECTORS (sizeof(chacha_test_vectors) / sizeof(*chacha_test_vectors))
224 
225 /* Single-shot ChaCha20 using CRYPTO_chacha_20 interface. */
226 static void
227 crypto_chacha_20_test(struct chacha_tv *tv, unsigned char *out,
228     unsigned char *in)
229 {
230 	CRYPTO_chacha_20(out, in, tv->len, tv->key, tv->iv, 0);
231 }
232 
233 /* Single-shot ChaCha20 using the ChaCha interface. */
234 static void
235 chacha_ctx_full_test(struct chacha_tv *tv, unsigned char *out,
236     unsigned char *in)
237 {
238 	ChaCha_ctx ctx;
239 
240 	ChaCha_set_key(&ctx, tv->key, 256);
241 	ChaCha_set_iv(&ctx, tv->iv, NULL);
242 	ChaCha(&ctx, out, in, tv->len);
243 }
244 
245 /* ChaCha20 with partial writes using the Chacha interface. */
246 static void
247 chacha_ctx_partial_test(struct chacha_tv *tv, unsigned char *out,
248     unsigned char *in)
249 {
250 	ChaCha_ctx ctx;
251 	int len, size = 0;
252 
253 	ChaCha_set_key(&ctx, tv->key, 256);
254 	ChaCha_set_iv(&ctx, tv->iv, NULL);
255 	len = tv->len - 1;
256 	while (len > 1) {
257 		size = len / 2;
258 		ChaCha(&ctx, out, in, size);
259 		in += size;
260 		out += size;
261 		len -= size;
262 	}
263 	ChaCha(&ctx, out, in, len + 1);
264 }
265 
266 /* ChaCha20 with single byte writes using the Chacha interface. */
267 static void
268 chacha_ctx_single_test(struct chacha_tv *tv, unsigned char *out,
269     unsigned char *in)
270 {
271 	ChaCha_ctx ctx;
272 	size_t i;
273 
274 	ChaCha_set_key(&ctx, tv->key, 256);
275 	ChaCha_set_iv(&ctx, tv->iv, NULL);
276 	for (i = 0; i < tv->len; i++)
277 		ChaCha(&ctx, out + i, in + i, 1);
278 }
279 
280 struct chacha_test_function {
281 	char *name;
282 	void (*func)(struct chacha_tv *, unsigned char *, unsigned char *);
283 };
284 
285 struct chacha_test_function chacha_test_functions[] = {
286 	{"crypto_chacha_20_test", crypto_chacha_20_test},
287 	{"chacha_ctx_full_test", chacha_ctx_full_test},
288 	{"chacha_ctx_partial_test", chacha_ctx_partial_test},
289 	{"chacha_ctx_single_test", chacha_ctx_single_test},
290 };
291 
292 #define N_FUNCS (sizeof(chacha_test_functions) / sizeof(*chacha_test_functions))
293 
294 int
295 main(int argc, char **argv)
296 {
297 	struct chacha_tv *tv;
298 	unsigned char *in, *out;
299 	size_t i, j, k;
300 	int failed = 0;
301 
302 	for (i = 0; i < N_VECTORS; i++) {
303 		tv = &chacha_test_vectors[i];
304 
305 		for (j = 0; j < N_FUNCS; j++) {
306 			in = calloc(1, tv->len);
307 			if (in == NULL)
308 				errx(1, "calloc in");
309 			out = calloc(1, tv->len);
310 			if (out == NULL)
311 				errx(1, "calloc out");
312 
313 			chacha_test_functions[j].func(tv, out, in);
314 
315 			if (memcmp(out, tv->out, tv->len) != 0) {
316 				printf("ChaCha %s failed for \"%s\"!\n",
317 				    chacha_test_functions[j].name, tv->desc);
318 
319 				printf("Got:\t");
320 				for (k = 0; k < tv->len; k++)
321 					printf("%2.2x", out[k]);
322 				printf("\n");
323 
324 				printf("Want:\t");
325 				for (k = 0; k < tv->len; k++)
326 					printf("%2.2x", tv->out[k]);
327 				printf("\n");
328 
329 				failed = 1;
330 			}
331 
332 			free(in);
333 			free(out);
334 		}
335 	}
336 
337 	return failed;
338 }
339