chachatest.c revision 1.3
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
24struct 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 */
36struct 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. */
226static void
227crypto_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. */
234static void
235chacha_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. */
246static void
247chacha_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. */
267static void
268chacha_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
280struct chacha_test_function {
281	char *name;
282	void (*func)(struct chacha_tv *, unsigned char *, unsigned char *);
283};
284
285struct 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
294int
295main(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