- (djm) [openbsd-compat/Makefile.in openbsd-compat/arc4random.c]

[openbsd-compat/bsd-arc4random.c] Replace old RC4-based arc4random
   implementation with recent OpenBSD's ChaCha-based PRNG. ok dtucker@,
   tested tim@
This commit is contained in:
Damien Miller 2013-10-09 10:44:47 +11:00
parent 9159310087
commit 720711960b
4 changed files with 52 additions and 165 deletions

View File

@ -2,6 +2,10 @@
- (djm) [openbsd-compat/arc4random.c openbsd-compat/chacha_private.h] Pull
in OpenBSD implementation of arc4random, shortly to replace the existing
bsd-arc4random.c
- (djm) [openbsd-compat/Makefile.in openbsd-compat/arc4random.c]
[openbsd-compat/bsd-arc4random.c] Replace old RC4-based arc4random
implementation with recent OpenBSD's ChaCha-based PRNG. ok dtucker@,
tested tim@
20130922
- (dtucker) [platform.c platform.h sshd.c] bz#2156: restore Linux oom_adj

View File

@ -1,4 +1,4 @@
# $Id: Makefile.in,v 1.51 2013/05/10 06:28:56 dtucker Exp $
# $Id: Makefile.in,v 1.52 2013/10/08 23:44:49 djm Exp $
sysconfdir=@sysconfdir@
piddir=@piddir@
@ -18,7 +18,7 @@ LDFLAGS=-L. @LDFLAGS@
OPENBSD=base64.o basename.o bindresvport.o daemon.o dirname.o fmt_scaled.o getcwd.o getgrouplist.o getopt_long.o getrrsetbyname.o glob.o inet_aton.o inet_ntoa.o inet_ntop.o mktemp.o pwcache.o readpassphrase.o realpath.o rresvport.o setenv.o setproctitle.o sha2.o sigact.o strlcat.o strlcpy.o strmode.o strnlen.o strptime.o strsep.o strtonum.o strtoll.o strtoul.o strtoull.o timingsafe_bcmp.o vis.o
COMPAT=bsd-arc4random.o bsd-asprintf.o bsd-closefrom.o bsd-cray.o bsd-cygwin_util.o bsd-getpeereid.o getrrsetbyname-ldns.o bsd-misc.o bsd-nextstep.o bsd-openpty.o bsd-poll.o bsd-setres_id.o bsd-snprintf.o bsd-statvfs.o bsd-waitpid.o fake-rfc2553.o openssl-compat.o xmmap.o xcrypt.o
COMPAT=arc4random.o bsd-asprintf.o bsd-closefrom.o bsd-cray.o bsd-cygwin_util.o bsd-getpeereid.o getrrsetbyname-ldns.o bsd-misc.o bsd-nextstep.o bsd-openpty.o bsd-poll.o bsd-setres_id.o bsd-snprintf.o bsd-statvfs.o bsd-waitpid.o fake-rfc2553.o openssl-compat.o xmmap.o xcrypt.o
PORTS=port-aix.o port-irix.o port-linux.o port-solaris.o port-tun.o port-uw.o

View File

