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