Page Menu
Home
FreeBSD
Search
Configure Global Search
Log In
Files
F161606811
D10048.id26394.diff
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Flag For Later
Award Token
Size
15 KB
Referenced Files
None
Subscribers
None
D10048.id26394.diff
View Options
Index: sys/conf/files
===================================================================
--- sys/conf/files
+++ sys/conf/files
@@ -3805,6 +3805,7 @@
# 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
Index: sys/crypto/chacha20/chacha.h
===================================================================
--- /dev/null
+++ sys/crypto/chacha20/chacha.h
@@ -0,0 +1,35 @@
+/* $OpenBSD: chacha.h,v 1.4 2016/08/27 04:04:56 guenther Exp $ */
+
+/*
+chacha-merged.c version 20080118
+D. J. Bernstein
+Public domain.
+*/
+
+#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)
+ __attribute__((__bounded__(__minbytes__, 2, CHACHA_MINKEYLEN)));
+void chacha_ivsetup(struct chacha_ctx *x, const u_char *iv, const u_char *ctr)
+ __attribute__((__bounded__(__minbytes__, 2, CHACHA_NONCELEN)))
+ __attribute__((__bounded__(__minbytes__, 3, CHACHA_CTRLEN)));
+void chacha_encrypt_bytes(struct chacha_ctx *x, const u_char *m,
+ u_char *c, u_int bytes)
+ __attribute__((__bounded__(__buffer__, 2, 4)))
+ __attribute__((__bounded__(__buffer__, 3, 4)));
+
+#endif /* CHACHA_H */
+
Index: sys/crypto/chacha20/chacha.c
===================================================================
--- /dev/null
+++ sys/crypto/chacha20/chacha.c
@@ -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;
+ }
+}
Index: sys/libkern/arc4random.c
===================================================================
--- sys/libkern/arc4random.c
+++ sys/libkern/arc4random.c
@@ -1,11 +1,28 @@
/*-
- * THE BEER-WARE LICENSE
+ * Copyright (c) 2017 Mark R V Murray
+ * 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>
@@ -22,165 +39,135 @@
#include <sys/smp.h>
#include <sys/malloc.h>
-#define ARC4_RESEED_BYTES 65536
-#define ARC4_RESEED_SECONDS 300
-#define ARC4_KEYBYTES 256
+#include <crypto/chacha20/chacha.h>
+
+#define CHACHA20_RESEED_BYTES 65536
+#define CHACHA20_RESEED_SECONDS 300
+#define CHACHA20_KEYBYTES 32
+#define CHACHA20_BUFFER_SIZE 64
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];
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;
-
-#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;
+static struct chacha20_s *chacha20inst = NULL;
- 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];
+ u_int8_t key[CHACHA20_KEYBYTES];
+ u_int8_t c_buffer[CHACHA20_BUFFER_SIZE];
int n;
struct timeval tv_now;
/*
* XXX: FIX!! This isn't brilliant. Need more confidence.
* This returns zero entropy before random(4) is seeded.
+ * But how? At early boot, there is no entropy, but demand
+ * for it? Where else can we grab some cheap garbage?
*/
- (void)read_random(key, ARC4_KEYBYTES);
+ (void)read_random(key, CHACHA20_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]);
- }
- arc4->i = arc4->j = 0;
+ 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->numruns = 0;
+ /* Burn the first 4k of output just because. */
+ for (n = 0; n < (1024*4)/CHACHA20_BUFFER_SIZE; n++)
+ chacha_encrypt_bytes(&chacha20->ctx, chacha20->m_buffer,
+ c_buffer, CHACHA20_BUFFER_SIZE);
+ memset(c_buffer, 0, CHACHA20_BUFFER_SIZE);
+ 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"));
-
- 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;
+ struct chacha20_s *chacha20;
+
+ 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->numruns = 0;
+ memset(chacha20->m_buffer, 0, CHACHA20_BUFFER_SIZE);
+ memset(&chacha20->ctx, 0, 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;
-
- ARC4_FOREACH(arc4) {
- mtx_destroy(&arc4->mtx);
- }
+ struct chacha20_s *chacha20;
- free(arc4inst, M_ARC4RANDOM);
+ CHACHA20_FOREACH(chacha20)
+ mtx_destroy(&chacha20->mtx);
+ free(chacha20inst, M_CHACHA20RANDOM);
}
-SYSUNINIT(arc4, SI_SUB_LOCK, SI_ORDER_ANY, arc4_uninit, NULL);
+SYSUNINIT(chacha20, SI_SUB_LOCK, SI_ORDER_ANY, chacha20_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
*/
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);
+ 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);
+ if ((chacha20->numruns > CHACHA20_RESEED_BYTES) ||
+ (tv.tv_sec > chacha20->t_reseed))
+ chacha20_randomstir(chacha20);
- mtx_lock(&arc4->mtx);
- arc4->numruns += len;
+ mtx_lock(&chacha20->mtx);
+ chacha20->numruns += len;
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;
+ }
+ mtx_unlock(&chacha20->mtx);
}
uint32_t
@@ -188,6 +175,6 @@
{
uint32_t ret;
- arc4rand(&ret, sizeof ret, 0);
+ arc4rand(&ret, sizeof(ret), 0);
return ret;
}
File Metadata
Details
Attached
Mime Type
text/plain
Expires
Mon, Jul 6, 7:02 AM (10 h, 7 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
34742234
Default Alt Text
D10048.id26394.diff (15 KB)
Attached To
Mode
D10048: Replace the kernel RC4 with Chacha20.
Attached
Detach File
Event Timeline
Log In to Comment