@ -1,3 +1,5 @@
/* OPENBSD ORIGINAL: lib/libc/crypto/arc4random.c */
/* $OpenBSD: arc4random.c,v 1.25 2013/10/01 18:34:57 markus Exp $ */
/*
@ -22,16 +24,19 @@
* ChaCha based random number generator for OpenBSD.
*/
#include <fcntl.h>
#include <limits.h>
#include "includes.h"
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/param.h>
#include <sys/time.h>
#include <sys/sysctl.h>
#include "thread_private.h"
#ifndef HAVE_ARC4RANDOM
#include <openssl/rand.h>
#include <openssl/err.h>
#include "log.h"
#define KEYSTREAM_ONLY
#include "chacha_private.h"
@ -42,6 +47,10 @@
#define inline
#endif /* !__GNUC__ */
/* OpenSSH isn't multithreaded */
#define _ARC4_LOCK()
#define _ARC4_UNLOCK()
#define KEYSZ 32
#define IVSZ 8
#define BLOCKSZ 64
@ -67,15 +76,11 @@ _rs_init(u_char *buf, size_t n)
static void
_rs_stir(void)
{
int mib[2];
size_t len;
u_char rnd[KEYSZ + IVSZ];
mib[0] = CTL_KERN;
mib[1] = KERN_ARND;
len = sizeof(rnd);
sysctl(mib, 2, rnd, &len, NULL, 0);
if (RAND_bytes(rnd, sizeof(rnd)) <= 0)
fatal("Couldn't obtain random bytes (error %ld)",
ERR_get_error());
if (!rs_initialized) {
rs_initialized = 1;
@ -194,6 +199,11 @@ arc4random(void)
return val;
}
/*
* If we are providing arc4random, then we can provide a more efficient
* arc4random_buf().
*/
# ifndef HAVE_ARC4RANDOM_BUF
void
arc4random_buf(void *buf, size_t n)
{
@ -201,7 +211,29 @@ arc4random_buf(void *buf, size_t n)
_rs_random_buf(buf, n);
_ARC4_UNLOCK();
}
# endif /* !HAVE_ARC4RANDOM_BUF */
#endif /* !HAVE_ARC4RANDOM */
/* arc4random_buf() that uses platform arc4random() */
#if !defined(HAVE_ARC4RANDOM_BUF) && defined(HAVE_ARC4RANDOM)
void
arc4random_buf(void *_buf, size_t n)
{
size_t i;
u_int32_t r = 0;
char *buf = (char *)_buf;
for (i = 0; i < n; i++) {
if (i % 4 == 0)
r = arc4random();
buf[i] = r & 0xff;
r >>= 8;
}
i = r = 0;
}
#endif /* !defined(HAVE_ARC4RANDOM_BUF) && defined(HAVE_ARC4RANDOM) */
#ifndef HAVE_ARC4RANDOM_UNIFORM
/*
* Calculate a uniformly distributed random number less than upper_bound
* avoiding "modulo bias".
@ -237,6 +269,7 @@ arc4random_uniform(u_int32_t upper_bound)
return r % upper_bound;
}
#endif /* !HAVE_ARC4RANDOM_UNIFORM */
#if 0
/*-------- Test code for i386 --------*/

View File

@ -1,150 +0,0 @@
/*
* Copyright (c) 1999,2000,2004 Damien Miller <djm@mindrot.org>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
#include "includes.h"
#include <sys/types.h>
#include <string.h>
#include <stdlib.h>
#include <stdarg.h>
#include "log.h"
#ifndef HAVE_ARC4RANDOM
#include <openssl/rand.h>
#include <openssl/rc4.h>
#include <openssl/err.h>
/* Size of key to use */
#define SEED_SIZE 20
/* Number of bytes to reseed after */
#define REKEY_BYTES (1 << 24)
static int rc4_ready = 0;
static RC4_KEY rc4;
unsigned int
arc4random(void)
{
unsigned int r = 0;
static int first_time = 1;
if (rc4_ready <= 0) {
if (first_time)
seed_rng();
first_time = 0;
arc4random_stir();
}
RC4(&rc4, sizeof(r), (unsigned char *)&r, (unsigned char *)&r);
rc4_ready -= sizeof(r);
return(r);
}
void
arc4random_stir(void)
{
unsigned char rand_buf[SEED_SIZE];
int i;
memset(&rc4, 0, sizeof(rc4));
if (RAND_bytes(rand_buf, sizeof(rand_buf)) <= 0)
fatal("Couldn't obtain random bytes (error %ld)",
ERR_get_error());
RC4_set_key(&rc4, sizeof(rand_buf), rand_buf);
/*
* Discard early keystream, as per recommendations in:
* http://www.wisdom.weizmann.ac.il/~itsik/RC4/Papers/Rc4_ksa.ps
*/
for(i = 0; i <= 256; i += sizeof(rand_buf))
RC4(&rc4, sizeof(rand_buf), rand_buf, rand_buf);
memset(rand_buf, 0, sizeof(rand_buf));
rc4_ready = REKEY_BYTES;
}
#endif /* !HAVE_ARC4RANDOM */
#ifndef HAVE_ARC4RANDOM_BUF
void
arc4random_buf(void *_buf, size_t n)
{
size_t i;
u_int32_t r = 0;
char *buf = (char *)_buf;
for (i = 0; i < n; i++) {
if (i % 4 == 0)
r = arc4random();
buf[i] = r & 0xff;
r >>= 8;
}
i = r = 0;
}
#endif /* !HAVE_ARC4RANDOM_BUF */
#ifndef HAVE_ARC4RANDOM_UNIFORM
/*
* Calculate a uniformly distributed random number less than upper_bound
* avoiding "modulo bias".
*
* Uniformity is achieved by generating new random numbers until the one
* returned is outside the range [0, 2**32 % upper_bound). This
* guarantees the selected random number will be inside
* [2**32 % upper_bound, 2**32) which maps back to [0, upper_bound)
* after reduction modulo upper_bound.
*/
u_int32_t
arc4random_uniform(u_int32_t upper_bound)
{
u_int32_t r, min;
if (upper_bound < 2)
return 0;
#if (ULONG_MAX > 0xffffffffUL)
min = 0x100000000UL % upper_bound;
#else
/* Calculate (2**32 % upper_bound) avoiding 64-bit math */
if (upper_bound > 0x80000000)
min = 1 + ~upper_bound; /* 2**32 - upper_bound */
else {
/* (2**32 - (x * 2)) % x == 2**32 % x when x <= 2**31 */
min = ((0xffffffff - (upper_bound * 2)) + 1) % upper_bound;
}
#endif
/*
* This could theoretically loop forever but each retry has
* p > 0.5 (worst case, usually far better) of selecting a
* number inside the range we need, so it should rarely need
* to re-roll.
*/
for (;;) {
r = arc4random();
if (r >= min)
break;
}
return r % upper_bound;
}
#endif /* !HAVE_ARC4RANDOM_UNIFORM */