From owner-svn-src-head@freebsd.org Sun Apr 16 09:19:45 2017 Return-Path: Delivered-To: svn-src-head@mailman.ysv.freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:1900:2254:206a::19:1]) by mailman.ysv.freebsd.org (Postfix) with ESMTP id 22FF9D40AC4; Sun, 16 Apr 2017 09:19:45 +0000 (UTC) (envelope-from markm@FreeBSD.org) Received: from gromit.grondar.org (grandfather.grondar.org [IPv6:2a01:348:0:15:5d59:5c20:0:2]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (Client did not present a certificate) by mx1.freebsd.org (Postfix) with ESMTPS id D0A2A19F3; Sun, 16 Apr 2017 09:19:44 +0000 (UTC) (envelope-from markm@FreeBSD.org) Received: from graveyard.grondar.org ([88.96.155.33] helo=gronkulator.grondar.org) by gromit.grondar.org with esmtpsa (TLSv1.2:ECDHE-RSA-AES256-GCM-SHA384:256) (Exim 4.88 (FreeBSD)) (envelope-from ) id 1czgLM-000Pss-5E; Sun, 16 Apr 2017 10:19:43 +0100 Content-Type: text/plain; charset=us-ascii Mime-Version: 1.0 (Mac OS X Mail 10.3 \(3273\)) Subject: Re: svn commit: r317015 - in head/sys: boot/forth conf crypto/chacha20 dev/random libkern sys From: Mark R V Murray In-Reply-To: <201704160911.v3G9B3df023095@repo.freebsd.org> Date: Sun, 16 Apr 2017 10:19:39 +0100 Content-Transfer-Encoding: quoted-printable Message-Id: References: <201704160911.v3G9B3df023095@repo.freebsd.org> To: src-committers , svn-src-all@freebsd.org, svn-src-head@freebsd.org X-Mailer: Apple Mail (2.3273) X-SA-Score: -1.0 X-BeenThere: svn-src-head@freebsd.org X-Mailman-Version: 2.1.23 Precedence: list List-Id: SVN commit messages for the src tree for head/-current List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Sun, 16 Apr 2017 09:19:45 -0000 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? M > On 16 Apr 2017, at 10:11, Mark Murray wrote: >=20 > Author: markm > Date: Sun Apr 16 09:11:02 2017 > New Revision: 317015 > URL: https://svnweb.freebsd.org/changeset/base/317015 >=20 > 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. >=20 > Use the boot-time entropy stash (if present) to bootstrap the > in-kernel entropy source. >=20 > 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. >=20 > 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 >=20 > Modified: head/sys/boot/forth/loader.conf > = =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D > --- 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=3D"splash_image_data" # and pl > entropy_cache_load=3D"YES" # Set this to NO to disable = loading > # entropy at boot time > entropy_cache_name=3D"/boot/entropy" # Set this to the name of the = file > -entropy_cache_type=3D"/boot/entropy" # Required for the kernel to = find > +entropy_cache_type=3D"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! >=20 > Modified: head/sys/conf/files > = =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D > --- 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. from here. > # > libkern/arc4random.c standard > +crypto/chacha20/chacha.c standard > libkern/asprintf.c standard > libkern/bcd.c standard > libkern/bsearch.c standard >=20 > Added: head/sys/crypto/chacha20/chacha.c > = =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D > --- /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 > +__FBSDID("$FreeBSD$"); > + > +#include > +#include > + > +#include > + > + > +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] =3D U8V((v) ); \ > + (p)[1] =3D U8V((v) >> 8); \ > + (p)[2] =3D U8V((v) >> 16); \ > + (p)[3] =3D 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 =3D PLUS(a,b); d =3D ROTATE(XOR(d,a),16); \ > + c =3D PLUS(c,d); b =3D ROTATE(XOR(b,c),12); \ > + a =3D PLUS(a,b); d =3D ROTATE(XOR(d,a), 8); \ > + c =3D PLUS(c,d); b =3D ROTATE(XOR(b,c), 7); > + > +static const char sigma[16] =3D "expand 32-byte k"; > +static const char tau[16] =3D "expand 16-byte k"; > + > +void > +chacha_keysetup(chacha_ctx *x,const u8 *k,u32 kbits) > +{ > + const char *constants; > + > + x->input[4] =3D U8TO32_LITTLE(k + 0); > + x->input[5] =3D U8TO32_LITTLE(k + 4); > + x->input[6] =3D U8TO32_LITTLE(k + 8); > + x->input[7] =3D U8TO32_LITTLE(k + 12); > + if (kbits =3D=3D 256) { /* recommended */ > + k +=3D 16; > + constants =3D sigma; > + } else { /* kbits =3D=3D 128 */ > + constants =3D tau; > + } > + x->input[8] =3D U8TO32_LITTLE(k + 0); > + x->input[9] =3D U8TO32_LITTLE(k + 4); > + x->input[10] =3D U8TO32_LITTLE(k + 8); > + x->input[11] =3D U8TO32_LITTLE(k + 12); > + x->input[0] =3D U8TO32_LITTLE(constants + 0); > + x->input[1] =3D U8TO32_LITTLE(constants + 4); > + x->input[2] =3D U8TO32_LITTLE(constants + 8); > + x->input[3] =3D U8TO32_LITTLE(constants + 12); > +} > + > +void > +chacha_ivsetup(chacha_ctx *x, const u8 *iv, const u8 *counter) > +{ > + x->input[12] =3D counter =3D=3D NULL ? 0 : U8TO32_LITTLE(counter + = 0); > + x->input[13] =3D counter =3D=3D NULL ? 0 : U8TO32_LITTLE(counter + = 4); > + x->input[14] =3D U8TO32_LITTLE(iv + 0); > + x->input[15] =3D 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 =3D NULL; > + u8 tmp[64]; > + u_int i; > + > + if (!bytes) return; > + > + j0 =3D x->input[0]; > + j1 =3D x->input[1]; > + j2 =3D x->input[2]; > + j3 =3D x->input[3]; > + j4 =3D x->input[4]; > + j5 =3D x->input[5]; > + j6 =3D x->input[6]; > + j7 =3D x->input[7]; > + j8 =3D x->input[8]; > + j9 =3D x->input[9]; > + j10 =3D x->input[10]; > + j11 =3D x->input[11]; > + j12 =3D x->input[12]; > + j13 =3D x->input[13]; > + j14 =3D x->input[14]; > + j15 =3D x->input[15]; > + > + for (;;) { > + if (bytes < 64) { > + for (i =3D 0;i < bytes;++i) tmp[i] =3D m[i]; > + m =3D tmp; > + ctarget =3D c; > + c =3D tmp; > + } > + x0 =3D j0; > + x1 =3D j1; > + x2 =3D j2; > + x3 =3D j3; > + x4 =3D j4; > + x5 =3D j5; > + x6 =3D j6; > + x7 =3D j7; > + x8 =3D j8; > + x9 =3D j9; > + x10 =3D j10; > + x11 =3D j11; > + x12 =3D j12; > + x13 =3D j13; > + x14 =3D j14; > + x15 =3D j15; > + for (i =3D 20;i > 0;i -=3D 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 =3D PLUS(x0,j0); > + x1 =3D PLUS(x1,j1); > + x2 =3D PLUS(x2,j2); > + x3 =3D PLUS(x3,j3); > + x4 =3D PLUS(x4,j4); > + x5 =3D PLUS(x5,j5); > + x6 =3D PLUS(x6,j6); > + x7 =3D PLUS(x7,j7); > + x8 =3D PLUS(x8,j8); > + x9 =3D PLUS(x9,j9); > + x10 =3D PLUS(x10,j10); > + x11 =3D PLUS(x11,j11); > + x12 =3D PLUS(x12,j12); > + x13 =3D PLUS(x13,j13); > + x14 =3D PLUS(x14,j14); > + x15 =3D PLUS(x15,j15); > + > + x0 =3D XOR(x0,U8TO32_LITTLE(m + 0)); > + x1 =3D XOR(x1,U8TO32_LITTLE(m + 4)); > + x2 =3D XOR(x2,U8TO32_LITTLE(m + 8)); > + x3 =3D XOR(x3,U8TO32_LITTLE(m + 12)); > + x4 =3D XOR(x4,U8TO32_LITTLE(m + 16)); > + x5 =3D XOR(x5,U8TO32_LITTLE(m + 20)); > + x6 =3D XOR(x6,U8TO32_LITTLE(m + 24)); > + x7 =3D XOR(x7,U8TO32_LITTLE(m + 28)); > + x8 =3D XOR(x8,U8TO32_LITTLE(m + 32)); > + x9 =3D XOR(x9,U8TO32_LITTLE(m + 36)); > + x10 =3D XOR(x10,U8TO32_LITTLE(m + 40)); > + x11 =3D XOR(x11,U8TO32_LITTLE(m + 44)); > + x12 =3D XOR(x12,U8TO32_LITTLE(m + 48)); > + x13 =3D XOR(x13,U8TO32_LITTLE(m + 52)); > + x14 =3D XOR(x14,U8TO32_LITTLE(m + 56)); > + x15 =3D XOR(x15,U8TO32_LITTLE(m + 60)); > + > + j12 =3D PLUSONE(j12); > + if (!j12) { > + j13 =3D 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 <=3D 64) { > + if (bytes < 64) { > + for (i =3D 0;i < bytes;++i) ctarget[i] =3D c[i]; > + } > + x->input[12] =3D j12; > + x->input[13] =3D j13; > + return; > + } > + bytes -=3D 64; > + c +=3D 64; > + m +=3D 64; > + } > +} >=20 > Added: head/sys/crypto/chacha20/chacha.h > = =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D > --- /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 > + > +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 */ > + >=20 > Modified: head/sys/dev/random/random_harvestq.c > = =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D > --- 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 =3D = preload_search_by_type(RANDOM_HARVESTQ_BOOT_ENTROPY_FILE); > + keyfile =3D = preload_search_by_type(RANDOM_CACHED_BOOT_ENTROPY_MODULE); > +#ifndef NO_BACKWARD_COMPATIBILITY > + if (keyfile =3D=3D NULL) > + keyfile =3D = preload_search_by_type(RANDOM_LEGACY_BOOT_ENTROPY_MODULE); > +#endif > if (keyfile !=3D NULL) { > data =3D preload_fetch_addr(keyfile); > size =3D 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 +=3D RANDOM_CACHED_SKIP_START; > + size -=3D RANDOM_CACHED_SKIP_START; > + } > /* Trim the size. If the admin has a file with a funny = size, we lose some. Tough. */ > size -=3D (size % sizeof(event.he_entropy)); > if (data !=3D NULL && size !=3D 0) { >=20 > Modified: head/sys/dev/random/random_harvestq.h > = =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D > --- 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 { >=20 > void read_rate_increment(u_int); >=20 > -#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) >=20 > Modified: head/sys/libkern/arc4random.c > = =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D > --- 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. > * > - * 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 > */ >=20 > #include > @@ -14,144 +31,122 @@ __FBSDID("$FreeBSD$"); > #include > #include > #include > -#include > #include > +#include > #include > +#include > #include > -#include > +#include > #include > -#include > +#include > + > +#include >=20 > -#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 >=3D CHACHA_MINKEYLEN); >=20 > int arc4rand_iniseed_state =3D ARC4_ENTR_NONE; >=20 > -MALLOC_DEFINE(M_ARC4RANDOM, "arc4random", "arc4random structures"); > +MALLOC_DEFINE(M_CHACHA20RANDOM, "chacha20random", "chacha20random = structures"); >=20 > -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); >=20 > -static struct arc4_s *arc4inst =3D NULL; > +static struct chacha20_s *chacha20inst =3D NULL; >=20 > -#define ARC4_FOREACH(_arc4) \ > - for (_arc4 =3D &arc4inst[0]; _arc4 <=3D &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 =3D *a; > - *a =3D *b; > - *b =3D c; > -}=09 > +#define CHACHA20_FOREACH(_chacha20) \ > + for (_chacha20 =3D &chacha20inst[0]; \ > + _chacha20 <=3D &chacha20inst[mp_maxid]; \ > + _chacha20++) >=20 > /* > - * 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; >=20 > /* > - * 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 =3D 0; n < 256; n++) { > - arc4->j =3D (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 =3D = preload_search_by_type(RANDOM_CACHED_BOOT_ENTROPY_MODULE); > + if (keyfile !=3D NULL) { > + data =3D preload_fetch_addr(keyfile); > + size =3D MIN(preload_fetch_size(keyfile), = CHACHA20_KEYBYTES); > + for (n =3D 0; n < size; n++) > + key[n] ^=3D 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 =3D 1; > } > - arc4->i =3D arc4->j =3D 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 =3D tv_now.tv_sec + ARC4_RESEED_SECONDS; > - arc4->numruns =3D 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 =3D 768 in our case.) > - * > - * http://dl.acm.org/citation.cfm?id=3D646557.694759 > - */ > - for (n =3D 0; n < 768*4; n++) > - arc4_randbyte(arc4); > - > - mtx_unlock(&arc4->mtx); > + chacha20->t_reseed =3D tv_now.tv_sec + CHACHA20_RESEED_SECONDS; > + chacha20->numbytes =3D 0; > + mtx_unlock(&chacha20->mtx); > } >=20 > /* > - * 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 =3D malloc((mp_maxid + 1) * sizeof(struct arc4_s), > - M_ARC4RANDOM, M_NOWAIT | M_ZERO); > - KASSERT(arc4inst !=3D NULL, ("arc4_init: memory allocation = error")); > + struct chacha20_s *chacha20; >=20 > - ARC4_FOREACH(arc4) { > - mtx_init(&arc4->mtx, "arc4_mtx", NULL, MTX_DEF); > - > - arc4->i =3D arc4->j =3D 0; > - for (n =3D 0; n < 256; n++) > - arc4->sbox[n] =3D (u_int8_t) n; > - > - arc4->t_reseed =3D -1; > - arc4->numruns =3D 0; > + chacha20inst =3D malloc((mp_maxid + 1) * sizeof(struct = chacha20_s), > + M_CHACHA20RANDOM, M_NOWAIT | M_ZERO); > + KASSERT(chacha20inst !=3D NULL, ("chacha20_init: memory = allocation error")); > + > + CHACHA20_FOREACH(chacha20) { > + mtx_init(&chacha20->mtx, "chacha20_mtx", NULL, MTX_DEF); > + chacha20->t_reseed =3D -1; > + chacha20->numbytes =3D 0; > + chacha20->first_time_done =3D 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); >=20 >=20 > static void > -arc4_uninit(void) > +chacha20_uninit(void) > { > - struct arc4_s *arc4; > + struct chacha20_s *chacha20; >=20 > - 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); >=20 > -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 =3D (arc4->i + 1) % 256; > - arc4->j =3D (arc4->j + arc4->sbox[arc4->i]) % 256; > - > - arc4_swap(&arc4->sbox[arc4->i], &arc4->sbox[arc4->j]); > - > - arc4_t =3D (arc4->sbox[arc4->i] + arc4->sbox[arc4->j]) % 256; > - return arc4->sbox[arc4_t]; > -} >=20 > /* > * 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; >=20 > - 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); >=20 > - arc4 =3D &arc4inst[curcpu]; > + chacha20 =3D &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); >=20 > - mtx_lock(&arc4->mtx); > - arc4->numruns +=3D len; > + mtx_lock(&chacha20->mtx); > p =3D ptr; > - while (len--) > - *p++ =3D arc4_randbyte(arc4); > - mtx_unlock(&arc4->mtx); > + while (len) { > + length =3D MIN(CHACHA20_BUFFER_SIZE, len); > + chacha_encrypt_bytes(&chacha20->ctx, chacha20->m_buffer, = p, length); > + p +=3D length; > + len -=3D length; > + chacha20->numbytes +=3D length; > + if (chacha20->numbytes > CHACHA20_RESEED_BYTES) { > + mtx_unlock(&chacha20->mtx); > + chacha20_randomstir(chacha20); > + mtx_lock(&chacha20->mtx); > + } > + } > + mtx_unlock(&chacha20->mtx); > } >=20 > uint32_t > @@ -188,6 +191,13 @@ arc4random(void) > { > uint32_t ret; >=20 > - arc4rand(&ret, sizeof ret, 0); > + arc4rand(&ret, sizeof(ret), 0); > return ret; > } > + > +void > +arc4random_buf(void *ptr, size_t len) > +{ > + > + arc4rand(ptr, len, 0); > +} >=20 > Modified: head/sys/sys/libkern.h > = =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D > --- 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, >=20 > Modified: head/sys/sys/random.h > = =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D > --- 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 { >=20 > #define RANDOM_HARVEST_EVERYTHING_MASK ((1 << = (RANDOM_ENVIRONMENTAL_END + 1)) - 1) >=20 > +#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); >=20 --=20 Mark R V Murray