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