Date: Sun, 16 Apr 2017 04:50:43 -0700 (PDT) From: "Rodney W. Grimes" <freebsd@pdx.rh.CN85.dnsmgr.net> To: Mark R V Murray <markm@freebsd.org> Cc: src-committers <src-committers@freebsd.org>, svn-src-all@freebsd.org, svn-src-head@freebsd.org Subject: Re: svn commit: r317015 - in head/sys: boot/forth conf crypto/chacha20 dev/random libkern sys Message-ID: <201704161150.v3GBohYF016403@pdx.rh.CN85.dnsmgr.net> In-Reply-To: <BC50327E-E601-4FC4-98A7-0B258086CEFB@FreeBSD.org>
next in thread | previous in thread | raw e-mail | index | archive | help
> This does not use DES' Chacha20 commit, as I had already completed the > testing for it, and received SO@ approval. > > DES's commit made Chaha20 a module. This is of no use to arc4random(9), > which needs the code to be standard. Also his API is different. > > I have no objection to reworking the arc4random/Chacha below to use DES' > version of Chacha, but his code needs to be standard library code, > not an optional module. > > Any objections to me doing this? Yes We need to move towards more modules, not less. Having this standard does not even allow one to compile a kernel without it. I should be able to compile a kernel without arc4random(9) and without chacha if I so desire. And I should be able to load and unload these if I so desire. This later feature is VERY usefull for developement and debug cycles. I am sure with careful though we can find a way to allow arc4random to use a pointer that knows if the chacha code is avaliable, and use it if so, and if not fall back to something else, or punt with an error return. I have done this with minidumps, if my module is not loaded and the kernel panics, and is set to attempt a minidump it just logs another error when it finds the NULL pointer and continues on its way to panic. > M > > > On 16 Apr 2017, at 10:11, Mark Murray <markm@FreeBSD.org> wrote: > > > > Author: markm > > Date: Sun Apr 16 09:11:02 2017 > > New Revision: 317015 > > URL: https://svnweb.freebsd.org/changeset/base/317015 > > > > Log: > > Replace the RC4 algorithm for generating in-kernel secure random > > numbers with Chacha20. Keep the API, though, as that is what the > > other *BSD's have done. > > > > Use the boot-time entropy stash (if present) to bootstrap the > > in-kernel entropy source. > > > > Reviewed by: delphij,rwatson > > Approved by: so(delphij) > > MFC after: 2 months > > Relnotes: yes > > Differential Revision: https://reviews.freebsd.org/D10048 > > --This line, and those below, will be ignored-- > >> Description of fields to fill in above: 76 columns --| > >> PR: If and which Problem Report is related. > >> Submitted by: If someone else sent in the change. > >> Reported by: If someone else reported the issue. > >> Reviewed by: If someone else reviewed your modification. > >> Approved by: If you needed approval for this commit. > >> Obtained from: If the change is from a third party. > >> MFC after: N [day[s]|week[s]|month[s]]. Request a reminder email. > >> MFH: Ports tree branch name. Request approval for merge. > >> Relnotes: Set to 'yes' for mention in release notes. > >> Security: Vulnerability reference (one per line) or description. > >> Sponsored by: If the change was sponsored by an organization. > >> Differential Revision: https://reviews.freebsd.org/D### (*full* phabric URL needed). > >> Empty fields above will be automatically removed. > > > > Added: > > head/sys/crypto/chacha20/chacha.c (contents, props changed) > > head/sys/crypto/chacha20/chacha.h (contents, props changed) > > Modified: > > head/sys/boot/forth/loader.conf > > head/sys/conf/files > > head/sys/dev/random/random_harvestq.c > > head/sys/dev/random/random_harvestq.h > > head/sys/libkern/arc4random.c > > head/sys/sys/libkern.h > > head/sys/sys/random.h > > > > Modified: head/sys/boot/forth/loader.conf > > ============================================================================== > > --- head/sys/boot/forth/loader.conf Sun Apr 16 09:00:10 2017 (r317014) > > +++ head/sys/boot/forth/loader.conf Sun Apr 16 09:11:02 2017 (r317015) > > @@ -48,7 +48,7 @@ bitmap_type="splash_image_data" # and pl > > entropy_cache_load="YES" # Set this to NO to disable loading > > # entropy at boot time > > entropy_cache_name="/boot/entropy" # Set this to the name of the file > > -entropy_cache_type="/boot/entropy" # Required for the kernel to find > > +entropy_cache_type="boot_entropy_cache" # Required for the kernel to find > > # the boot-time entropy cache. This > > # must not change value even if the > > # _name above does change! > > > > Modified: head/sys/conf/files > > ============================================================================== > > --- head/sys/conf/files Sun Apr 16 09:00:10 2017 (r317014) > > +++ head/sys/conf/files Sun Apr 16 09:11:02 2017 (r317015) > > @@ -3810,6 +3810,7 @@ kgssapi/gsstest.c optional kgssapi_debu > > # the file should be moved to conf/files.<arch> from here. > > # > > libkern/arc4random.c standard > > +crypto/chacha20/chacha.c standard > > libkern/asprintf.c standard > > libkern/bcd.c standard > > libkern/bsearch.c standard > > > > Added: head/sys/crypto/chacha20/chacha.c > > ============================================================================== > > --- /dev/null 00:00:00 1970 (empty, because file is newly added) > > +++ head/sys/crypto/chacha20/chacha.c Sun Apr 16 09:11:02 2017 (r317015) > > @@ -0,0 +1,224 @@ > > +/* > > +chacha-merged.c version 20080118 > > +D. J. Bernstein > > +Public domain. > > +*/ > > + > > +/* $OpenBSD: chacha.c,v 1.1 2013/11/21 00:45:44 djm Exp $ */ > > + > > +#include <sys/cdefs.h> > > +__FBSDID("$FreeBSD$"); > > + > > +#include <sys/param.h> > > +#include <sys/types.h> > > + > > +#include <crypto/chacha20/chacha.h> > > + > > + > > +typedef uint8_t u8; > > +typedef uint32_t u32; > > + > > +typedef struct chacha_ctx chacha_ctx; > > + > > +#define U8C(v) (v##U) > > +#define U32C(v) (v##U) > > + > > +#define U8V(v) ((u8)(v) & U8C(0xFF)) > > +#define U32V(v) ((u32)(v) & U32C(0xFFFFFFFF)) > > + > > +#define ROTL32(v, n) \ > > + (U32V((v) << (n)) | ((v) >> (32 - (n)))) > > + > > +#define U8TO32_LITTLE(p) \ > > + (((u32)((p)[0]) ) | \ > > + ((u32)((p)[1]) << 8) | \ > > + ((u32)((p)[2]) << 16) | \ > > + ((u32)((p)[3]) << 24)) > > + > > +#define U32TO8_LITTLE(p, v) \ > > + do { \ > > + (p)[0] = U8V((v) ); \ > > + (p)[1] = U8V((v) >> 8); \ > > + (p)[2] = U8V((v) >> 16); \ > > + (p)[3] = U8V((v) >> 24); \ > > + } while (0) > > + > > +#define ROTATE(v,c) (ROTL32(v,c)) > > +#define XOR(v,w) ((v) ^ (w)) > > +#define PLUS(v,w) (U32V((v) + (w))) > > +#define PLUSONE(v) (PLUS((v),1)) > > + > > +#define QUARTERROUND(a,b,c,d) \ > > + a = PLUS(a,b); d = ROTATE(XOR(d,a),16); \ > > + c = PLUS(c,d); b = ROTATE(XOR(b,c),12); \ > > + a = PLUS(a,b); d = ROTATE(XOR(d,a), 8); \ > > + c = PLUS(c,d); b = ROTATE(XOR(b,c), 7); > > + > > +static const char sigma[16] = "expand 32-byte k"; > > +static const char tau[16] = "expand 16-byte k"; > > + > > +void > > +chacha_keysetup(chacha_ctx *x,const u8 *k,u32 kbits) > > +{ > > + const char *constants; > > + > > + x->input[4] = U8TO32_LITTLE(k + 0); > > + x->input[5] = U8TO32_LITTLE(k + 4); > > + x->input[6] = U8TO32_LITTLE(k + 8); > > + x->input[7] = U8TO32_LITTLE(k + 12); > > + if (kbits == 256) { /* recommended */ > > + k += 16; > > + constants = sigma; > > + } else { /* kbits == 128 */ > > + constants = tau; > > + } > > + x->input[8] = U8TO32_LITTLE(k + 0); > > + x->input[9] = U8TO32_LITTLE(k + 4); > > + x->input[10] = U8TO32_LITTLE(k + 8); > > + x->input[11] = U8TO32_LITTLE(k + 12); > > + x->input[0] = U8TO32_LITTLE(constants + 0); > > + x->input[1] = U8TO32_LITTLE(constants + 4); > > + x->input[2] = U8TO32_LITTLE(constants + 8); > > + x->input[3] = U8TO32_LITTLE(constants + 12); > > +} > > + > > +void > > +chacha_ivsetup(chacha_ctx *x, const u8 *iv, const u8 *counter) > > +{ > > + x->input[12] = counter == NULL ? 0 : U8TO32_LITTLE(counter + 0); > > + x->input[13] = counter == NULL ? 0 : U8TO32_LITTLE(counter + 4); > > + x->input[14] = U8TO32_LITTLE(iv + 0); > > + x->input[15] = U8TO32_LITTLE(iv + 4); > > +} > > + > > +void > > +chacha_encrypt_bytes(chacha_ctx *x,const u8 *m,u8 *c,u32 bytes) > > +{ > > + u32 x0, x1, x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, x12, x13, x14, x15; > > + u32 j0, j1, j2, j3, j4, j5, j6, j7, j8, j9, j10, j11, j12, j13, j14, j15; > > + u8 *ctarget = NULL; > > + u8 tmp[64]; > > + u_int i; > > + > > + if (!bytes) return; > > + > > + j0 = x->input[0]; > > + j1 = x->input[1]; > > + j2 = x->input[2]; > > + j3 = x->input[3]; > > + j4 = x->input[4]; > > + j5 = x->input[5]; > > + j6 = x->input[6]; > > + j7 = x->input[7]; > > + j8 = x->input[8]; > > + j9 = x->input[9]; > > + j10 = x->input[10]; > > + j11 = x->input[11]; > > + j12 = x->input[12]; > > + j13 = x->input[13]; > > + j14 = x->input[14]; > > + j15 = x->input[15]; > > + > > + for (;;) { > > + if (bytes < 64) { > > + for (i = 0;i < bytes;++i) tmp[i] = m[i]; > > + m = tmp; > > + ctarget = c; > > + c = tmp; > > + } > > + x0 = j0; > > + x1 = j1; > > + x2 = j2; > > + x3 = j3; > > + x4 = j4; > > + x5 = j5; > > + x6 = j6; > > + x7 = j7; > > + x8 = j8; > > + x9 = j9; > > + x10 = j10; > > + x11 = j11; > > + x12 = j12; > > + x13 = j13; > > + x14 = j14; > > + x15 = j15; > > + for (i = 20;i > 0;i -= 2) { > > + QUARTERROUND( x0, x4, x8,x12) > > + QUARTERROUND( x1, x5, x9,x13) > > + QUARTERROUND( x2, x6,x10,x14) > > + QUARTERROUND( x3, x7,x11,x15) > > + QUARTERROUND( x0, x5,x10,x15) > > + QUARTERROUND( x1, x6,x11,x12) > > + QUARTERROUND( x2, x7, x8,x13) > > + QUARTERROUND( x3, x4, x9,x14) > > + } > > + x0 = PLUS(x0,j0); > > + x1 = PLUS(x1,j1); > > + x2 = PLUS(x2,j2); > > + x3 = PLUS(x3,j3); > > + x4 = PLUS(x4,j4); > > + x5 = PLUS(x5,j5); > > + x6 = PLUS(x6,j6); > > + x7 = PLUS(x7,j7); > > + x8 = PLUS(x8,j8); > > + x9 = PLUS(x9,j9); > > + x10 = PLUS(x10,j10); > > + x11 = PLUS(x11,j11); > > + x12 = PLUS(x12,j12); > > + x13 = PLUS(x13,j13); > > + x14 = PLUS(x14,j14); > > + x15 = PLUS(x15,j15); > > + > > + x0 = XOR(x0,U8TO32_LITTLE(m + 0)); > > + x1 = XOR(x1,U8TO32_LITTLE(m + 4)); > > + x2 = XOR(x2,U8TO32_LITTLE(m + 8)); > > + x3 = XOR(x3,U8TO32_LITTLE(m + 12)); > > + x4 = XOR(x4,U8TO32_LITTLE(m + 16)); > > + x5 = XOR(x5,U8TO32_LITTLE(m + 20)); > > + x6 = XOR(x6,U8TO32_LITTLE(m + 24)); > > + x7 = XOR(x7,U8TO32_LITTLE(m + 28)); > > + x8 = XOR(x8,U8TO32_LITTLE(m + 32)); > > + x9 = XOR(x9,U8TO32_LITTLE(m + 36)); > > + x10 = XOR(x10,U8TO32_LITTLE(m + 40)); > > + x11 = XOR(x11,U8TO32_LITTLE(m + 44)); > > + x12 = XOR(x12,U8TO32_LITTLE(m + 48)); > > + x13 = XOR(x13,U8TO32_LITTLE(m + 52)); > > + x14 = XOR(x14,U8TO32_LITTLE(m + 56)); > > + x15 = XOR(x15,U8TO32_LITTLE(m + 60)); > > + > > + j12 = PLUSONE(j12); > > + if (!j12) { > > + j13 = PLUSONE(j13); > > + /* stopping at 2^70 bytes per nonce is user's responsibility */ > > + } > > + > > + U32TO8_LITTLE(c + 0,x0); > > + U32TO8_LITTLE(c + 4,x1); > > + U32TO8_LITTLE(c + 8,x2); > > + U32TO8_LITTLE(c + 12,x3); > > + U32TO8_LITTLE(c + 16,x4); > > + U32TO8_LITTLE(c + 20,x5); > > + U32TO8_LITTLE(c + 24,x6); > > + U32TO8_LITTLE(c + 28,x7); > > + U32TO8_LITTLE(c + 32,x8); > > + U32TO8_LITTLE(c + 36,x9); > > + U32TO8_LITTLE(c + 40,x10); > > + U32TO8_LITTLE(c + 44,x11); > > + U32TO8_LITTLE(c + 48,x12); > > + U32TO8_LITTLE(c + 52,x13); > > + U32TO8_LITTLE(c + 56,x14); > > + U32TO8_LITTLE(c + 60,x15); > > + > > + if (bytes <= 64) { > > + if (bytes < 64) { > > + for (i = 0;i < bytes;++i) ctarget[i] = c[i]; > > + } > > + x->input[12] = j12; > > + x->input[13] = j13; > > + return; > > + } > > + bytes -= 64; > > + c += 64; > > + m += 64; > > + } > > +} > > > > Added: head/sys/crypto/chacha20/chacha.h > > ============================================================================== > > --- /dev/null 00:00:00 1970 (empty, because file is newly added) > > +++ head/sys/crypto/chacha20/chacha.h Sun Apr 16 09:11:02 2017 (r317015) > > @@ -0,0 +1,32 @@ > > +/* $OpenBSD: chacha.h,v 1.4 2016/08/27 04:04:56 guenther Exp $ */ > > + > > +/* > > +chacha-merged.c version 20080118 > > +D. J. Bernstein > > +Public domain. > > + > > + $FreeBSD$ > > +*/ > > + > > +#ifndef CHACHA_H > > +#define CHACHA_H > > + > > +#include <sys/types.h> > > + > > +struct chacha_ctx { > > + u_int input[16]; > > +}; > > + > > +#define CHACHA_MINKEYLEN 16 > > +#define CHACHA_NONCELEN 8 > > +#define CHACHA_CTRLEN 8 > > +#define CHACHA_STATELEN (CHACHA_NONCELEN+CHACHA_CTRLEN) > > +#define CHACHA_BLOCKLEN 64 > > + > > +void chacha_keysetup(struct chacha_ctx *x, const u_char *k, u_int kbits); > > +void chacha_ivsetup(struct chacha_ctx *x, const u_char *iv, const u_char *ctr); > > +void chacha_encrypt_bytes(struct chacha_ctx *x, const u_char *m, > > + u_char *c, u_int bytes); > > + > > +#endif /* CHACHA_H */ > > + > > > > Modified: head/sys/dev/random/random_harvestq.c > > ============================================================================== > > --- head/sys/dev/random/random_harvestq.c Sun Apr 16 09:00:10 2017 (r317014) > > +++ head/sys/dev/random/random_harvestq.c Sun Apr 16 09:11:02 2017 (r317015) > > @@ -352,10 +352,19 @@ random_harvestq_prime(void *unused __unu > > * Get entropy that may have been preloaded by loader(8) > > * and use it to pre-charge the entropy harvest queue. > > */ > > - keyfile = preload_search_by_type(RANDOM_HARVESTQ_BOOT_ENTROPY_FILE); > > + keyfile = preload_search_by_type(RANDOM_CACHED_BOOT_ENTROPY_MODULE); > > +#ifndef NO_BACKWARD_COMPATIBILITY > > + if (keyfile == NULL) > > + keyfile = preload_search_by_type(RANDOM_LEGACY_BOOT_ENTROPY_MODULE); > > +#endif > > if (keyfile != NULL) { > > data = preload_fetch_addr(keyfile); > > size = preload_fetch_size(keyfile); > > + /* skip the first bit of the stash so others like arc4 can also have some. */ > > + if (size > RANDOM_CACHED_SKIP_START) { > > + data += RANDOM_CACHED_SKIP_START; > > + size -= RANDOM_CACHED_SKIP_START; > > + } > > /* Trim the size. If the admin has a file with a funny size, we lose some. Tough. */ > > size -= (size % sizeof(event.he_entropy)); > > if (data != NULL && size != 0) { > > > > Modified: head/sys/dev/random/random_harvestq.h > > ============================================================================== > > --- head/sys/dev/random/random_harvestq.h Sun Apr 16 09:00:10 2017 (r317014) > > +++ head/sys/dev/random/random_harvestq.h Sun Apr 16 09:11:02 2017 (r317015) > > @@ -1,5 +1,5 @@ > > /*- > > - * Copyright (c) 2013-2015 Mark R V Murray > > + * Copyright (c) 2013-2015, 2017 Mark R V Murray > > * All rights reserved. > > * > > * Redistribution and use in source and binary forms, with or without > > @@ -45,8 +45,6 @@ struct harvest_event { > > > > void read_rate_increment(u_int); > > > > -#define RANDOM_HARVESTQ_BOOT_ENTROPY_FILE "/boot/entropy" > > - > > #define RANDOM_HARVEST_INIT_LOCK(x) mtx_init(&harvest_context.hc_mtx, "entropy harvest mutex", NULL, MTX_SPIN) > > #define RANDOM_HARVEST_LOCK(x) mtx_lock_spin(&harvest_context.hc_mtx) > > #define RANDOM_HARVEST_UNLOCK(x) mtx_unlock_spin(&harvest_context.hc_mtx) > > > > Modified: head/sys/libkern/arc4random.c > > ============================================================================== > > --- head/sys/libkern/arc4random.c Sun Apr 16 09:00:10 2017 (r317014) > > +++ head/sys/libkern/arc4random.c Sun Apr 16 09:11:02 2017 (r317015) > > @@ -1,11 +1,28 @@ > > /*- > > - * THE BEER-WARE LICENSE > > + * Copyright (c) 2017 The FreeBSD Foundation > > + * All rights reserved. > > * > > - * <dan@FreeBSD.ORG> wrote this file. As long as you retain this notice you > > - * can do whatever you want with this stuff. If we meet some day, and you > > - * think this stuff is worth it, you can buy me a beer in return. > > + * Redistribution and use in source and binary forms, with or without > > + * modification, are permitted provided that the following conditions > > + * are met: > > + * 1. Redistributions of source code must retain the above copyright > > + * notice, this list of conditions and the following disclaimer > > + * in this position and unchanged. > > + * 2. Redistributions in binary form must reproduce the above copyright > > + * notice, this list of conditions and the following disclaimer in the > > + * documentation and/or other materials provided with the distribution. > > + * > > + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR > > + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES > > + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. > > + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, > > + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT > > + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, > > + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY > > + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT > > + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF > > + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. > > * > > - * Dan Moschuk > > */ > > > > #include <sys/cdefs.h> > > @@ -14,144 +31,122 @@ __FBSDID("$FreeBSD$"); > > #include <sys/types.h> > > #include <sys/param.h> > > #include <sys/kernel.h> > > -#include <sys/random.h> > > #include <sys/libkern.h> > > +#include <sys/linker.h> > > #include <sys/lock.h> > > +#include <sys/malloc.h> > > #include <sys/mutex.h> > > -#include <sys/time.h> > > +#include <sys/random.h> > > #include <sys/smp.h> > > -#include <sys/malloc.h> > > +#include <sys/time.h> > > + > > +#include <crypto/chacha20/chacha.h> > > > > -#define ARC4_RESEED_BYTES 65536 > > -#define ARC4_RESEED_SECONDS 300 > > -#define ARC4_KEYBYTES 256 > > +#define CHACHA20_RESEED_BYTES 65536 > > +#define CHACHA20_RESEED_SECONDS 300 > > +#define CHACHA20_KEYBYTES 32 > > +#define CHACHA20_BUFFER_SIZE 64 > > + > > +CTASSERT(CHACHA20_KEYBYTES*8 >= CHACHA_MINKEYLEN); > > > > int arc4rand_iniseed_state = ARC4_ENTR_NONE; > > > > -MALLOC_DEFINE(M_ARC4RANDOM, "arc4random", "arc4random structures"); > > +MALLOC_DEFINE(M_CHACHA20RANDOM, "chacha20random", "chacha20random structures"); > > > > -struct arc4_s { > > +struct chacha20_s { > > struct mtx mtx; > > - u_int8_t i, j; > > - int numruns; > > - u_int8_t sbox[256]; > > + int numbytes; > > + int first_time_done; > > time_t t_reseed; > > - > > + u_int8_t m_buffer[CHACHA20_BUFFER_SIZE]; > > + struct chacha_ctx ctx; > > } __aligned(CACHE_LINE_SIZE); > > > > -static struct arc4_s *arc4inst = NULL; > > +static struct chacha20_s *chacha20inst = NULL; > > > > -#define ARC4_FOREACH(_arc4) \ > > - for (_arc4 = &arc4inst[0]; _arc4 <= &arc4inst[mp_maxid]; _arc4++) > > - > > -static u_int8_t arc4_randbyte(struct arc4_s *arc4); > > - > > -static __inline void > > -arc4_swap(u_int8_t *a, u_int8_t *b) > > -{ > > - u_int8_t c; > > - > > - c = *a; > > - *a = *b; > > - *b = c; > > -} > > +#define CHACHA20_FOREACH(_chacha20) \ > > + for (_chacha20 = &chacha20inst[0]; \ > > + _chacha20 <= &chacha20inst[mp_maxid]; \ > > + _chacha20++) > > > > /* > > - * Stir our S-box. > > + * Mix up the current context. > > */ > > static void > > -arc4_randomstir(struct arc4_s* arc4) > > +chacha20_randomstir(struct chacha20_s* chacha20) > > { > > - u_int8_t key[ARC4_KEYBYTES]; > > - int n; > > struct timeval tv_now; > > + size_t n, size; > > + u_int8_t key[CHACHA20_KEYBYTES], *data; > > + caddr_t keyfile; > > > > /* > > - * XXX: FIX!! This isn't brilliant. Need more confidence. > > - * This returns zero entropy before random(4) is seeded. > > + * This is making the best of what may be an insecure > > + * Situation. If the loader(8) did not have an entropy > > + * stash from the previous shutdown to load, then we will > > + * be improperly seeded. The answer is to make sure there > > + * is an entropy stash at shutdown time. > > */ > > - (void)read_random(key, ARC4_KEYBYTES); > > - getmicrouptime(&tv_now); > > - mtx_lock(&arc4->mtx); > > - for (n = 0; n < 256; n++) { > > - arc4->j = (arc4->j + arc4->sbox[n] + key[n]) % 256; > > - arc4_swap(&arc4->sbox[n], &arc4->sbox[arc4->j]); > > + (void)read_random(key, CHACHA20_KEYBYTES); > > + if (!chacha20->first_time_done) { > > + keyfile = preload_search_by_type(RANDOM_CACHED_BOOT_ENTROPY_MODULE); > > + if (keyfile != NULL) { > > + data = preload_fetch_addr(keyfile); > > + size = MIN(preload_fetch_size(keyfile), CHACHA20_KEYBYTES); > > + for (n = 0; n < size; n++) > > + key[n] ^= data[n]; > > + explicit_bzero(data, size); > > + if (bootverbose) > > + printf("arc4random: read %zu bytes from preloaded cache\n", size); > > + } else > > + printf("arc4random: no preloaded entropy cache\n"); > > + chacha20->first_time_done = 1; > > } > > - arc4->i = arc4->j = 0; > > + getmicrouptime(&tv_now); > > + mtx_lock(&chacha20->mtx); > > + chacha_keysetup(&chacha20->ctx, key, CHACHA20_KEYBYTES*8); > > + chacha_ivsetup(&chacha20->ctx, (u_char *)&tv_now.tv_sec, (u_char *)&tv_now.tv_usec); > > /* Reset for next reseed cycle. */ > > - arc4->t_reseed = tv_now.tv_sec + ARC4_RESEED_SECONDS; > > - arc4->numruns = 0; > > - /* > > - * Throw away the first N words of output, as suggested in the > > - * paper "Weaknesses in the Key Scheduling Algorithm of RC4" > > - * by Fluher, Mantin, and Shamir. (N = 768 in our case.) > > - * > > - * http://dl.acm.org/citation.cfm?id=646557.694759 > > - */ > > - for (n = 0; n < 768*4; n++) > > - arc4_randbyte(arc4); > > - > > - mtx_unlock(&arc4->mtx); > > + chacha20->t_reseed = tv_now.tv_sec + CHACHA20_RESEED_SECONDS; > > + chacha20->numbytes = 0; > > + mtx_unlock(&chacha20->mtx); > > } > > > > /* > > - * Initialize our S-box to its beginning defaults. > > + * Initialize the contexts. > > */ > > static void > > -arc4_init(void) > > +chacha20_init(void) > > { > > - struct arc4_s *arc4; > > - int n; > > - > > - arc4inst = malloc((mp_maxid + 1) * sizeof(struct arc4_s), > > - M_ARC4RANDOM, M_NOWAIT | M_ZERO); > > - KASSERT(arc4inst != NULL, ("arc4_init: memory allocation error")); > > + struct chacha20_s *chacha20; > > > > - ARC4_FOREACH(arc4) { > > - mtx_init(&arc4->mtx, "arc4_mtx", NULL, MTX_DEF); > > - > > - arc4->i = arc4->j = 0; > > - for (n = 0; n < 256; n++) > > - arc4->sbox[n] = (u_int8_t) n; > > - > > - arc4->t_reseed = -1; > > - arc4->numruns = 0; > > + chacha20inst = malloc((mp_maxid + 1) * sizeof(struct chacha20_s), > > + M_CHACHA20RANDOM, M_NOWAIT | M_ZERO); > > + KASSERT(chacha20inst != NULL, ("chacha20_init: memory allocation error")); > > + > > + CHACHA20_FOREACH(chacha20) { > > + mtx_init(&chacha20->mtx, "chacha20_mtx", NULL, MTX_DEF); > > + chacha20->t_reseed = -1; > > + chacha20->numbytes = 0; > > + chacha20->first_time_done = 0; > > + explicit_bzero(chacha20->m_buffer, CHACHA20_BUFFER_SIZE); > > + explicit_bzero(&chacha20->ctx, sizeof(chacha20->ctx)); > > } > > } > > -SYSINIT(arc4, SI_SUB_LOCK, SI_ORDER_ANY, arc4_init, NULL); > > +SYSINIT(chacha20, SI_SUB_LOCK, SI_ORDER_ANY, chacha20_init, NULL); > > > > > > static void > > -arc4_uninit(void) > > +chacha20_uninit(void) > > { > > - struct arc4_s *arc4; > > + struct chacha20_s *chacha20; > > > > - ARC4_FOREACH(arc4) { > > - mtx_destroy(&arc4->mtx); > > - } > > - > > - free(arc4inst, M_ARC4RANDOM); > > + CHACHA20_FOREACH(chacha20) > > + mtx_destroy(&chacha20->mtx); > > + free(chacha20inst, M_CHACHA20RANDOM); > > } > > +SYSUNINIT(chacha20, SI_SUB_LOCK, SI_ORDER_ANY, chacha20_uninit, NULL); > > > > -SYSUNINIT(arc4, SI_SUB_LOCK, SI_ORDER_ANY, arc4_uninit, NULL); > > - > > - > > -/* > > - * Generate a random byte. > > - */ > > -static u_int8_t > > -arc4_randbyte(struct arc4_s *arc4) > > -{ > > - u_int8_t arc4_t; > > - > > - arc4->i = (arc4->i + 1) % 256; > > - arc4->j = (arc4->j + arc4->sbox[arc4->i]) % 256; > > - > > - arc4_swap(&arc4->sbox[arc4->i], &arc4->sbox[arc4->j]); > > - > > - arc4_t = (arc4->sbox[arc4->i] + arc4->sbox[arc4->j]) % 256; > > - return arc4->sbox[arc4_t]; > > -} > > > > /* > > * MPSAFE > > @@ -159,28 +154,36 @@ arc4_randbyte(struct arc4_s *arc4) > > void > > arc4rand(void *ptr, u_int len, int reseed) > > { > > - u_char *p; > > + struct chacha20_s *chacha20; > > struct timeval tv; > > - struct arc4_s *arc4; > > + u_int length; > > + u_int8_t *p; > > > > - if (reseed || atomic_cmpset_int(&arc4rand_iniseed_state, > > - ARC4_ENTR_HAVE, ARC4_ENTR_SEED)) { > > - ARC4_FOREACH(arc4) > > - arc4_randomstir(arc4); > > - } > > + if (reseed || atomic_cmpset_int(&arc4rand_iniseed_state, ARC4_ENTR_HAVE, ARC4_ENTR_SEED)) > > + CHACHA20_FOREACH(chacha20) > > + chacha20_randomstir(chacha20); > > > > - arc4 = &arc4inst[curcpu]; > > + chacha20 = &chacha20inst[curcpu]; > > getmicrouptime(&tv); > > - if ((arc4->numruns > ARC4_RESEED_BYTES) || > > - (tv.tv_sec > arc4->t_reseed)) > > - arc4_randomstir(arc4); > > + /* We may get unlucky and be migrated off this CPU, but that is expected to be infrequent */ > > + if ((chacha20->numbytes > CHACHA20_RESEED_BYTES) || (tv.tv_sec > chacha20->t_reseed)) > > + chacha20_randomstir(chacha20); > > > > - mtx_lock(&arc4->mtx); > > - arc4->numruns += len; > > + mtx_lock(&chacha20->mtx); > > p = ptr; > > - while (len--) > > - *p++ = arc4_randbyte(arc4); > > - mtx_unlock(&arc4->mtx); > > + while (len) { > > + length = MIN(CHACHA20_BUFFER_SIZE, len); > > + chacha_encrypt_bytes(&chacha20->ctx, chacha20->m_buffer, p, length); > > + p += length; > > + len -= length; > > + chacha20->numbytes += length; > > + if (chacha20->numbytes > CHACHA20_RESEED_BYTES) { > > + mtx_unlock(&chacha20->mtx); > > + chacha20_randomstir(chacha20); > > + mtx_lock(&chacha20->mtx); > > + } > > + } > > + mtx_unlock(&chacha20->mtx); > > } > > > > uint32_t > > @@ -188,6 +191,13 @@ arc4random(void) > > { > > uint32_t ret; > > > > - arc4rand(&ret, sizeof ret, 0); > > + arc4rand(&ret, sizeof(ret), 0); > > return ret; > > } > > + > > +void > > +arc4random_buf(void *ptr, size_t len) > > +{ > > + > > + arc4rand(ptr, len, 0); > > +} > > > > Modified: head/sys/sys/libkern.h > > ============================================================================== > > --- head/sys/sys/libkern.h Sun Apr 16 09:00:10 2017 (r317014) > > +++ head/sys/sys/libkern.h Sun Apr 16 09:11:02 2017 (r317015) > > @@ -117,7 +117,8 @@ extern int arc4rand_iniseed_state; > > /* Prototypes for non-quad routines. */ > > struct malloc_type; > > uint32_t arc4random(void); > > -void arc4rand(void *ptr, u_int len, int reseed); > > +void arc4random_buf(void *, size_t); > > +void arc4rand(void *, u_int, int); > > int bcmp(const void *, const void *, size_t); > > int timingsafe_bcmp(const void *, const void *, size_t); > > void *bsearch(const void *, const void *, size_t, > > > > Modified: head/sys/sys/random.h > > ============================================================================== > > --- head/sys/sys/random.h Sun Apr 16 09:00:10 2017 (r317014) > > +++ head/sys/sys/random.h Sun Apr 16 09:11:02 2017 (r317015) > > @@ -1,5 +1,5 @@ > > /*- > > - * Copyright (c) 2000-2015 Mark R. V. Murray > > + * Copyright (c) 2000-2015, 2017 Mark R. V. Murray > > * All rights reserved. > > * > > * Redistribution and use in source and binary forms, with or without > > @@ -96,6 +96,10 @@ enum random_entropy_source { > > > > #define RANDOM_HARVEST_EVERYTHING_MASK ((1 << (RANDOM_ENVIRONMENTAL_END + 1)) - 1) > > > > +#define RANDOM_LEGACY_BOOT_ENTROPY_MODULE "/boot/entropy" > > +#define RANDOM_CACHED_BOOT_ENTROPY_MODULE "boot_entropy_cache" > > +#define RANDOM_CACHED_SKIP_START 256 > > + > > #if defined(DEV_RANDOM) > > void random_harvest_queue(const void *, u_int, u_int, enum random_entropy_source); > > void random_harvest_fast(const void *, u_int, u_int, enum random_entropy_source); > > > > -- > Mark R V Murray > > > > -- Rod Grimes rgrimes@freebsd.org
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201704161150.v3GBohYF016403>