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