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