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