1a3c41f8bSConrad Meyer /*- 2a3c41f8bSConrad Meyer * SPDX-License-Identifier: BSD-2-Clause-FreeBSD 3a3c41f8bSConrad Meyer * 4a3c41f8bSConrad Meyer * Copyright (c) 2019 Conrad Meyer <cem@FreeBSD.org> 5a3c41f8bSConrad Meyer * 6a3c41f8bSConrad Meyer * Redistribution and use in source and binary forms, with or without 7a3c41f8bSConrad Meyer * modification, are permitted provided that the following conditions 8a3c41f8bSConrad Meyer * are met: 9a3c41f8bSConrad Meyer * 1. Redistributions of source code must retain the above copyright 10a3c41f8bSConrad Meyer * notice, this list of conditions and the following disclaimer. 11a3c41f8bSConrad Meyer * 2. Redistributions in binary form must reproduce the above copyright 12a3c41f8bSConrad Meyer * notice, this list of conditions and the following disclaimer in the 13a3c41f8bSConrad Meyer * documentation and/or other materials provided with the distribution. 14a3c41f8bSConrad Meyer * 15a3c41f8bSConrad Meyer * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 16a3c41f8bSConrad Meyer * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 17a3c41f8bSConrad Meyer * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 18a3c41f8bSConrad Meyer * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 19a3c41f8bSConrad Meyer * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 20a3c41f8bSConrad Meyer * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 21a3c41f8bSConrad Meyer * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 22a3c41f8bSConrad Meyer * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 23a3c41f8bSConrad Meyer * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 24a3c41f8bSConrad Meyer * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 25a3c41f8bSConrad Meyer * SUCH DAMAGE. 26a3c41f8bSConrad Meyer */ 27a3c41f8bSConrad Meyer 28a3c41f8bSConrad Meyer #include <sys/cdefs.h> 29a3c41f8bSConrad Meyer __FBSDID("$FreeBSD$"); 30a3c41f8bSConrad Meyer 31a3c41f8bSConrad Meyer #include <sys/param.h> 32a3c41f8bSConrad Meyer #include <sys/fail.h> 33a3c41f8bSConrad Meyer #include <sys/limits.h> 34a3c41f8bSConrad Meyer #include <sys/lock.h> 35a3c41f8bSConrad Meyer #include <sys/kernel.h> 36a3c41f8bSConrad Meyer #include <sys/malloc.h> 37a3c41f8bSConrad Meyer #include <sys/mutex.h> 38a3c41f8bSConrad Meyer #include <sys/random.h> 39a3c41f8bSConrad Meyer #include <sys/sdt.h> 40a3c41f8bSConrad Meyer #include <sys/sysctl.h> 41a3c41f8bSConrad Meyer #include <sys/systm.h> 42a3c41f8bSConrad Meyer 43a3c41f8bSConrad Meyer #include <machine/cpu.h> 44a3c41f8bSConrad Meyer #include <machine/stdarg.h> 45a3c41f8bSConrad Meyer 46a3c41f8bSConrad Meyer #define CHACHA_EMBED 47a3c41f8bSConrad Meyer #define KEYSTREAM_ONLY 48a3c41f8bSConrad Meyer #define CHACHA_NONCE0_CTR128 49a3c41f8bSConrad Meyer #include <crypto/chacha20/chacha.h> 50a3c41f8bSConrad Meyer #include <crypto/rijndael/rijndael-api-fst.h> 51a3c41f8bSConrad Meyer #include <crypto/sha2/sha256.h> 52a3c41f8bSConrad Meyer 53a3c41f8bSConrad Meyer #include <dev/random/hash.h> 54a3c41f8bSConrad Meyer #include <dev/random/randomdev.h> 55a3c41f8bSConrad Meyer #include <dev/random/random_harvestq.h> 56a3c41f8bSConrad Meyer #include <dev/random/uint128.h> 57a3c41f8bSConrad Meyer 58a3c41f8bSConrad Meyer #include <dev/random/fenestrasX/fx_hash.h> 59a3c41f8bSConrad Meyer #include <dev/random/fenestrasX/fx_priv.h> 60a3c41f8bSConrad Meyer #include <dev/random/fenestrasX/fx_rng.h> 61a3c41f8bSConrad Meyer 62a3c41f8bSConrad Meyer _Static_assert(FX_CHACHA20_KEYSIZE == RANDOM_KEYSIZE, ""); 63a3c41f8bSConrad Meyer 64a3c41f8bSConrad Meyer #include <crypto/chacha20/chacha.c> 65a3c41f8bSConrad Meyer 66a3c41f8bSConrad Meyer static void 67a3c41f8bSConrad Meyer fxrng_rng_keystream_internal(struct chacha_ctx *prf, void *buf, size_t nbytes) 68a3c41f8bSConrad Meyer { 69a3c41f8bSConrad Meyer size_t chunklen; 70a3c41f8bSConrad Meyer 71a3c41f8bSConrad Meyer while (nbytes > 0) { 72a3c41f8bSConrad Meyer chunklen = MIN(nbytes, 73a3c41f8bSConrad Meyer rounddown((size_t)UINT32_MAX, CHACHA_BLOCKLEN)); 74a3c41f8bSConrad Meyer 75a3c41f8bSConrad Meyer chacha_encrypt_bytes(prf, NULL, buf, chunklen); 76a3c41f8bSConrad Meyer buf = (uint8_t *)buf + chunklen; 77a3c41f8bSConrad Meyer nbytes -= chunklen; 78a3c41f8bSConrad Meyer } 79a3c41f8bSConrad Meyer } 80a3c41f8bSConrad Meyer 81a3c41f8bSConrad Meyer /* 82a3c41f8bSConrad Meyer * This subroutine pulls the counter out of Chacha, which for whatever reason 83a3c41f8bSConrad Meyer * always encodes and decodes counters in a little endian format, and adds 84a3c41f8bSConrad Meyer * 'addend' to it, saving the result in Chacha. 85a3c41f8bSConrad Meyer */ 86a3c41f8bSConrad Meyer static void 87a3c41f8bSConrad Meyer fxrng_chacha_nonce_add64(struct chacha_ctx *ctx, uint64_t addend) 88a3c41f8bSConrad Meyer { 89a3c41f8bSConrad Meyer uint128_t ctr; /* Native-endian. */ 90a3c41f8bSConrad Meyer #if BYTE_ORDER == BIG_ENDIAN 91a3c41f8bSConrad Meyer uint128_t lectr; 92a3c41f8bSConrad Meyer 93a3c41f8bSConrad Meyer chacha_ctrsave(ctx, (void *)&lectr); 94a3c41f8bSConrad Meyer ctr = le128dec(&lectr); 95a3c41f8bSConrad Meyer #else 96a3c41f8bSConrad Meyer chacha_ctrsave(ctx, (void *)&ctr); 97a3c41f8bSConrad Meyer #endif 98a3c41f8bSConrad Meyer 99a3c41f8bSConrad Meyer uint128_add64(&ctr, addend); 100a3c41f8bSConrad Meyer 101a3c41f8bSConrad Meyer /* chacha_ivsetup() does not modify the key, and we rely on that. */ 102a3c41f8bSConrad Meyer #if BYTE_ORDER == BIG_ENDIAN 103a3c41f8bSConrad Meyer le128enc(&lectr, ctr); 104a3c41f8bSConrad Meyer chacha_ivsetup(ctx, NULL, (const void *)&lectr); 105a3c41f8bSConrad Meyer explicit_bzero(&lectr, sizeof(lectr)); 106a3c41f8bSConrad Meyer #else 107a3c41f8bSConrad Meyer chacha_ivsetup(ctx, NULL, (const void *)&ctr); 108a3c41f8bSConrad Meyer #endif 109a3c41f8bSConrad Meyer explicit_bzero(&ctr, sizeof(ctr)); 110a3c41f8bSConrad Meyer } 111a3c41f8bSConrad Meyer 112a3c41f8bSConrad Meyer /* 113a3c41f8bSConrad Meyer * Generate from the unbuffered source PRNG. 114a3c41f8bSConrad Meyer * 115a3c41f8bSConrad Meyer * Handles fast key erasure (rekeys the PRF with a generated key under lock). 116a3c41f8bSConrad Meyer * 117a3c41f8bSConrad Meyer * RNG lock is required on entry. If return_unlocked is true, RNG lock will 118a3c41f8bSConrad Meyer * be dropped on return. 119a3c41f8bSConrad Meyer */ 120a3c41f8bSConrad Meyer void 121a3c41f8bSConrad Meyer fxrng_rng_genrandom_internal(struct fxrng_basic_rng *rng, void *buf, 122a3c41f8bSConrad Meyer size_t nbytes, bool return_unlocked) 123a3c41f8bSConrad Meyer { 124a3c41f8bSConrad Meyer struct chacha_ctx ctx_copy, *p_ctx; 125a3c41f8bSConrad Meyer uint8_t newkey[FX_CHACHA20_KEYSIZE]; 126a3c41f8bSConrad Meyer size_t blockcount; 127a3c41f8bSConrad Meyer 128a3c41f8bSConrad Meyer FXRNG_RNG_ASSERT(rng); 129a3c41f8bSConrad Meyer 130a3c41f8bSConrad Meyer /* Save off the initial output of the generator for rekeying. */ 131a3c41f8bSConrad Meyer fxrng_rng_keystream_internal(&rng->rng_prf, newkey, sizeof(newkey)); 132a3c41f8bSConrad Meyer 133a3c41f8bSConrad Meyer if (return_unlocked) { 134a3c41f8bSConrad Meyer memcpy(&ctx_copy, &rng->rng_prf, sizeof(ctx_copy)); 135a3c41f8bSConrad Meyer p_ctx = &ctx_copy; 136a3c41f8bSConrad Meyer 137a3c41f8bSConrad Meyer /* 138a3c41f8bSConrad Meyer * Forward the Chacha counter state over the blocks we promise 139a3c41f8bSConrad Meyer * to generate for the caller without the lock. 140a3c41f8bSConrad Meyer */ 141a3c41f8bSConrad Meyer blockcount = howmany(nbytes, CHACHA_BLOCKLEN); 142a3c41f8bSConrad Meyer fxrng_chacha_nonce_add64(&rng->rng_prf, blockcount); 143a3c41f8bSConrad Meyer 144a3c41f8bSConrad Meyer /* Re-key before dropping the lock. */ 145a3c41f8bSConrad Meyer chacha_keysetup(&rng->rng_prf, newkey, sizeof(newkey) * 8); 146a3c41f8bSConrad Meyer explicit_bzero(newkey, sizeof(newkey)); 147a3c41f8bSConrad Meyer 148a3c41f8bSConrad Meyer FXRNG_RNG_UNLOCK(rng); 149a3c41f8bSConrad Meyer } else { 150a3c41f8bSConrad Meyer p_ctx = &rng->rng_prf; 151a3c41f8bSConrad Meyer } 152a3c41f8bSConrad Meyer 153a3c41f8bSConrad Meyer fxrng_rng_keystream_internal(p_ctx, buf, nbytes); 154a3c41f8bSConrad Meyer 155a3c41f8bSConrad Meyer if (return_unlocked) { 156a3c41f8bSConrad Meyer explicit_bzero(&ctx_copy, sizeof(ctx_copy)); 157a3c41f8bSConrad Meyer FXRNG_RNG_ASSERT_NOT(rng); 158a3c41f8bSConrad Meyer } else { 159a3c41f8bSConrad Meyer /* Re-key before exit. */ 160a3c41f8bSConrad Meyer chacha_keysetup(&rng->rng_prf, newkey, sizeof(newkey) * 8); 161a3c41f8bSConrad Meyer explicit_bzero(newkey, sizeof(newkey)); 162a3c41f8bSConrad Meyer FXRNG_RNG_ASSERT(rng); 163a3c41f8bSConrad Meyer } 164a3c41f8bSConrad Meyer } 165a3c41f8bSConrad Meyer 166a3c41f8bSConrad Meyer /* 167a3c41f8bSConrad Meyer * Helper to reseed the root RNG, incorporating the existing RNG state. 168a3c41f8bSConrad Meyer * 169a3c41f8bSConrad Meyer * The root RNG is locked on entry and locked on return. 170a3c41f8bSConrad Meyer */ 171a3c41f8bSConrad Meyer static void 172a3c41f8bSConrad Meyer fxrng_rng_reseed_internal(struct fxrng_basic_rng *rng, bool seeded, 173a3c41f8bSConrad Meyer const void *src, size_t sz, ...) 174a3c41f8bSConrad Meyer { 175a3c41f8bSConrad Meyer union { 176a3c41f8bSConrad Meyer uint8_t root_state[FX_CHACHA20_KEYSIZE]; 177a3c41f8bSConrad Meyer uint8_t hash_out[FXRNG_HASH_SZ]; 178a3c41f8bSConrad Meyer } u; 179a3c41f8bSConrad Meyer struct fxrng_hash mix; 180a3c41f8bSConrad Meyer va_list ap; 181a3c41f8bSConrad Meyer 182a3c41f8bSConrad Meyer _Static_assert(FX_CHACHA20_KEYSIZE <= FXRNG_HASH_SZ, ""); 183a3c41f8bSConrad Meyer 184a3c41f8bSConrad Meyer FXRNG_RNG_ASSERT(rng); 185a3c41f8bSConrad Meyer 186a3c41f8bSConrad Meyer fxrng_hash_init(&mix); 187a3c41f8bSConrad Meyer if (seeded) { 188a3c41f8bSConrad Meyer fxrng_rng_keystream_internal(&rng->rng_prf, u.root_state, 189a3c41f8bSConrad Meyer sizeof(u.root_state)); 190a3c41f8bSConrad Meyer fxrng_hash_update(&mix, u.root_state, sizeof(u.root_state)); 191a3c41f8bSConrad Meyer } 192a3c41f8bSConrad Meyer fxrng_hash_update(&mix, src, sz); 193a3c41f8bSConrad Meyer 194a3c41f8bSConrad Meyer va_start(ap, sz); 195a3c41f8bSConrad Meyer while (true) { 196a3c41f8bSConrad Meyer src = va_arg(ap, const void *); 197a3c41f8bSConrad Meyer if (src == NULL) 198a3c41f8bSConrad Meyer break; 199a3c41f8bSConrad Meyer sz = va_arg(ap, size_t); 200a3c41f8bSConrad Meyer fxrng_hash_update(&mix, src, sz); 201a3c41f8bSConrad Meyer } 202a3c41f8bSConrad Meyer va_end(ap); 203a3c41f8bSConrad Meyer 204a3c41f8bSConrad Meyer fxrng_hash_finish(&mix, u.hash_out, sizeof(u.hash_out)); 205a3c41f8bSConrad Meyer 206a3c41f8bSConrad Meyer /* 207a3c41f8bSConrad Meyer * Take the first keysize (32) bytes of our digest (64 bytes). It is 208a3c41f8bSConrad Meyer * also possible to just have Blake2 emit fewer bytes, but our wrapper 209a3c41f8bSConrad Meyer * API doesn't provide that functionality and there isn't anything 210a3c41f8bSConrad Meyer * obviously wrong with emitting more hash bytes. 211a3c41f8bSConrad Meyer * 212a3c41f8bSConrad Meyer * keysetup does not reset the embedded counter, and we rely on that 213a3c41f8bSConrad Meyer * property. 214a3c41f8bSConrad Meyer */ 215a3c41f8bSConrad Meyer chacha_keysetup(&rng->rng_prf, u.hash_out, FX_CHACHA20_KEYSIZE * 8); 216a3c41f8bSConrad Meyer 217a3c41f8bSConrad Meyer /* 'mix' zeroed by fxrng_hash_finish(). */ 218a3c41f8bSConrad Meyer explicit_bzero(u.hash_out, sizeof(u.hash_out)); 219a3c41f8bSConrad Meyer 220a3c41f8bSConrad Meyer FXRNG_RNG_ASSERT(rng); 221a3c41f8bSConrad Meyer } 222a3c41f8bSConrad Meyer 223a3c41f8bSConrad Meyer /* 224a3c41f8bSConrad Meyer * Directly reseed the root RNG from a first-time entropy source, 225a3c41f8bSConrad Meyer * incorporating the existing RNG state, called by fxrng_brng_src_reseed. 226a3c41f8bSConrad Meyer * 227a3c41f8bSConrad Meyer * The root RNG is locked on entry and locked on return. 228a3c41f8bSConrad Meyer */ 229a3c41f8bSConrad Meyer void 230a3c41f8bSConrad Meyer fxrng_rng_src_reseed(struct fxrng_basic_rng *rng, 231a3c41f8bSConrad Meyer const struct harvest_event *event) 232a3c41f8bSConrad Meyer { 233a3c41f8bSConrad Meyer fxrng_rng_reseed_internal(rng, true, &event->he_somecounter, 234a3c41f8bSConrad Meyer sizeof(event->he_somecounter), (const void *)event->he_entropy, 235a3c41f8bSConrad Meyer (size_t)event->he_size, NULL); 236a3c41f8bSConrad Meyer } 237a3c41f8bSConrad Meyer 238a3c41f8bSConrad Meyer /* 239a3c41f8bSConrad Meyer * Reseed the root RNG from pooled entropy, incorporating the existing RNG 240a3c41f8bSConrad Meyer * state, called by fxrng_brng_reseed. 241a3c41f8bSConrad Meyer * 242a3c41f8bSConrad Meyer * The root RNG is locked on entry and locked on return. 243a3c41f8bSConrad Meyer */ 244a3c41f8bSConrad Meyer void 245a3c41f8bSConrad Meyer fxrng_rng_reseed(struct fxrng_basic_rng *rng, bool seeded, const void *entr, 246a3c41f8bSConrad Meyer size_t sz) 247a3c41f8bSConrad Meyer { 248a3c41f8bSConrad Meyer fxrng_rng_reseed_internal(rng, seeded, entr, sz, NULL); 249a3c41f8bSConrad Meyer } 250