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