1249259Sdim/*	$NetBSD: chacha_selftest.c,v 1.1 2020/07/25 22:46:34 riastradh Exp $	*/
2249259Sdim
3249259Sdim/*-
4249259Sdim * Copyright (c) 2020 The NetBSD Foundation, Inc.
5249259Sdim * All rights reserved.
6249259Sdim *
7249259Sdim * Redistribution and use in source and binary forms, with or without
8249259Sdim * modification, are permitted provided that the following conditions
9249259Sdim * are met:
10249259Sdim * 1. Redistributions of source code must retain the above copyright
11249259Sdim *    notice, this list of conditions and the following disclaimer.
12249259Sdim * 2. Redistributions in binary form must reproduce the above copyright
13249259Sdim *    notice, this list of conditions and the following disclaimer in the
14249259Sdim *    documentation and/or other materials provided with the distribution.
15249259Sdim *
16249259Sdim * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
17249259Sdim * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
18249259Sdim * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
19249259Sdim * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
20249259Sdim * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
21249259Sdim * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
22249259Sdim * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
23249259Sdim * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
24249259Sdim * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
25249259Sdim * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
26249259Sdim * POSSIBILITY OF SUCH DAMAGE.
27249259Sdim */
28249259Sdim
29249259Sdim#include "chacha_impl.h"
30249259Sdim
31249259Sdim#ifdef _KERNEL
32249259Sdim
33249259Sdim#include <lib/libkern/libkern.h>
34249259Sdim
35249259Sdim#else
36263508Sdim
37249259Sdim#include <stdio.h>
38249259Sdim#include <string.h>
39249259Sdim
40249259Sdimstatic void
41249259Sdimhexdump(int (*prf)(const char *, ...) __printflike(1,2), const char *prefix,
42249259Sdim    const void *buf, size_t len)
43249259Sdim{
44249259Sdim	const uint8_t *p = buf;
45249259Sdim	size_t i;
46249259Sdim
47249259Sdim	(*prf)("%s (%zu bytes @ %p)\n", prefix, len, buf);
48249259Sdim	for (i = 0; i < len; i++) {
49249259Sdim		if (i % 16 == 8)
50249259Sdim			(*prf)("  ");
51249259Sdim		else
52249259Sdim			(*prf)(" ");
53249259Sdim		(*prf)("%02hhx", p[i]);
54249259Sdim		if ((i + 1) % 16 == 0)
55249259Sdim			(*prf)("\n");
56249259Sdim	}
57249259Sdim	if (i % 16)
58249259Sdim		(*prf)("\n");
59249259Sdim}
60249259Sdim
61249259Sdim#endif
62249259Sdim
63263508Sdim/* https://tools.ietf.org/html/draft-strombergson-chacha-test-vectors-00 */
64263508Sdimstatic int
65249259Sdimchacha_core_selftest(const struct chacha_impl *ci)
66249259Sdim{
67249259Sdim	/* TC1, 32-byte key, rounds=12, keystream block 1 */
68263508Sdim	static const uint8_t zero[32];
69263508Sdim	static const uint8_t expected0[64] = {
70263508Sdim		0x9b,0xf4,0x9a,0x6a, 0x07,0x55,0xf9,0x53,
71249259Sdim		0x81,0x1f,0xce,0x12, 0x5f,0x26,0x83,0xd5,
72263508Sdim		0x04,0x29,0xc3,0xbb, 0x49,0xe0,0x74,0x14,
73263508Sdim		0x7e,0x00,0x89,0xa5, 0x2e,0xae,0x15,0x5f,
74249259Sdim		0x05,0x64,0xf8,0x79, 0xd2,0x7a,0xe3,0xc0,
75263508Sdim		0x2c,0xe8,0x28,0x34, 0xac,0xfa,0x8c,0x79,
76249259Sdim		0x3a,0x62,0x9f,0x2c, 0xa0,0xde,0x69,0x19,
77249259Sdim		0x61,0x0b,0xe8,0x2f, 0x41,0x13,0x26,0xbe,
78249259Sdim	};
79249259Sdim	/* TC7, 32-byte key, rounds=12, keystream block 2 */
80249259Sdim	static const uint8_t k1[32] = {
81249259Sdim		0x00,0x11,0x22,0x33, 0x44,0x55,0x66,0x77,
82249259Sdim		0x88,0x99,0xaa,0xbb, 0xcc,0xdd,0xee,0xff,
83249259Sdim		0xff,0xee,0xdd,0xcc, 0xbb,0xaa,0x99,0x88,
84249259Sdim		0x77,0x66,0x55,0x44, 0x33,0x22,0x11,0x00,
85263508Sdim	};
86249259Sdim	static const uint8_t in1[16] = {
87249259Sdim		0x01,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,
88249259Sdim		0x0f,0x1e,0x2d,0x3c, 0x4b,0x59,0x68,0x77,
89249259Sdim	};
90249259Sdim	static const uint8_t expected1[64] = {
91263508Sdim		0xcd,0x9a,0x2a,0xa9, 0xea,0x93,0xc2,0x67,
92263508Sdim		0x5e,0x82,0x88,0x14, 0x08,0xde,0x85,0x2c,
93263508Sdim		0x62,0xfa,0x74,0x6a, 0x30,0xe5,0x2b,0x45,
94263508Sdim		0xa2,0x69,0x62,0xcf, 0x43,0x51,0xe3,0x04,
95263508Sdim		0xd3,0x13,0x20,0xbb, 0xd6,0xaa,0x6c,0xc8,
96263508Sdim		0xf3,0x26,0x37,0xf9, 0x59,0x34,0xe4,0xc1,
97263508Sdim		0x45,0xef,0xd5,0x62, 0x31,0xef,0x31,0x61,
98263508Sdim		0x03,0x28,0x36,0xf4, 0x96,0x71,0x83,0x3e,
99249259Sdim	};
100249259Sdim	uint8_t out[64];
101249259Sdim	int result = 0;
102249259Sdim
103249259Sdim	(*ci->ci_chacha_core)(out, zero, zero, chacha_const32, 12);
104249259Sdim	if (memcmp(out, expected0, 64)) {
105249259Sdim		hexdump(printf, "chacha core 1", out, sizeof out);
106249259Sdim		result = -1;
107249259Sdim	}
108249259Sdim
109249259Sdim	(*ci->ci_chacha_core)(out, in1, k1, chacha_const32, 12);
110249259Sdim	if (memcmp(out, expected1, 64)) {
111249259Sdim		hexdump(printf, "chacha core 2", out, sizeof out);
112263508Sdim		result = -1;
113263508Sdim	}
114263508Sdim
115263508Sdim	return result;
116263508Sdim}
117263508Sdim
118263508Sdimstatic int
119263508Sdimhchacha_selftest(const struct chacha_impl *ci)
120263508Sdim{
121263508Sdim	/* https://tools.ietf.org/html/draft-irtf-cfrg-xchacha-03, ��2.2.1 */
122263508Sdim	static const uint8_t k[32] = {
123263508Sdim		0x00,0x01,0x02,0x03, 0x04,0x05,0x06,0x07,
124249259Sdim		0x08,0x09,0x0a,0x0b, 0x0c,0x0d,0x0e,0x0f,
125249259Sdim		0x10,0x11,0x12,0x13, 0x14,0x15,0x16,0x17,
126249259Sdim		0x18,0x19,0x1a,0x1b, 0x1c,0x1d,0x1e,0x1f,
127263508Sdim	};
128263508Sdim	static const uint8_t in[16] = {
129263508Sdim		0x00,0x00,0x00,0x09, 0x00,0x00,0x00,0x4a,
130263508Sdim		0x00,0x00,0x00,0x00, 0x31,0x41,0x59,0x27,
131263508Sdim	};
132263508Sdim	static const uint8_t expected[32] = {
133249259Sdim		0x82,0x41,0x3b,0x42, 0x27,0xb2,0x7b,0xfe,
134263508Sdim		0xd3,0x0e,0x42,0x50, 0x8a,0x87,0x7d,0x73,
135263508Sdim		0xa0,0xf9,0xe4,0xd5, 0x8a,0x74,0xa8,0x53,
136249259Sdim		0xc1,0x2e,0xc4,0x13, 0x26,0xd3,0xec,0xdc,
137249259Sdim	};
138249259Sdim	uint8_t out[32];
139249259Sdim	int result = 0;
140249259Sdim
141249259Sdim	(*ci->ci_hchacha)(out, in, k, chacha_const32, 20);
142249259Sdim	if (memcmp(out, expected, 32)) {
143249259Sdim		hexdump(printf, "hchacha", out, sizeof out);
144249259Sdim		result = -1;
145249259Sdim	}
146249259Sdim
147263508Sdim	return result;
148263508Sdim}
149263508Sdim
150263508Sdimstatic int
151263508Sdimchacha_stream_selftest(const struct chacha_impl *ci)
152263508Sdim{
153263508Sdim
154249259Sdim	/* XXX */
155249259Sdim	return 0;
156249259Sdim}
157249259Sdim
158249259Sdimstatic int
159249259Sdimxchacha_stream_selftest(const struct chacha_impl *ci)
160263508Sdim{
161249259Sdim	/* https://tools.ietf.org/html/draft-irtf-cfrg-xchacha-03, A.2.1 */
162249259Sdim	static const uint8_t k[32] = {
163249259Sdim		0x80,0x81,0x82,0x83, 0x84,0x85,0x86,0x87,
164249259Sdim		0x88,0x89,0x8a,0x8b, 0x8c,0x8d,0x8e,0x8f,
165249259Sdim		0x90,0x91,0x92,0x93, 0x94,0x95,0x96,0x97,
166249259Sdim		0x98,0x99,0x9a,0x9b, 0x9c,0x9d,0x9e,0x9f,
167263508Sdim	};
168249259Sdim	static const uint8_t nonce[24] = {
169263508Sdim		0x40,0x41,0x42,0x43, 0x44,0x45,0x46,0x47,
170263508Sdim		0x48,0x49,0x4a,0x4b, 0x4c,0x4d,0x4e,0x4f,
171263508Sdim		0x50,0x51,0x52,0x53, 0x54,0x55,0x56,0x58,
172263508Sdim	};
173263508Sdim	static const uint8_t p[608] = {
174263508Sdim		0x54,0x68,0x65,0x20, 0x64,0x68,0x6f,0x6c,
175249259Sdim		0x65,0x20,0x28,0x70, 0x72,0x6f,0x6e,0x6f,
176249259Sdim		0x75,0x6e,0x63,0x65, 0x64,0x20,0x22,0x64,
177249259Sdim		0x6f,0x6c,0x65,0x22, 0x29,0x20,0x69,0x73,
178249259Sdim		0x20,0x61,0x6c,0x73, 0x6f,0x20,0x6b,0x6e,
179249259Sdim		0x6f,0x77,0x6e,0x20, 0x61,0x73,0x20,0x74,
180263508Sdim		0x68,0x65,0x20,0x41, 0x73,0x69,0x61,0x74,
181249259Sdim		0x69,0x63,0x20,0x77, 0x69,0x6c,0x64,0x20,
182249259Sdim		0x64,0x6f,0x67,0x2c, 0x20,0x72,0x65,0x64,
183251662Sdim		0x20,0x64,0x6f,0x67, 0x2c,0x20,0x61,0x6e,
184251662Sdim		0x64,0x20,0x77,0x68, 0x69,0x73,0x74,0x6c,
185249259Sdim		0x69,0x6e,0x67,0x20, 0x64,0x6f,0x67,0x2e,
186249259Sdim		0x20,0x49,0x74,0x20, 0x69,0x73,0x20,0x61,
187249259Sdim		0x62,0x6f,0x75,0x74, 0x20,0x74,0x68,0x65,
188249259Sdim		0x20,0x73,0x69,0x7a, 0x65,0x20,0x6f,0x66,
189249259Sdim		0x20,0x61,0x20,0x47, 0x65,0x72,0x6d,0x61,
190249259Sdim		0x6e,0x20,0x73,0x68, 0x65,0x70,0x68,0x65,
191249259Sdim		0x72,0x64,0x20,0x62, 0x75,0x74,0x20,0x6c,
192		0x6f,0x6f,0x6b,0x73, 0x20,0x6d,0x6f,0x72,
193		0x65,0x20,0x6c,0x69, 0x6b,0x65,0x20,0x61,
194		0x20,0x6c,0x6f,0x6e, 0x67,0x2d,0x6c,0x65,
195		0x67,0x67,0x65,0x64, 0x20,0x66,0x6f,0x78,
196		0x2e,0x20,0x54,0x68, 0x69,0x73,0x20,0x68,
197		0x69,0x67,0x68,0x6c, 0x79,0x20,0x65,0x6c,
198		0x75,0x73,0x69,0x76, 0x65,0x20,0x61,0x6e,
199		0x64,0x20,0x73,0x6b, 0x69,0x6c,0x6c,0x65,
200		0x64,0x20,0x6a,0x75, 0x6d,0x70,0x65,0x72,
201		0x20,0x69,0x73,0x20, 0x63,0x6c,0x61,0x73,
202		0x73,0x69,0x66,0x69, 0x65,0x64,0x20,0x77,
203		0x69,0x74,0x68,0x20, 0x77,0x6f,0x6c,0x76,
204		0x65,0x73,0x2c,0x20, 0x63,0x6f,0x79,0x6f,
205		0x74,0x65,0x73,0x2c, 0x20,0x6a,0x61,0x63,
206		0x6b,0x61,0x6c,0x73, 0x2c,0x20,0x61,0x6e,
207		0x64,0x20,0x66,0x6f, 0x78,0x65,0x73,0x20,
208		0x69,0x6e,0x20,0x74, 0x68,0x65,0x20,0x74,
209		0x61,0x78,0x6f,0x6e, 0x6f,0x6d,0x69,0x63,
210		0x20,0x66,0x61,0x6d, 0x69,0x6c,0x79,0x20,
211		0x43,0x61,0x6e,0x69, 0x64,0x61,0x65,0x2e,
212
213		0x54,0x68,0x65,0x20, 0x64,0x68,0x6f,0x6c,
214		0x65,0x20,0x28,0x70, 0x72,0x6f,0x6e,0x6f,
215		0x75,0x6e,0x63,0x65, 0x64,0x20,0x22,0x64,
216		0x6f,0x6c,0x65,0x22, 0x29,0x20,0x69,0x73,
217		0x20,0x61,0x6c,0x73, 0x6f,0x20,0x6b,0x6e,
218		0x6f,0x77,0x6e,0x20, 0x61,0x73,0x20,0x74,
219		0x68,0x65,0x20,0x41, 0x73,0x69,0x61,0x74,
220		0x69,0x63,0x20,0x77, 0x69,0x6c,0x64,0x20,
221		0x64,0x6f,0x67,0x2c, 0x20,0x72,0x65,0x64,
222		0x20,0x64,0x6f,0x67, 0x2c,0x20,0x61,0x6e,
223		0x64,0x20,0x77,0x68, 0x69,0x73,0x74,0x6c,
224		0x69,0x6e,0x67,0x20, 0x64,0x6f,0x67,0x2e,
225		0x20,0x49,0x74,0x20, 0x69,0x73,0x20,0x61,
226		0x62,0x6f,0x75,0x74, 0x20,0x74,0x68,0x65,
227		0x20,0x73,0x69,0x7a, 0x65,0x20,0x6f,0x66,
228		0x20,0x61,0x20,0x47, 0x65,0x72,0x6d,0x61,
229		0x6e,0x20,0x73,0x68, 0x65,0x70,0x68,0x65,
230		0x72,0x64,0x20,0x62, 0x75,0x74,0x20,0x6c,
231		0x6f,0x6f,0x6b,0x73, 0x20,0x6d,0x6f,0x72,
232		0x65,0x20,0x6c,0x69, 0x6b,0x65,0x20,0x61,
233		0x20,0x6c,0x6f,0x6e, 0x67,0x2d,0x6c,0x65,
234		0x67,0x67,0x65,0x64, 0x20,0x66,0x6f,0x78,
235		0x2e,0x20,0x54,0x68, 0x69,0x73,0x20,0x68,
236		0x69,0x67,0x68,0x6c, 0x79,0x20,0x65,0x6c,
237		0x75,0x73,0x69,0x76, 0x65,0x20,0x61,0x6e,
238		0x64,0x20,0x73,0x6b, 0x69,0x6c,0x6c,0x65,
239		0x64,0x20,0x6a,0x75, 0x6d,0x70,0x65,0x72,
240		0x20,0x69,0x73,0x20, 0x63,0x6c,0x61,0x73,
241		0x73,0x69,0x66,0x69, 0x65,0x64,0x20,0x77,
242		0x69,0x74,0x68,0x20, 0x77,0x6f,0x6c,0x76,
243		0x65,0x73,0x2c,0x20, 0x63,0x6f,0x79,0x6f,
244		0x74,0x65,0x73,0x2c, 0x20,0x6a,0x61,0x63,
245		0x6b,0x61,0x6c,0x73, 0x2c,0x20,0x61,0x6e,
246		0x64,0x20,0x66,0x6f, 0x78,0x65,0x73,0x20,
247		0x69,0x6e,0x20,0x74, 0x68,0x65,0x20,0x74,
248		0x61,0x78,0x6f,0x6e, 0x6f,0x6d,0x69,0x63,
249		0x20,0x66,0x61,0x6d, 0x69,0x6c,0x79,0x20,
250		0x43,0x61,0x6e,0x69, 0x64,0x61,0x65,0x2e,
251	};
252	static const uint8_t expected[608] = {
253		0x45,0x59,0xab,0xba, 0x4e,0x48,0xc1,0x61,
254		0x02,0xe8,0xbb,0x2c, 0x05,0xe6,0x94,0x7f,
255		0x50,0xa7,0x86,0xde, 0x16,0x2f,0x9b,0x0b,
256		0x7e,0x59,0x2a,0x9b, 0x53,0xd0,0xd4,0xe9,
257		0x8d,0x8d,0x64,0x10, 0xd5,0x40,0xa1,0xa6,
258		0x37,0x5b,0x26,0xd8, 0x0d,0xac,0xe4,0xfa,
259		0xb5,0x23,0x84,0xc7, 0x31,0xac,0xbf,0x16,
260		0xa5,0x92,0x3c,0x0c, 0x48,0xd3,0x57,0x5d,
261		0x4d,0x0d,0x2c,0x67, 0x3b,0x66,0x6f,0xaa,
262		0x73,0x10,0x61,0x27, 0x77,0x01,0x09,0x3a,
263		0x6b,0xf7,0xa1,0x58, 0xa8,0x86,0x42,0x92,
264		0xa4,0x1c,0x48,0xe3, 0xa9,0xb4,0xc0,0xda,
265		0xec,0xe0,0xf8,0xd9, 0x8d,0x0d,0x7e,0x05,
266		0xb3,0x7a,0x30,0x7b, 0xbb,0x66,0x33,0x31,
267		0x64,0xec,0x9e,0x1b, 0x24,0xea,0x0d,0x6c,
268		0x3f,0xfd,0xdc,0xec, 0x4f,0x68,0xe7,0x44,
269		0x30,0x56,0x19,0x3a, 0x03,0xc8,0x10,0xe1,
270		0x13,0x44,0xca,0x06, 0xd8,0xed,0x8a,0x2b,
271		0xfb,0x1e,0x8d,0x48, 0xcf,0xa6,0xbc,0x0e,
272		0xb4,0xe2,0x46,0x4b, 0x74,0x81,0x42,0x40,
273		0x7c,0x9f,0x43,0x1a, 0xee,0x76,0x99,0x60,
274		0xe1,0x5b,0xa8,0xb9, 0x68,0x90,0x46,0x6e,
275		0xf2,0x45,0x75,0x99, 0x85,0x23,0x85,0xc6,
276		0x61,0xf7,0x52,0xce, 0x20,0xf9,0xda,0x0c,
277		0x09,0xab,0x6b,0x19, 0xdf,0x74,0xe7,0x6a,
278		0x95,0x96,0x74,0x46, 0xf8,0xd0,0xfd,0x41,
279		0x5e,0x7b,0xee,0x2a, 0x12,0xa1,0x14,0xc2,
280		0x0e,0xb5,0x29,0x2a, 0xe7,0xa3,0x49,0xae,
281		0x57,0x78,0x20,0xd5, 0x52,0x0a,0x1f,0x3f,
282		0xb6,0x2a,0x17,0xce, 0x6a,0x7e,0x68,0xfa,
283		0x7c,0x79,0x11,0x1d, 0x88,0x60,0x92,0x0b,
284		0xc0,0x48,0xef,0x43, 0xfe,0x84,0x48,0x6c,
285		0xcb,0x87,0xc2,0x5f, 0x0a,0xe0,0x45,0xf0,
286		0xcc,0xe1,0xe7,0x98, 0x9a,0x9a,0xa2,0x20,
287		0xa2,0x8b,0xdd,0x48, 0x27,0xe7,0x51,0xa2,
288		0x4a,0x6d,0x5c,0x62, 0xd7,0x90,0xa6,0x63,
289		0x93,0xb9,0x31,0x11, 0xc1,0xa5,0x5d,0xd7,
290		0x42,0x1a,0x10,0x18, 0x49,0x74,0xc7,0xc5,
291
292		0x08,0x38,0x2d,0x64, 0x35,0x8d,0x21,0x77,
293		0x2e,0xb9,0x73,0xa8, 0x8f,0xb6,0x2b,0xf8,
294		0xce,0xfa,0xb4,0xca, 0x6f,0x0c,0x26,0xbb,
295		0x7f,0xd6,0x6d,0xb2, 0xa0,0xbe,0xb0,0x5a,
296		0x1a,0x6e,0x39,0xcb, 0xd5,0xda,0xf2,0xfc,
297		0x0b,0x74,0x31,0x3d, 0x2e,0xcd,0x5f,0x94,
298		0xc2,0x9f,0x30,0xdb, 0x11,0x5e,0x41,0x53,
299		0x8c,0x6d,0x30,0xba, 0x97,0xa0,0xc5,0x07,
300		0x70,0x78,0x02,0x5a, 0xc1,0x69,0x70,0x8f,
301		0x22,0x85,0xcb,0x98, 0xbc,0x6a,0x51,0xfb,
302		0xc6,0xa7,0xc3,0x3d, 0x76,0xe4,0x93,0x9a,
303		0x21,0xe2,0xc6,0x12, 0xe1,0x3a,0xcc,0xfb,
304		0x6f,0xa6,0x57,0xc0, 0x09,0x8c,0x6f,0xf3,
305		0x8d,0x83,0x21,0x1b, 0x71,0xa9,0xc1,0x93,
306		0x88,0x35,0xfc,0x18, 0x1f,0x94,0xa2,0x57,
307		0x3a,0x4e,0xd0,0xc0, 0xbc,0x92,0xa7,0x9c,
308		0x52,0x8a,0x82,0x9d, 0x44,0x75,0x7b,0xa0,
309		0xcf,0x3d,0x2d,0xbf, 0xf9,0x6f,0x71,0x56,
310		0x38,0xb0,0x63,0x5e, 0x55,0xcd,0x28,0x12,
311		0xc5,0xea,0x52,0xf4, 0xdc,0xf7,0xdc,0x3d,
312		0xd8,0x96,0x09,0xe8, 0x2a,0xcc,0x00,0x16,
313		0x88,0x77,0x82,0x10, 0xed,0x7d,0xd8,0x8b,
314		0xf5,0xd3,0xe1,0xfc, 0x49,0x66,0x36,0x8d,
315		0x55,0xd2,0x33,0xb8, 0x6d,0xff,0xe3,0xd3,
316		0x55,0x80,0x0e,0xd8, 0x95,0x32,0x32,0x55,
317		0x83,0xe7,0x58,0x6f, 0xec,0xc3,0x8c,0xf8,
318		0x52,0x16,0xdc,0x0d, 0x29,0x02,0xe5,0x27,
319		0x35,0xc2,0xbb,0xe2, 0xe2,0x3b,0xf5,0x19,
320		0xcd,0x44,0x83,0xe8, 0x21,0x55,0xd0,0x10,
321		0x15,0x68,0x8e,0x46, 0xa3,0x2f,0xa5,0x7c,
322		0xa8,0x2c,0xc6,0x8f, 0x14,0xcd,0xb3,0x79,
323		0x92,0x32,0x71,0xac, 0xd9,0xaf,0x9c,0x4d,
324		0x00,0x88,0xd1,0x42, 0xd5,0x23,0xfa,0xe6,
325		0x7f,0x38,0xa2,0x56, 0x99,0xbe,0x6f,0xcf,
326		0xe0,0xaa,0x44,0x11, 0x8a,0xc8,0x3a,0x99,
327		0x48,0x6d,0x33,0x0e, 0x94,0xf2,0xb9,0x87,
328		0xed,0x4f,0x6a,0x9c, 0x33,0x93,0x6d,0xe4,
329		0x92,0x76,0xab,0xfa, 0xce,0x5b,0x17,0x14,
330	};
331	uint8_t c[608];
332	unsigned i;
333	int result = 0;
334
335	/*
336	 * 608 = 96 (mod 256)
337	 * 607 = 95 (mod 256), = 7 (mod 8)
338	 * 543 = 31 (mod 256), = 7 (mod 8)
339	 * 511 = 255 (mod 256), = 7 (mod 8)
340	 *
341	 * This exercises several branches when there are special cases
342	 * for integral numbers of 4-byte words, integral numbers of
343	 * 64-byte blocks, and integral numbers of 256-byte chunks.
344	 */
345
346	(*ci->ci_xchacha_stream)(c, 608, 0, nonce, k, 20);
347	for (i = 0; i < 608; i++)
348		c[i] ^= p[i];
349	if (memcmp(c, expected, 608)) {
350		for (i = 0; i < 608; i++)
351			c[i] ^= p[i];
352		hexdump(printf, "xchacha_stream", c, 608);
353		for (i = 0; i < 608; i++)
354			c[i] = expected[i] ^ p[i];
355		hexdump(printf, "expected", c, 608);
356		result = -1;
357	}
358
359	(*ci->ci_xchacha_stream)(c, 607, 0, nonce, k, 20);
360	for (i = 0; i < 607; i++)
361		c[i] ^= p[i];
362	if (memcmp(c, expected, 607)) {
363		for (i = 0; i < 607; i++)
364			c[i] ^= p[i];
365		hexdump(printf, "xchacha_stream", c, 607);
366		for (i = 0; i < 607; i++)
367			c[i] = expected[i] ^ p[i];
368		hexdump(printf, "expected", c, 607);
369		result = -1;
370	}
371
372	(*ci->ci_xchacha_stream)(c, 543, 0, nonce, k, 20);
373	for (i = 0; i < 543; i++)
374		c[i] ^= p[i];
375	if (memcmp(c, expected, 543)) {
376		for (i = 0; i < 543; i++)
377			c[i] ^= p[i];
378		hexdump(printf, "xchacha_stream", c, 543);
379		for (i = 0; i < 543; i++)
380			c[i] = expected[i] ^ p[i];
381		hexdump(printf, "expected", c, 543);
382		result = -1;
383	}
384
385	(*ci->ci_xchacha_stream)(c, 511, 0, nonce, k, 20);
386	for (i = 0; i < 511; i++)
387		c[i] ^= p[i];
388	if (memcmp(c, expected, 511)) {
389		for (i = 0; i < 511; i++)
390			c[i] ^= p[i];
391		hexdump(printf, "xchacha_stream", c, 511);
392		for (i = 0; i < 511; i++)
393			c[i] = expected[i] ^ p[i];
394		hexdump(printf, "expected", c, 511);
395		result = -1;
396	}
397
398	(*ci->ci_xchacha_stream)(c, 63, 0, nonce, k, 20);
399	for (i = 0; i < 63; i++)
400		c[i] ^= p[i];
401	if (memcmp(c, expected, 63)) {
402		for (i = 0; i < 63; i++)
403			c[i] ^= p[i];
404		hexdump(printf, "xchacha_stream", c, 63);
405		for (i = 0; i < 63; i++)
406			c[i] = expected[i] ^ p[i];
407		hexdump(printf, "expected", c, 63);
408		result = -1;
409	}
410
411	(*ci->ci_xchacha_stream_xor)(c, p, 608, 0, nonce, k, 20);
412	if (memcmp(c, expected, 608)) {
413		hexdump(printf, "xchacha_stream_xor", c, 608);
414		hexdump(printf, "expected", expected, 608);
415		result = -1;
416	}
417
418	memset(c, 0, sizeof c);
419	(*ci->ci_xchacha_stream_xor)(c, p, 607, 0, nonce, k, 20);
420	if (memcmp(c, expected, 607)) {
421		hexdump(printf, "xchacha_stream_xor", c, 607);
422		hexdump(printf, "expected", expected, 607);
423		result = -1;
424	}
425
426	memset(c, 0, sizeof c);
427	(*ci->ci_xchacha_stream_xor)(c, p, 543, 0, nonce, k, 20);
428	if (memcmp(c, expected, 543)) {
429		hexdump(printf, "xchacha_stream_xor", c, 543);
430		hexdump(printf, "expected", expected, 543);
431		result = -1;
432	}
433
434	memset(c, 0, sizeof c);
435	(*ci->ci_xchacha_stream_xor)(c, p, 511, 0, nonce, k, 20);
436	if (memcmp(c, expected, 511)) {
437		hexdump(printf, "xchacha_stream_xor", c, 511);
438		hexdump(printf, "expected", expected, 511);
439		result = -1;
440	}
441
442	memset(c, 0, sizeof c);
443	(*ci->ci_xchacha_stream_xor)(c, p, 63, 0, nonce, k, 20);
444	if (memcmp(c, expected, 63)) {
445		hexdump(printf, "xchacha_stream_xor", c, 63);
446		hexdump(printf, "expected", expected, 63);
447		result = -1;
448	}
449
450	return result;
451}
452
453int
454chacha_selftest(const struct chacha_impl *ci)
455{
456	int result = 0;
457
458	result |= chacha_core_selftest(ci);
459	result |= chacha_stream_selftest(ci);
460	result |= hchacha_selftest(ci);
461	result |= xchacha_stream_selftest(ci);
462
463	return result;
464}
465