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