xref: /netbsd-src/sys/lib/libkern/entpool.c (revision 5084c1b50f9863db4e36c6ec86538f91c324b1ac)
1*5084c1b5Sriastradh /*	$NetBSD: entpool.c,v 1.1 2020/04/30 03:28:19 riastradh Exp $	*/
2*5084c1b5Sriastradh 
3*5084c1b5Sriastradh /*-
4*5084c1b5Sriastradh  * Copyright (c) 2019 The NetBSD Foundation, Inc.
5*5084c1b5Sriastradh  * All rights reserved.
6*5084c1b5Sriastradh  *
7*5084c1b5Sriastradh  * This code is derived from software contributed to The NetBSD Foundation
8*5084c1b5Sriastradh  * by Taylor R. Campbell.
9*5084c1b5Sriastradh  *
10*5084c1b5Sriastradh  * Redistribution and use in source and binary forms, with or without
11*5084c1b5Sriastradh  * modification, are permitted provided that the following conditions
12*5084c1b5Sriastradh  * are met:
13*5084c1b5Sriastradh  * 1. Redistributions of source code must retain the above copyright
14*5084c1b5Sriastradh  *    notice, this list of conditions and the following disclaimer.
15*5084c1b5Sriastradh  * 2. Redistributions in binary form must reproduce the above copyright
16*5084c1b5Sriastradh  *    notice, this list of conditions and the following disclaimer in the
17*5084c1b5Sriastradh  *    documentation and/or other materials provided with the distribution.
18*5084c1b5Sriastradh  *
19*5084c1b5Sriastradh  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
20*5084c1b5Sriastradh  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
21*5084c1b5Sriastradh  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
22*5084c1b5Sriastradh  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
23*5084c1b5Sriastradh  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
24*5084c1b5Sriastradh  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
25*5084c1b5Sriastradh  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
26*5084c1b5Sriastradh  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
27*5084c1b5Sriastradh  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
28*5084c1b5Sriastradh  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
29*5084c1b5Sriastradh  * POSSIBILITY OF SUCH DAMAGE.
30*5084c1b5Sriastradh  */
31*5084c1b5Sriastradh 
32*5084c1b5Sriastradh /*
33*5084c1b5Sriastradh  * Entropy pool (`reseedable pseudorandom number generator') based on a
34*5084c1b5Sriastradh  * sponge duplex, following the design described and analyzed in
35*5084c1b5Sriastradh  *
36*5084c1b5Sriastradh  *	Guido Bertoni, Joan Daemen, Michaël Peeters, and Gilles Van
37*5084c1b5Sriastradh  *	Assche, `Sponge-Based Pseudo-Random Number Generators', in
38*5084c1b5Sriastradh  *	Stefan Mangard and François-Xavier Standaert, eds.,
39*5084c1b5Sriastradh  *	Cryptographic Hardware and Embedded Systems—CHES 2010, Springer
40*5084c1b5Sriastradh  *	LNCS 6225, pp. 33–47.
41*5084c1b5Sriastradh  *	https://link.springer.com/chapter/10.1007/978-3-642-15031-9_3
42*5084c1b5Sriastradh  *	https://keccak.team/files/SpongePRNG.pdf
43*5084c1b5Sriastradh  *
44*5084c1b5Sriastradh  *	Guido Bertoni, Joan Daemen, Michaël Peeters, and Gilles Van
45*5084c1b5Sriastradh  *	Assche, `Duplexing the Sponge: Single-Pass Authenticated
46*5084c1b5Sriastradh  *	Encryption and Other Applications', in Ali Miri and Serge
47*5084c1b5Sriastradh  *	Vaudenay, eds., Selected Areas in Cryptography—SAC 2011,
48*5084c1b5Sriastradh  *	Springer LNCS 7118, pp. 320–337.
49*5084c1b5Sriastradh  *	https://link.springer.com/chapter/10.1007/978-3-642-28496-0_19
50*5084c1b5Sriastradh  *	https://keccak.team/files/SpongeDuplex.pdf
51*5084c1b5Sriastradh  *
52*5084c1b5Sriastradh  * We make the following tweaks that don't affect security:
53*5084c1b5Sriastradh  *
54*5084c1b5Sriastradh  *	- Samples are length-delimited 7-bit variable-length encoding.
55*5084c1b5Sriastradh  *	  The encoding is still injective, so the security theorems
56*5084c1b5Sriastradh  *	  continue to apply.
57*5084c1b5Sriastradh  *
58*5084c1b5Sriastradh  *	- Output is not buffered -- callers should draw 32 bytes and
59*5084c1b5Sriastradh  *	  expand with a stream cipher.  In effect, every output draws
60*5084c1b5Sriastradh  *	  the full rate, and we just discard whatever the caller didn't
61*5084c1b5Sriastradh  *	  ask for; the impact is only on performance, not security.
62*5084c1b5Sriastradh  *
63*5084c1b5Sriastradh  * On top of the underlying sponge state, an entropy pool maintains an
64*5084c1b5Sriastradh  * integer i in [0, RATE-1] indicating where to write the next byte in
65*5084c1b5Sriastradh  * the input buffer.  Zeroing an entropy pool initializes it.
66*5084c1b5Sriastradh  */
67*5084c1b5Sriastradh 
68*5084c1b5Sriastradh #if defined(_KERNEL) || defined(_STANDALONE)
69*5084c1b5Sriastradh #include <sys/cdefs.h>
70*5084c1b5Sriastradh __KERNEL_RCSID(0, "$NetBSD: entpool.c,v 1.1 2020/04/30 03:28:19 riastradh Exp $");
71*5084c1b5Sriastradh #endif
72*5084c1b5Sriastradh 
73*5084c1b5Sriastradh #include "entpool.h"
74*5084c1b5Sriastradh #include ENTPOOL_HEADER
75*5084c1b5Sriastradh 
76*5084c1b5Sriastradh #if defined(_KERNEL) || defined(_STANDALONE)
77*5084c1b5Sriastradh #include <sys/types.h>
78*5084c1b5Sriastradh #include <lib/libkern/libkern.h>
79*5084c1b5Sriastradh #define	ASSERT		KASSERT
80*5084c1b5Sriastradh #else
81*5084c1b5Sriastradh #include <sys/cdefs.h>
82*5084c1b5Sriastradh #include <assert.h>
83*5084c1b5Sriastradh #include <stdbool.h>
84*5084c1b5Sriastradh #include <stdint.h>
85*5084c1b5Sriastradh #include <string.h>
86*5084c1b5Sriastradh #define	ASSERT		assert
87*5084c1b5Sriastradh #define	CTASSERT	__CTASSERT
88*5084c1b5Sriastradh #endif
89*5084c1b5Sriastradh 
90*5084c1b5Sriastradh #define	secret	/* must not use in variable-time operations; should zero */
91*5084c1b5Sriastradh #define	arraycount(A)	(sizeof(A)/sizeof((A)[0]))
92*5084c1b5Sriastradh #define	MIN(X,Y)	((X) < (Y) ? (X) : (Y))
93*5084c1b5Sriastradh 
94*5084c1b5Sriastradh #define	RATE		ENTPOOL_RATE
95*5084c1b5Sriastradh 
96*5084c1b5Sriastradh /*
97*5084c1b5Sriastradh  * stir(P)
98*5084c1b5Sriastradh  *
99*5084c1b5Sriastradh  *	Internal subroutine to apply the sponge permutation to the
100*5084c1b5Sriastradh  *	state in P.  Resets P->i to 0 to indicate that the input buffer
101*5084c1b5Sriastradh  *	is empty.
102*5084c1b5Sriastradh  */
103*5084c1b5Sriastradh static void
stir(struct entpool * P)104*5084c1b5Sriastradh stir(struct entpool *P)
105*5084c1b5Sriastradh {
106*5084c1b5Sriastradh 	size_t i;
107*5084c1b5Sriastradh 
108*5084c1b5Sriastradh 	/*
109*5084c1b5Sriastradh 	 * Switch to the permutation's byte order, if necessary, apply
110*5084c1b5Sriastradh 	 * permutation, and then switch back.  This way we can data in
111*5084c1b5Sriastradh 	 * and out byte by byte, but get the same answers out of test
112*5084c1b5Sriastradh 	 * vectors.
113*5084c1b5Sriastradh 	 */
114*5084c1b5Sriastradh 	for (i = 0; i < arraycount(P->s.w); i++)
115*5084c1b5Sriastradh 		P->s.w[i] = ENTPOOL_WTOH(P->s.w[i]);
116*5084c1b5Sriastradh 	ENTPOOL_PERMUTE(P->s.w);
117*5084c1b5Sriastradh 	for (i = 0; i < arraycount(P->s.w); i++)
118*5084c1b5Sriastradh 		P->s.w[i] = ENTPOOL_HTOW(P->s.w[i]);
119*5084c1b5Sriastradh 
120*5084c1b5Sriastradh 	/* Reset the input buffer.  */
121*5084c1b5Sriastradh 	P->i = 0;
122*5084c1b5Sriastradh }
123*5084c1b5Sriastradh 
124*5084c1b5Sriastradh /*
125*5084c1b5Sriastradh  * entpool_enter(P, buf, len)
126*5084c1b5Sriastradh  *
127*5084c1b5Sriastradh  *	Enter len bytes from buf into the entropy pool P, stirring as
128*5084c1b5Sriastradh  *	needed.  Corresponds to P.feed in the paper.
129*5084c1b5Sriastradh  */
130*5084c1b5Sriastradh void
entpool_enter(struct entpool * P,const void * buf,size_t len)131*5084c1b5Sriastradh entpool_enter(struct entpool *P, const void *buf, size_t len)
132*5084c1b5Sriastradh {
133*5084c1b5Sriastradh 	const uint8_t *p = buf;
134*5084c1b5Sriastradh 	size_t n = len, n1 = n;
135*5084c1b5Sriastradh 
136*5084c1b5Sriastradh 	/* Sanity-check P->i.  */
137*5084c1b5Sriastradh 	ASSERT(P->i <= RATE-1);
138*5084c1b5Sriastradh 
139*5084c1b5Sriastradh 	/* Encode the length, stirring as needed.  */
140*5084c1b5Sriastradh 	while (n1) {
141*5084c1b5Sriastradh 		if (P->i == RATE-1)
142*5084c1b5Sriastradh 			stir(P);
143*5084c1b5Sriastradh 		ASSERT(P->i < RATE-1);
144*5084c1b5Sriastradh 		P->s.u8[P->i++] ^= (n1 >= 0x80 ? 0x80 : 0) | (n1 & 0x7f);
145*5084c1b5Sriastradh 		n1 >>= 7;
146*5084c1b5Sriastradh 	}
147*5084c1b5Sriastradh 
148*5084c1b5Sriastradh 	/* Enter the sample, stirring as needed.  */
149*5084c1b5Sriastradh 	while (n --> 0) {
150*5084c1b5Sriastradh 		if (P->i == RATE-1)
151*5084c1b5Sriastradh 			stir(P);
152*5084c1b5Sriastradh 		ASSERT(P->i < RATE-1);
153*5084c1b5Sriastradh 		P->s.u8[P->i++] ^= *p++;
154*5084c1b5Sriastradh 	}
155*5084c1b5Sriastradh 
156*5084c1b5Sriastradh 	/* If we filled the input buffer exactly, stir once more.  */
157*5084c1b5Sriastradh 	if (P->i == RATE-1)
158*5084c1b5Sriastradh 		stir(P);
159*5084c1b5Sriastradh 	ASSERT(P->i < RATE-1);
160*5084c1b5Sriastradh }
161*5084c1b5Sriastradh 
162*5084c1b5Sriastradh /*
163*5084c1b5Sriastradh  * entpool_enter_nostir(P, buf, len)
164*5084c1b5Sriastradh  *
165*5084c1b5Sriastradh  *	Enter as many bytes as possible, up to len, from buf into the
166*5084c1b5Sriastradh  *	entropy pool P.  Roughly corresponds to P.feed in the paper,
167*5084c1b5Sriastradh  *	but we stop if we would have run the permutation.
168*5084c1b5Sriastradh  *
169*5084c1b5Sriastradh  *	Return true if the sample was consumed in its entirety, or true
170*5084c1b5Sriastradh  *	if the sample was truncated so the caller should arrange to
171*5084c1b5Sriastradh  *	call entpool_stir when it is next convenient to do so.
172*5084c1b5Sriastradh  *
173*5084c1b5Sriastradh  *	This function is cheap -- it only xors the input into the
174*5084c1b5Sriastradh  *	state, and never calls the underlying permutation, but it may
175*5084c1b5Sriastradh  *	truncate samples.
176*5084c1b5Sriastradh  */
177*5084c1b5Sriastradh bool
entpool_enter_nostir(struct entpool * P,const void * buf,size_t len)178*5084c1b5Sriastradh entpool_enter_nostir(struct entpool *P, const void *buf, size_t len)
179*5084c1b5Sriastradh {
180*5084c1b5Sriastradh 	const uint8_t *p = buf;
181*5084c1b5Sriastradh 	size_t n0, n;
182*5084c1b5Sriastradh 
183*5084c1b5Sriastradh 	/* Sanity-check P->i.  */
184*5084c1b5Sriastradh 	ASSERT(P->i <= RATE-1);
185*5084c1b5Sriastradh 
186*5084c1b5Sriastradh 	/* If the input buffer is full, fail.  */
187*5084c1b5Sriastradh 	if (P->i == RATE-1)
188*5084c1b5Sriastradh 		return false;
189*5084c1b5Sriastradh 	ASSERT(P->i < RATE-1);
190*5084c1b5Sriastradh 
191*5084c1b5Sriastradh 	/*
192*5084c1b5Sriastradh 	 * Truncate the sample and enter it with 1-byte length encoding
193*5084c1b5Sriastradh 	 * -- don't bother with variable-length encoding, not worth the
194*5084c1b5Sriastradh 	 * trouble.
195*5084c1b5Sriastradh 	 */
196*5084c1b5Sriastradh 	n = n0 = MIN(127, MIN(len, RATE-1 - P->i - 1));
197*5084c1b5Sriastradh 	P->s.u8[P->i++] ^= n;
198*5084c1b5Sriastradh 	while (n --> 0)
199*5084c1b5Sriastradh 		P->s.u8[P->i++] ^= *p++;
200*5084c1b5Sriastradh 
201*5084c1b5Sriastradh 	/* Can't guarantee anything better than 0 <= i <= RATE-1.  */
202*5084c1b5Sriastradh 	ASSERT(P->i <= RATE-1);
203*5084c1b5Sriastradh 
204*5084c1b5Sriastradh 	/* Return true if all done, false if truncated and in need of stir.  */
205*5084c1b5Sriastradh 	return (n0 == len);
206*5084c1b5Sriastradh }
207*5084c1b5Sriastradh 
208*5084c1b5Sriastradh /*
209*5084c1b5Sriastradh  * entpool_stir(P)
210*5084c1b5Sriastradh  *
211*5084c1b5Sriastradh  *	Stir the entropy pool after entpool_enter_nostir fails.  If it
212*5084c1b5Sriastradh  *	has already been stirred already, this has no effect.
213*5084c1b5Sriastradh  */
214*5084c1b5Sriastradh void
entpool_stir(struct entpool * P)215*5084c1b5Sriastradh entpool_stir(struct entpool *P)
216*5084c1b5Sriastradh {
217*5084c1b5Sriastradh 
218*5084c1b5Sriastradh 	/* Sanity-check P->i.  */
219*5084c1b5Sriastradh 	ASSERT(P->i <= RATE-1);
220*5084c1b5Sriastradh 
221*5084c1b5Sriastradh 	/* If the input buffer is full, stir.  */
222*5084c1b5Sriastradh 	if (P->i == RATE-1)
223*5084c1b5Sriastradh 		stir(P);
224*5084c1b5Sriastradh 	ASSERT(P->i < RATE-1);
225*5084c1b5Sriastradh }
226*5084c1b5Sriastradh 
227*5084c1b5Sriastradh /*
228*5084c1b5Sriastradh  * entpool_extract(P, buf, len)
229*5084c1b5Sriastradh  *
230*5084c1b5Sriastradh  *	Extract len bytes from the entropy pool P into buf.
231*5084c1b5Sriastradh  *	Corresponds to iterating P.fetch/P.forget in the paper.
232*5084c1b5Sriastradh  *	(Feeding the output back in -- as P.forget does -- is the same
233*5084c1b5Sriastradh  *	as zeroing what we just read out.)
234*5084c1b5Sriastradh  */
235*5084c1b5Sriastradh void
entpool_extract(struct entpool * P,secret void * buf,size_t len)236*5084c1b5Sriastradh entpool_extract(struct entpool *P, secret void *buf, size_t len)
237*5084c1b5Sriastradh {
238*5084c1b5Sriastradh 	uint8_t *p = buf;
239*5084c1b5Sriastradh 	size_t n = len;
240*5084c1b5Sriastradh 
241*5084c1b5Sriastradh 	/* Sanity-check P->i.  */
242*5084c1b5Sriastradh 	ASSERT(P->i <= RATE-1);
243*5084c1b5Sriastradh 
244*5084c1b5Sriastradh 	/* If input buffer is not empty, stir.  */
245*5084c1b5Sriastradh 	if (P->i != 0)
246*5084c1b5Sriastradh 		stir(P);
247*5084c1b5Sriastradh 	ASSERT(P->i == 0);
248*5084c1b5Sriastradh 
249*5084c1b5Sriastradh 	/*
250*5084c1b5Sriastradh 	 * Copy out and zero (RATE-1)-sized chunks at a time, stirring
251*5084c1b5Sriastradh 	 * with a bit set to distinguish this from inputs.
252*5084c1b5Sriastradh 	 */
253*5084c1b5Sriastradh 	while (n >= RATE-1) {
254*5084c1b5Sriastradh 		memcpy(p, P->s.u8, RATE-1);
255*5084c1b5Sriastradh 		memset(P->s.u8, 0, RATE-1);
256*5084c1b5Sriastradh 		P->s.u8[RATE-1] ^= 0x80;
257*5084c1b5Sriastradh 		stir(P);
258*5084c1b5Sriastradh 		p += RATE-1;
259*5084c1b5Sriastradh 		n -= RATE-1;
260*5084c1b5Sriastradh 	}
261*5084c1b5Sriastradh 
262*5084c1b5Sriastradh 	/*
263*5084c1b5Sriastradh 	 * If there's anything left, copy out a partial rate's worth
264*5084c1b5Sriastradh 	 * and zero the entire rate's worth, stirring with a bit set to
265*5084c1b5Sriastradh 	 * distinguish this from inputs.
266*5084c1b5Sriastradh 	 */
267*5084c1b5Sriastradh 	if (n) {
268*5084c1b5Sriastradh 		ASSERT(n < RATE-1);
269*5084c1b5Sriastradh 		memcpy(p, P->s.u8, n);		/* Copy part of it.  */
270*5084c1b5Sriastradh 		memset(P->s.u8, 0, RATE-1);	/* Zero all of it. */
271*5084c1b5Sriastradh 		P->s.u8[RATE-1] ^= 0x80;
272*5084c1b5Sriastradh 		stir(P);
273*5084c1b5Sriastradh 	}
274*5084c1b5Sriastradh }
275*5084c1b5Sriastradh 
276*5084c1b5Sriastradh /*
277*5084c1b5Sriastradh  * Known-answer tests
278*5084c1b5Sriastradh  */
279*5084c1b5Sriastradh 
280*5084c1b5Sriastradh #if ENTPOOL_SMALL
281*5084c1b5Sriastradh 
282*5084c1b5Sriastradh #define	KATLEN	15
283*5084c1b5Sriastradh 
284*5084c1b5Sriastradh /* Gimli */
285*5084c1b5Sriastradh static const uint8_t known_answers[][KATLEN] = {
286*5084c1b5Sriastradh 	[0] = {
287*5084c1b5Sriastradh 		0x69,0xb8,0x49,0x0d,0x39,0xfb,0x42,0x61,
288*5084c1b5Sriastradh 		0xf7,0x66,0xdf,0x04,0xb6,0xed,0x11,
289*5084c1b5Sriastradh 	},
290*5084c1b5Sriastradh 	[1] = {
291*5084c1b5Sriastradh 		0x74,0x15,0x16,0x49,0x31,0x07,0x77,0xa1,
292*5084c1b5Sriastradh 		0x3b,0x4d,0x78,0xc6,0x5d,0xef,0x87,
293*5084c1b5Sriastradh 	},
294*5084c1b5Sriastradh 	[2] = {
295*5084c1b5Sriastradh 		0xae,0xfd,0x7d,0xc4,0x3b,0xce,0x09,0x25,
296*5084c1b5Sriastradh 		0xbf,0x60,0x21,0x6e,0x3c,0x3a,0x84,
297*5084c1b5Sriastradh 	},
298*5084c1b5Sriastradh 	[3] = {
299*5084c1b5Sriastradh 		0xae,0xfd,0x7d,0xc4,0x3b,0xce,0x09,0x25,
300*5084c1b5Sriastradh 		0xbf,0x60,0x21,0x6e,0x3c,0x3a,0x84,
301*5084c1b5Sriastradh 	},
302*5084c1b5Sriastradh 	[4] = {
303*5084c1b5Sriastradh 		0x69,0xb8,0x49,0x0d,0x39,0xfb,0x42,0x61,
304*5084c1b5Sriastradh 		0xf7,0x66,0xdf,0x04,0xb6,0xed,0x11,
305*5084c1b5Sriastradh 	},
306*5084c1b5Sriastradh 	[5] = {
307*5084c1b5Sriastradh 		0xa9,0x3c,0x3c,0xac,0x5f,0x6d,0x80,0xdc,
308*5084c1b5Sriastradh 		0x33,0x0c,0xb2,0xe3,0xdd,0x55,0x31,
309*5084c1b5Sriastradh 	},
310*5084c1b5Sriastradh 	[6] = {
311*5084c1b5Sriastradh 		0x2e,0x69,0x1a,0x2a,0x2d,0x09,0xd4,0x5e,
312*5084c1b5Sriastradh 		0x49,0xcc,0x8c,0xb2,0x0b,0xcc,0x42,
313*5084c1b5Sriastradh 	},
314*5084c1b5Sriastradh 	[7] = {
315*5084c1b5Sriastradh 		0xae,0xfd,0x7d,0xc4,0x3b,0xce,0x09,0x25,
316*5084c1b5Sriastradh 		0xbf,0x60,0x21,0x6e,0x3c,0x3a,0x84,
317*5084c1b5Sriastradh 	},
318*5084c1b5Sriastradh 	[8] = {
319*5084c1b5Sriastradh 		0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
320*5084c1b5Sriastradh 		0x00,0x00,0x00,0x00,0x00,0x00,0x00,
321*5084c1b5Sriastradh 	},
322*5084c1b5Sriastradh 	[9] = {
323*5084c1b5Sriastradh 		0x69,0xb8,0x49,0x0d,0x39,0xfb,0x42,0x61,
324*5084c1b5Sriastradh 		0xf7,0x66,0xdf,0x04,0xb6,0xed,0x11,
325*5084c1b5Sriastradh 	},
326*5084c1b5Sriastradh 	[10] = {
327*5084c1b5Sriastradh 		0x2e,0x69,0x1a,0x2a,0x2d,0x09,0xd4,0x5e,
328*5084c1b5Sriastradh 		0x49,0xcc,0x8c,0xb2,0x0b,0xcc,0x42,
329*5084c1b5Sriastradh 	},
330*5084c1b5Sriastradh 	[11] = {
331*5084c1b5Sriastradh 		0x6f,0xfd,0xd2,0x29,0x78,0x46,0xc0,0x7d,
332*5084c1b5Sriastradh 		0xc7,0xf2,0x0a,0x2b,0x72,0xd6,0xc6,
333*5084c1b5Sriastradh 	},
334*5084c1b5Sriastradh 	[12] = {
335*5084c1b5Sriastradh 		0x86,0xf0,0xc1,0xf9,0x95,0x0f,0xc9,0x12,
336*5084c1b5Sriastradh 		0xde,0x38,0x39,0x10,0x1f,0x8c,0xc4,
337*5084c1b5Sriastradh 	},
338*5084c1b5Sriastradh };
339*5084c1b5Sriastradh 
340*5084c1b5Sriastradh #else  /* !ENTPOOL_SMALL */
341*5084c1b5Sriastradh 
342*5084c1b5Sriastradh #define	KATLEN	16
343*5084c1b5Sriastradh 
344*5084c1b5Sriastradh /* Keccak-p[1600, 24] */
345*5084c1b5Sriastradh static const uint8_t known_answers[][KATLEN] = {
346*5084c1b5Sriastradh 	[0] = {
347*5084c1b5Sriastradh 		0x3b,0x20,0xf0,0xe9,0xce,0x94,0x48,0x07,
348*5084c1b5Sriastradh 		0x97,0xb6,0x16,0xb5,0xb5,0x05,0x1a,0xce,
349*5084c1b5Sriastradh 	},
350*5084c1b5Sriastradh 	[1] = {
351*5084c1b5Sriastradh 		0x57,0x49,0x6e,0x28,0x7f,0xaa,0xee,0x6c,
352*5084c1b5Sriastradh 		0xa8,0xb0,0xf5,0x0b,0x87,0xae,0xd6,0xd6,
353*5084c1b5Sriastradh 	},
354*5084c1b5Sriastradh 	[2] = {
355*5084c1b5Sriastradh 		0x51,0x72,0x0f,0x59,0x54,0xe1,0xaf,0xa8,
356*5084c1b5Sriastradh 		0x16,0x67,0xfa,0x3f,0x8a,0x19,0x52,0x50,
357*5084c1b5Sriastradh 	},
358*5084c1b5Sriastradh 	[3] = {
359*5084c1b5Sriastradh 		0x51,0x72,0x0f,0x59,0x54,0xe1,0xaf,0xa8,
360*5084c1b5Sriastradh 		0x16,0x67,0xfa,0x3f,0x8a,0x19,0x52,0x50,
361*5084c1b5Sriastradh 	},
362*5084c1b5Sriastradh 	[4] = {
363*5084c1b5Sriastradh 		0x3b,0x20,0xf0,0xe9,0xce,0x94,0x48,0x07,
364*5084c1b5Sriastradh 		0x97,0xb6,0x16,0xb5,0xb5,0x05,0x1a,0xce,
365*5084c1b5Sriastradh 	},
366*5084c1b5Sriastradh 	[5] = {
367*5084c1b5Sriastradh 		0x95,0x23,0x77,0xe4,0x84,0xeb,0xaa,0x2e,
368*5084c1b5Sriastradh 		0x6a,0x99,0xc2,0x52,0x06,0x6d,0xdf,0xea,
369*5084c1b5Sriastradh 	},
370*5084c1b5Sriastradh 	[6] = {
371*5084c1b5Sriastradh 		0x8c,0xdd,0x1b,0xaf,0x0e,0xf6,0xe9,0x1d,
372*5084c1b5Sriastradh 		0x51,0x33,0x68,0x38,0x8d,0xad,0x55,0x84,
373*5084c1b5Sriastradh 	},
374*5084c1b5Sriastradh 	[7] = {
375*5084c1b5Sriastradh 		0x51,0x72,0x0f,0x59,0x54,0xe1,0xaf,0xa8,
376*5084c1b5Sriastradh 		0x16,0x67,0xfa,0x3f,0x8a,0x19,0x52,0x50,
377*5084c1b5Sriastradh 	},
378*5084c1b5Sriastradh 	[8] = {
379*5084c1b5Sriastradh 		0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
380*5084c1b5Sriastradh 		0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
381*5084c1b5Sriastradh 	},
382*5084c1b5Sriastradh 	[9] = {
383*5084c1b5Sriastradh 		0x3b,0x20,0xf0,0xe9,0xce,0x94,0x48,0x07,
384*5084c1b5Sriastradh 		0x97,0xb6,0x16,0xb5,0xb5,0x05,0x1a,0xce,
385*5084c1b5Sriastradh 	},
386*5084c1b5Sriastradh 	[10] = {
387*5084c1b5Sriastradh 		0x8c,0xdd,0x1b,0xaf,0x0e,0xf6,0xe9,0x1d,
388*5084c1b5Sriastradh 		0x51,0x33,0x68,0x38,0x8d,0xad,0x55,0x84,
389*5084c1b5Sriastradh 	},
390*5084c1b5Sriastradh 	[11] = {
391*5084c1b5Sriastradh 		0xf6,0xc1,0x14,0xbb,0x13,0x0a,0xaf,0xed,
392*5084c1b5Sriastradh 		0xca,0x0b,0x35,0x2c,0xf1,0x2b,0x1a,0x85,
393*5084c1b5Sriastradh 	},
394*5084c1b5Sriastradh 	[12] = {
395*5084c1b5Sriastradh 		0xf9,0x4b,0x05,0xd1,0x8b,0xcd,0xb3,0xd0,
396*5084c1b5Sriastradh 		0x77,0x27,0xfe,0x46,0xf9,0x33,0xb2,0xa2,
397*5084c1b5Sriastradh 	},
398*5084c1b5Sriastradh };
399*5084c1b5Sriastradh 
400*5084c1b5Sriastradh #endif
401*5084c1b5Sriastradh 
402*5084c1b5Sriastradh #define	KAT_BEGIN(P, n)	memset(P, 0, sizeof(*(P)))
403*5084c1b5Sriastradh #define	KAT_ERROR()	return -1
404*5084c1b5Sriastradh #define	KAT_END(P, n)	do						      \
405*5084c1b5Sriastradh {									      \
406*5084c1b5Sriastradh 	uint8_t KAT_ACTUAL[KATLEN];					      \
407*5084c1b5Sriastradh 	entpool_extract(P, KAT_ACTUAL, KATLEN);				      \
408*5084c1b5Sriastradh 	if (memcmp(KAT_ACTUAL, known_answers[n], KATLEN))		      \
409*5084c1b5Sriastradh 		return -1;						      \
410*5084c1b5Sriastradh } while (0)
411*5084c1b5Sriastradh 
412*5084c1b5Sriastradh int
entpool_selftest(void)413*5084c1b5Sriastradh entpool_selftest(void)
414*5084c1b5Sriastradh {
415*5084c1b5Sriastradh 	struct entpool pool, *P = &pool;
416*5084c1b5Sriastradh 	uint8_t sample[1] = {0xff};
417*5084c1b5Sriastradh 	uint8_t scratch[RATE];
418*5084c1b5Sriastradh 	const uint8_t zero[RATE] = {0};
419*5084c1b5Sriastradh 
420*5084c1b5Sriastradh 	/* Test entpool_enter with empty buffer.  */
421*5084c1b5Sriastradh 	KAT_BEGIN(P, 0);
422*5084c1b5Sriastradh 	entpool_stir(P);	/* noop */
423*5084c1b5Sriastradh 	entpool_enter(P, sample, 1);
424*5084c1b5Sriastradh 	entpool_stir(P);	/* noop */
425*5084c1b5Sriastradh 	KAT_END(P, 0);
426*5084c1b5Sriastradh 
427*5084c1b5Sriastradh 	/* Test entpool_enter with partial buffer.  */
428*5084c1b5Sriastradh 	KAT_BEGIN(P, 1);
429*5084c1b5Sriastradh 	entpool_stir(P);	/* noop */
430*5084c1b5Sriastradh #if ENTPOOL_SMALL
431*5084c1b5Sriastradh 	entpool_enter(P, zero, RATE-3);
432*5084c1b5Sriastradh #else
433*5084c1b5Sriastradh 	entpool_enter(P, zero, RATE-4);
434*5084c1b5Sriastradh #endif
435*5084c1b5Sriastradh 	entpool_stir(P);	/* noop */
436*5084c1b5Sriastradh 	entpool_enter(P, sample, 1);
437*5084c1b5Sriastradh 	entpool_stir(P);	/* noop */
438*5084c1b5Sriastradh 	KAT_END(P, 1);
439*5084c1b5Sriastradh 
440*5084c1b5Sriastradh 	/* Test entpool_enter with full buffer.  */
441*5084c1b5Sriastradh 	KAT_BEGIN(P, 2);
442*5084c1b5Sriastradh 	entpool_stir(P);	/* noop */
443*5084c1b5Sriastradh #if ENTPOOL_SMALL
444*5084c1b5Sriastradh 	if (!entpool_enter_nostir(P, zero, RATE-2))
445*5084c1b5Sriastradh 		KAT_ERROR();
446*5084c1b5Sriastradh #else
447*5084c1b5Sriastradh 	if (!entpool_enter_nostir(P, zero, 127))
448*5084c1b5Sriastradh 		KAT_ERROR();
449*5084c1b5Sriastradh 	if (!entpool_enter_nostir(P, zero, RATE-2 - 127 - 1))
450*5084c1b5Sriastradh 		KAT_ERROR();
451*5084c1b5Sriastradh #endif
452*5084c1b5Sriastradh 	entpool_enter(P, sample, 1);
453*5084c1b5Sriastradh 	entpool_stir(P);	/* noop */
454*5084c1b5Sriastradh 	KAT_END(P, 2);
455*5084c1b5Sriastradh 
456*5084c1b5Sriastradh 	/* Test entpool_enter with full buffer after stir.  */
457*5084c1b5Sriastradh 	KAT_BEGIN(P, 3);
458*5084c1b5Sriastradh 	entpool_stir(P);	/* noop */
459*5084c1b5Sriastradh #if ENTPOOL_SMALL
460*5084c1b5Sriastradh 	if (!entpool_enter_nostir(P, zero, RATE-2))
461*5084c1b5Sriastradh 		KAT_ERROR();
462*5084c1b5Sriastradh #else
463*5084c1b5Sriastradh 	CTASSERT(127 <= RATE-2);
464*5084c1b5Sriastradh 	if (!entpool_enter_nostir(P, zero, 127))
465*5084c1b5Sriastradh 		KAT_ERROR();
466*5084c1b5Sriastradh 	if (!entpool_enter_nostir(P, zero, RATE-2 - 127 - 1))
467*5084c1b5Sriastradh 		KAT_ERROR();
468*5084c1b5Sriastradh #endif
469*5084c1b5Sriastradh 	entpool_stir(P);
470*5084c1b5Sriastradh 	entpool_enter(P, sample, 1);
471*5084c1b5Sriastradh 	entpool_stir(P);	/* noop */
472*5084c1b5Sriastradh 	KAT_END(P, 3);
473*5084c1b5Sriastradh 
474*5084c1b5Sriastradh 	/* Test entpool_enter_nostir with empty buffer.  */
475*5084c1b5Sriastradh 	KAT_BEGIN(P, 4);
476*5084c1b5Sriastradh 	entpool_stir(P);	/* noop */
477*5084c1b5Sriastradh 	if (!entpool_enter_nostir(P, sample, 1))
478*5084c1b5Sriastradh 		KAT_ERROR();
479*5084c1b5Sriastradh 	entpool_stir(P);	/* noop */
480*5084c1b5Sriastradh 	KAT_END(P, 4);
481*5084c1b5Sriastradh 
482*5084c1b5Sriastradh 	/* Test entpool_enter_nostir with partial buffer.  */
483*5084c1b5Sriastradh 	KAT_BEGIN(P, 5);
484*5084c1b5Sriastradh 	entpool_stir(P);	/* noop */
485*5084c1b5Sriastradh #if ENTPOOL_SMALL
486*5084c1b5Sriastradh 	entpool_enter(P, zero, RATE-3);
487*5084c1b5Sriastradh #else
488*5084c1b5Sriastradh 	entpool_enter(P, zero, RATE-4);
489*5084c1b5Sriastradh #endif
490*5084c1b5Sriastradh 	entpool_stir(P);	/* noop */
491*5084c1b5Sriastradh 	if (entpool_enter_nostir(P, sample, 1))
492*5084c1b5Sriastradh 		KAT_ERROR();
493*5084c1b5Sriastradh 	entpool_stir(P);
494*5084c1b5Sriastradh 	KAT_END(P, 5);
495*5084c1b5Sriastradh 
496*5084c1b5Sriastradh 	/* Test entpool_enter_nostir with full buffer.  */
497*5084c1b5Sriastradh 	KAT_BEGIN(P, 6);
498*5084c1b5Sriastradh 	entpool_stir(P);	/* noop */
499*5084c1b5Sriastradh #if ENTPOOL_SMALL
500*5084c1b5Sriastradh 	if (!entpool_enter_nostir(P, zero, RATE-2))
501*5084c1b5Sriastradh 		KAT_ERROR();
502*5084c1b5Sriastradh #else
503*5084c1b5Sriastradh 	CTASSERT(127 <= RATE-2);
504*5084c1b5Sriastradh 	if (!entpool_enter_nostir(P, zero, 127))
505*5084c1b5Sriastradh 		KAT_ERROR();
506*5084c1b5Sriastradh 	if (!entpool_enter_nostir(P, zero, RATE-2 - 127 - 1))
507*5084c1b5Sriastradh 		KAT_ERROR();
508*5084c1b5Sriastradh #endif
509*5084c1b5Sriastradh 	if (entpool_enter_nostir(P, sample, 1))
510*5084c1b5Sriastradh 		KAT_ERROR();
511*5084c1b5Sriastradh 	entpool_stir(P);
512*5084c1b5Sriastradh 	KAT_END(P, 6);
513*5084c1b5Sriastradh 
514*5084c1b5Sriastradh 	/* Test entpool_enter_nostir with full buffer after stir.  */
515*5084c1b5Sriastradh 	KAT_BEGIN(P, 7);
516*5084c1b5Sriastradh 	entpool_stir(P);	/* noop */
517*5084c1b5Sriastradh #if ENTPOOL_SMALL
518*5084c1b5Sriastradh 	if (!entpool_enter_nostir(P, zero, RATE-2))
519*5084c1b5Sriastradh 		KAT_ERROR();
520*5084c1b5Sriastradh #else
521*5084c1b5Sriastradh 	CTASSERT(127 <= RATE-2);
522*5084c1b5Sriastradh 	if (!entpool_enter_nostir(P, zero, 127))
523*5084c1b5Sriastradh 		KAT_ERROR();
524*5084c1b5Sriastradh 	if (!entpool_enter_nostir(P, zero, RATE-2 - 127 - 1))
525*5084c1b5Sriastradh 		KAT_ERROR();
526*5084c1b5Sriastradh #endif
527*5084c1b5Sriastradh 	entpool_stir(P);
528*5084c1b5Sriastradh 	if (!entpool_enter_nostir(P, sample, 1))
529*5084c1b5Sriastradh 		KAT_ERROR();
530*5084c1b5Sriastradh 	entpool_stir(P);	/* noop */
531*5084c1b5Sriastradh 	KAT_END(P, 7);
532*5084c1b5Sriastradh 
533*5084c1b5Sriastradh 	/* Test entpool_extract with empty input buffer.  */
534*5084c1b5Sriastradh 	KAT_BEGIN(P, 8);
535*5084c1b5Sriastradh 	entpool_stir(P);	/* noop */
536*5084c1b5Sriastradh 	KAT_END(P, 8);
537*5084c1b5Sriastradh 
538*5084c1b5Sriastradh 	/* Test entpool_extract with nonempty input buffer.  */
539*5084c1b5Sriastradh 	KAT_BEGIN(P, 9);
540*5084c1b5Sriastradh 	entpool_stir(P);	/* noop */
541*5084c1b5Sriastradh 	entpool_enter(P, sample, 1);
542*5084c1b5Sriastradh 	entpool_stir(P);	/* noop */
543*5084c1b5Sriastradh 	KAT_END(P, 9);
544*5084c1b5Sriastradh 
545*5084c1b5Sriastradh 	/* Test entpool_extract with full input buffer.  */
546*5084c1b5Sriastradh 	KAT_BEGIN(P, 10);
547*5084c1b5Sriastradh 	entpool_stir(P);	/* noop */
548*5084c1b5Sriastradh #if ENTPOOL_SMALL
549*5084c1b5Sriastradh 	if (!entpool_enter_nostir(P, zero, RATE-2))
550*5084c1b5Sriastradh 		KAT_ERROR();
551*5084c1b5Sriastradh #else
552*5084c1b5Sriastradh 	CTASSERT(127 <= RATE-2);
553*5084c1b5Sriastradh 	if (!entpool_enter_nostir(P, zero, 127))
554*5084c1b5Sriastradh 		KAT_ERROR();
555*5084c1b5Sriastradh 	if (!entpool_enter_nostir(P, zero, RATE-2 - 127 - 1))
556*5084c1b5Sriastradh 		KAT_ERROR();
557*5084c1b5Sriastradh #endif
558*5084c1b5Sriastradh 	KAT_END(P, 10);
559*5084c1b5Sriastradh 
560*5084c1b5Sriastradh 	/* Test entpool_extract with iterated output.  */
561*5084c1b5Sriastradh 	KAT_BEGIN(P, 11);
562*5084c1b5Sriastradh 	entpool_stir(P);	/* noop */
563*5084c1b5Sriastradh 	entpool_extract(P, scratch, RATE-1 + 1);
564*5084c1b5Sriastradh 	entpool_stir(P);	/* noop */
565*5084c1b5Sriastradh 	KAT_END(P, 11);
566*5084c1b5Sriastradh 
567*5084c1b5Sriastradh 	/* Test extract, enter, extract.  */
568*5084c1b5Sriastradh 	KAT_BEGIN(P, 12);
569*5084c1b5Sriastradh 	entpool_stir(P);	/* noop */
570*5084c1b5Sriastradh 	entpool_extract(P, scratch, 1);
571*5084c1b5Sriastradh 	entpool_stir(P);	/* noop */
572*5084c1b5Sriastradh 	entpool_enter(P, sample, 1);
573*5084c1b5Sriastradh 	entpool_stir(P);	/* noop */
574*5084c1b5Sriastradh 	KAT_END(P, 12);
575*5084c1b5Sriastradh 
576*5084c1b5Sriastradh 	return 0;
577*5084c1b5Sriastradh }
578*5084c1b5Sriastradh 
579*5084c1b5Sriastradh #if ENTPOOL_TEST
580*5084c1b5Sriastradh int
main(void)581*5084c1b5Sriastradh main(void)
582*5084c1b5Sriastradh {
583*5084c1b5Sriastradh 	return entpool_selftest();
584*5084c1b5Sriastradh }
585*5084c1b5Sriastradh #endif
586*5084c1b5Sriastradh 
587*5084c1b5Sriastradh /*
588*5084c1b5Sriastradh  * Known-answer test generation
589*5084c1b5Sriastradh  *
590*5084c1b5Sriastradh  *	This generates the known-answer test vectors from explicitly
591*5084c1b5Sriastradh  *	specified duplex inputs that correspond to what entpool_enter
592*5084c1b5Sriastradh  *	&c. induce, to confirm the encoding of inputs works as
593*5084c1b5Sriastradh  *	intended.
594*5084c1b5Sriastradh  */
595*5084c1b5Sriastradh 
596*5084c1b5Sriastradh #if ENTPOOL_GENKAT
597*5084c1b5Sriastradh 
598*5084c1b5Sriastradh #include <stdio.h>
599*5084c1b5Sriastradh 
600*5084c1b5Sriastradh struct event {
601*5084c1b5Sriastradh 	enum { IN, OUT, STOP } t;
602*5084c1b5Sriastradh 	uint8_t b[RATE-1];
603*5084c1b5Sriastradh };
604*5084c1b5Sriastradh 
605*5084c1b5Sriastradh /* Cases correspond to entpool_selftest above.  */
606*5084c1b5Sriastradh static const struct event *const cases[] = {
607*5084c1b5Sriastradh 	[0] = (const struct event[]) {
608*5084c1b5Sriastradh 		{IN, {1, 0xff}},
609*5084c1b5Sriastradh 		{STOP, {0}},
610*5084c1b5Sriastradh 	},
611*5084c1b5Sriastradh 	[1] = (const struct event[]) {
612*5084c1b5Sriastradh #if ENTPOOL_SMALL
613*5084c1b5Sriastradh 		{IN, {RATE-3, [RATE-2] = 1}},
614*5084c1b5Sriastradh #else
615*5084c1b5Sriastradh 		{IN, {0x80|((RATE-4)&0x7f), (RATE-4)>>7, [RATE-2] = 1}},
616*5084c1b5Sriastradh #endif
617*5084c1b5Sriastradh 		{IN, {0xff}},
618*5084c1b5Sriastradh 		{STOP, {0}},
619*5084c1b5Sriastradh 	},
620*5084c1b5Sriastradh 	[2] = (const struct event[]) {
621*5084c1b5Sriastradh #if ENTPOOL_SMALL
622*5084c1b5Sriastradh 		{IN, {RATE-2}},
623*5084c1b5Sriastradh #else
624*5084c1b5Sriastradh 		{IN, {127, [128] = RATE-2 - 127 - 1}},
625*5084c1b5Sriastradh #endif
626*5084c1b5Sriastradh 		{IN, {1, 0xff}},
627*5084c1b5Sriastradh 		{STOP, {0}},
628*5084c1b5Sriastradh 	},
629*5084c1b5Sriastradh 	[3] = (const struct event[]) {
630*5084c1b5Sriastradh #if ENTPOOL_SMALL
631*5084c1b5Sriastradh 		{IN, {RATE-2}},
632*5084c1b5Sriastradh #else
633*5084c1b5Sriastradh 		{IN, {127, [128] = RATE-2 - 127 - 1}},
634*5084c1b5Sriastradh #endif
635*5084c1b5Sriastradh 		{IN, {1, 0xff}},
636*5084c1b5Sriastradh 		{STOP, {0}},
637*5084c1b5Sriastradh 	},
638*5084c1b5Sriastradh 	[4] = (const struct event[]) {
639*5084c1b5Sriastradh 		{IN, {1, 0xff}},
640*5084c1b5Sriastradh 		{STOP, {0}},
641*5084c1b5Sriastradh 	},
642*5084c1b5Sriastradh 
643*5084c1b5Sriastradh 	[5] = (const struct event[]) {
644*5084c1b5Sriastradh #if ENTPOOL_SMALL
645*5084c1b5Sriastradh 		{IN, {RATE-3, [RATE-2] = 0 /* truncated length */}},
646*5084c1b5Sriastradh #else
647*5084c1b5Sriastradh 		{IN, {0x80|((RATE-4)&0x7f), (RATE-4)>>7,
648*5084c1b5Sriastradh 		      [RATE-2] = 0 /* truncated length */}},
649*5084c1b5Sriastradh #endif
650*5084c1b5Sriastradh 		{STOP, {0}},
651*5084c1b5Sriastradh 	},
652*5084c1b5Sriastradh 	[6] = (const struct event[]) {
653*5084c1b5Sriastradh #if ENTPOOL_SMALL
654*5084c1b5Sriastradh 		{IN, {RATE-2}},
655*5084c1b5Sriastradh #else
656*5084c1b5Sriastradh 		{IN, {127, [128] = RATE-2 - 127 - 1}},
657*5084c1b5Sriastradh #endif
658*5084c1b5Sriastradh 		{STOP, {0}},
659*5084c1b5Sriastradh 	},
660*5084c1b5Sriastradh 	[7] = (const struct event[]) {
661*5084c1b5Sriastradh #if ENTPOOL_SMALL
662*5084c1b5Sriastradh 		{IN, {RATE-2}},
663*5084c1b5Sriastradh #else
664*5084c1b5Sriastradh 		{IN, {127, [128] = RATE-2 - 127 - 1}},
665*5084c1b5Sriastradh #endif
666*5084c1b5Sriastradh 		{IN, {1, 0xff}},
667*5084c1b5Sriastradh 		{STOP, {0}},
668*5084c1b5Sriastradh 	},
669*5084c1b5Sriastradh 	[8] = (const struct event[]) {
670*5084c1b5Sriastradh 		{STOP, {0}},
671*5084c1b5Sriastradh 	},
672*5084c1b5Sriastradh 	[9] = (const struct event[]) {
673*5084c1b5Sriastradh 		{IN, {1, 0xff}},
674*5084c1b5Sriastradh 		{STOP, {0}},
675*5084c1b5Sriastradh 	},
676*5084c1b5Sriastradh 	[10] = (const struct event[]) {
677*5084c1b5Sriastradh #if ENTPOOL_SMALL
678*5084c1b5Sriastradh 		{IN, {RATE-2}},
679*5084c1b5Sriastradh #else
680*5084c1b5Sriastradh 		{IN, {127, [128] = RATE-2 - 127 - 1}},
681*5084c1b5Sriastradh #endif
682*5084c1b5Sriastradh 		{STOP, {0}},
683*5084c1b5Sriastradh 	},
684*5084c1b5Sriastradh 	[11] = (const struct event[]) {
685*5084c1b5Sriastradh 		{OUT, {0}},
686*5084c1b5Sriastradh 		{OUT, {0}},
687*5084c1b5Sriastradh 		{STOP, {0}},
688*5084c1b5Sriastradh 	},
689*5084c1b5Sriastradh 	[12] = (const struct event[]) {
690*5084c1b5Sriastradh 		{OUT, {0}},
691*5084c1b5Sriastradh 		{IN, {1, 0xff}},
692*5084c1b5Sriastradh 		{STOP, {0}},
693*5084c1b5Sriastradh 	},
694*5084c1b5Sriastradh };
695*5084c1b5Sriastradh 
696*5084c1b5Sriastradh static void
compute(uint8_t output[KATLEN],const struct event * events)697*5084c1b5Sriastradh compute(uint8_t output[KATLEN], const struct event *events)
698*5084c1b5Sriastradh {
699*5084c1b5Sriastradh 	union {
700*5084c1b5Sriastradh 		uint8_t b[ENTPOOL_SIZE];
701*5084c1b5Sriastradh 		ENTPOOL_WORD w[ENTPOOL_SIZE/sizeof(ENTPOOL_WORD)];
702*5084c1b5Sriastradh 	} u;
703*5084c1b5Sriastradh 	unsigned i, j, k;
704*5084c1b5Sriastradh 
705*5084c1b5Sriastradh 	memset(&u.b, 0, sizeof u.b);
706*5084c1b5Sriastradh 	for (i = 0;; i++) {
707*5084c1b5Sriastradh 		if (events[i].t == STOP)
708*5084c1b5Sriastradh 			break;
709*5084c1b5Sriastradh 		for (j = 0; j < sizeof(events[i].b); j++)
710*5084c1b5Sriastradh 			u.b[j] ^= events[i].b[j];
711*5084c1b5Sriastradh 		if (events[i].t == OUT) {
712*5084c1b5Sriastradh 			memset(u.b, 0, RATE-1);
713*5084c1b5Sriastradh 			u.b[RATE-1] ^= 0x80;
714*5084c1b5Sriastradh 		}
715*5084c1b5Sriastradh 
716*5084c1b5Sriastradh 		for (k = 0; k < arraycount(u.w); k++)
717*5084c1b5Sriastradh 			u.w[k] = ENTPOOL_WTOH(u.w[k]);
718*5084c1b5Sriastradh 		ENTPOOL_PERMUTE(u.w);
719*5084c1b5Sriastradh 		for (k = 0; k < arraycount(u.w); k++)
720*5084c1b5Sriastradh 			u.w[k] = ENTPOOL_HTOW(u.w[k]);
721*5084c1b5Sriastradh 	}
722*5084c1b5Sriastradh 
723*5084c1b5Sriastradh 	for (j = 0; j < KATLEN; j++)
724*5084c1b5Sriastradh 		output[j] = u.b[j];
725*5084c1b5Sriastradh }
726*5084c1b5Sriastradh 
727*5084c1b5Sriastradh int
main(void)728*5084c1b5Sriastradh main(void)
729*5084c1b5Sriastradh {
730*5084c1b5Sriastradh 	uint8_t output[KATLEN];
731*5084c1b5Sriastradh 	unsigned i, j;
732*5084c1b5Sriastradh 
733*5084c1b5Sriastradh 	printf("static const uint8_t known_answers[][KATLEN] = {\n");
734*5084c1b5Sriastradh 	for (i = 0; i < arraycount(cases); i++) {
735*5084c1b5Sriastradh 		printf("\t[%u] = {\n", i);
736*5084c1b5Sriastradh 		compute(output, cases[i]);
737*5084c1b5Sriastradh 		for (j = 0; j < KATLEN; j++) {
738*5084c1b5Sriastradh 			if (j % 8 == 0)
739*5084c1b5Sriastradh 				printf("\t\t");
740*5084c1b5Sriastradh 			printf("0x%02hhx,", output[j]);
741*5084c1b5Sriastradh 			if (j % 8 == 7)
742*5084c1b5Sriastradh 				printf("\n");
743*5084c1b5Sriastradh 		}
744*5084c1b5Sriastradh 		if ((KATLEN % 8) != 0)
745*5084c1b5Sriastradh 			printf("\n");
746*5084c1b5Sriastradh 		printf("\t},\n");
747*5084c1b5Sriastradh 	}
748*5084c1b5Sriastradh 	printf("};\n");
749*5084c1b5Sriastradh 
750*5084c1b5Sriastradh 	fflush(stdout);
751*5084c1b5Sriastradh 	return ferror(stdout);
752*5084c1b5Sriastradh }
753*5084c1b5Sriastradh 
754*5084c1b5Sriastradh #endif
755