4
0
mirror of git://sourceware.org/git/newlib-cygwin.git synced 2025-02-19 07:22:14 +08:00

* Makefile.in (DLL_OFILES): Add arc4random.o.

* common.din: Export arc4random, arc4random_addrandom, arc4random_buf,
	arc4random_stir and arc4random_uniform.
	* mktemp.cc (arc4random): Remove static replacement function.
	* posix.sgml (std-bsd): Add arc4random functions.
	* include/cygwin/stdlib.h: Declare arc4random functions.
	* include/cygwin/version.h (CYGWIN_VERSION_API_MINOR): Bump.
	* libc/arc4random.cc: New file implementing arc4random functions taken
	from FreeBSD.
This commit is contained in:
Corinna Vinschen 2013-05-21 19:04:49 +00:00
parent 3e8d2576fd
commit 291d93b58b
8 changed files with 388 additions and 19 deletions

View File

@ -156,8 +156,8 @@ DLL_IMPORTS:=${shell $(CC) -print-file-name=w32api/libkernel32.a} ${shell $(CC)
MT_SAFE_OBJECTS:= MT_SAFE_OBJECTS:=
# #
DLL_OFILES:=advapi32.o assert.o autoload.o base64.o bsdlib.o ctype.o cxx.o \ DLL_OFILES:=advapi32.o arc4random.o assert.o autoload.o base64.o bsdlib.o ctype.o \
cygheap.o cygthread.o cygtls.o cygwait.o cygxdr.o dcrt0.o debug.o \ cxx.o cygheap.o cygthread.o cygtls.o cygwait.o cygxdr.o dcrt0.o debug.o \
devices.o dir.o dlfcn.o dll_init.o dtable.o environ.o errno.o exceptions.o \ devices.o dir.o dlfcn.o dll_init.o dtable.o environ.o errno.o exceptions.o \
exec.o external.o fcntl.o fenv.o fhandler.o fhandler_clipboard.o \ exec.o external.o fcntl.o fenv.o fhandler.o fhandler_clipboard.o \
fhandler_console.o fhandler_dev.o fhandler_disk_file.o fhandler_dsp.o \ fhandler_console.o fhandler_dev.o fhandler_disk_file.o fhandler_dsp.o \

View File

@ -118,6 +118,11 @@ acosh NOSIGFE
acoshf NOSIGFE acoshf NOSIGFE
alarm SIGFE alarm SIGFE
alphasort NOSIGFE alphasort NOSIGFE
arc4random NOSIGFE
arc4random_addrandom NOSIGFE
arc4random_buf NOSIGFE
arc4random_stir NOSIGFE
arc4random_uniform NOSIGFE
argz_add SIGFE argz_add SIGFE
argz_add_sep SIGFE argz_add_sep SIGFE
argz_append SIGFE argz_append SIGFE

View File

@ -1,6 +1,6 @@
/* stdlib.h /* stdlib.h
Copyright 2005, 2006, 2007, 2008, 2009, 2011 Red Hat Inc. Copyright 2005, 2006, 2007, 2008, 2009, 2011, 2013 Red Hat Inc.
This file is part of Cygwin. This file is part of Cygwin.
@ -18,6 +18,12 @@ extern "C"
{ {
#endif #endif
__uint32_t arc4random(void);
void arc4random_addrandom(unsigned char *, int);
void arc4random_buf(void *, size_t);
void arc4random_stir(void);
__uint32_t arc4random_uniform(__uint32_t);
const char *getprogname (void); const char *getprogname (void);
void setprogname (const char *); void setprogname (const char *);

View File

@ -434,12 +434,14 @@ details. */
263: Export cfsetspeed. 263: Export cfsetspeed.
264: Consistently export strtold 264: Consistently export strtold
265: Export __b64_ntop, __b64_pton. 265: Export __b64_ntop, __b64_pton.
266: Export arc4random, arc4random_addrandom, arc4random_buf,
arc4random_stir, arc4random_uniform.
*/ */
/* Note that we forgot to bump the api for ualarm, strtoll, strtoull */ /* Note that we forgot to bump the api for ualarm, strtoll, strtoull */
#define CYGWIN_VERSION_API_MAJOR 0 #define CYGWIN_VERSION_API_MAJOR 0
#define CYGWIN_VERSION_API_MINOR 265 #define CYGWIN_VERSION_API_MINOR 266
/* There is also a compatibity version number associated with the /* There is also a compatibity version number associated with the
shared memory regions. It is incremented when incompatible shared memory regions. It is incremented when incompatible

View File

@ -0,0 +1,363 @@
/* $OpenBSD: arc4random.c,v 1.22 2010/12/22 08:23:42 otto Exp $ */
/*
* Copyright (c) 1996, David Mazieres <dm@uun.org>
* Copyright (c) 2008, Damien Miller <djm@openbsd.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.
*/
/*
* Arc4 random number generator for OpenBSD.
*
* This code is derived from section 17.1 of Applied Cryptography,
* second edition, which describes a stream cipher allegedly
* compatible with RSA Labs "RC4" cipher (the actual description of
* which is a trade secret). The same algorithm is used as a stream
* cipher called "arcfour" in Tatu Ylonen's ssh package.
*
* RC4 is a registered trademark of RSA Laboratories.
*/
#include <sys/cdefs.h>
__FBSDID("$FreeBSD: src/lib/libc/gen/arc4random.c,v 1.30 2012/11/17 01:49:23 svnexp Exp $");
#ifdef __CYGWIN__
#include "winsup.h"
#include "sync.h"
#else
#include "namespace.h"
#endif
#include <fcntl.h>
#include <limits.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/param.h>
#ifndef __CYGWIN__
#include <sys/sysctl.h>
#endif
#include <sys/time.h>
#include <pthread.h>
#ifndef __CYGWIN__
#include "libc_private.h"
#include "un-namespace.h"
#endif
#ifdef __CYGWIN__
#define _open open
#define _read read
#define _close close
#endif
#ifdef __GNUC__
#define inline __inline
#else /* !__GNUC__ */
#define inline
#endif /* !__GNUC__ */
struct arc4_stream {
u_int8_t i;
u_int8_t j;
u_int8_t s[256];
};
#ifdef __CYGWIN__
static NO_COPY muto arc4random_mtx;
#else
static pthread_mutex_t arc4random_mtx = PTHREAD_MUTEX_INITIALIZER;
#endif
#define RANDOMDEV "/dev/random"
#define KEYSIZE 128
#ifdef __CYGWIN__
#define _ARC4_LOCK() \
do { \
if (__isthreaded) \
arc4random_mtx.init ("arc4random_mtx")->acquire (); \
} while (0)
#define _ARC4_UNLOCK() \
do { \
if (__isthreaded) \
arc4random_mtx.release (); \
} while (0)
#else
#define _ARC4_LOCK() \
do { \
if (__isthreaded) \
_pthread_mutex_lock(&arc4random_mtx); \
} while (0)
#define _ARC4_UNLOCK() \
do { \
if (__isthreaded) \
_pthread_mutex_unlock(&arc4random_mtx); \
} while (0)
#endif
static int rs_initialized;
static struct arc4_stream rs;
static pid_t arc4_stir_pid;
static int arc4_count;
#ifndef __CYGWIN__
extern int __sysctl(int *name, u_int namelen, void *oldp, size_t *oldlenp,
void *newp, size_t newlen);
#endif
static inline u_int8_t arc4_getbyte(void);
static void arc4_stir(void);
static inline void
arc4_init(void)
{
int n;
for (n = 0; n < 256; n++)
rs.s[n] = n;
rs.i = 0;
rs.j = 0;
}
static inline void
arc4_addrandom(u_char *dat, int datlen)
{
int n;
u_int8_t si;
rs.i--;
for (n = 0; n < 256; n++) {
rs.i = (rs.i + 1);
si = rs.s[rs.i];
rs.j = (rs.j + si + dat[n % datlen]);
rs.s[rs.i] = rs.s[rs.j];
rs.s[rs.j] = si;
}
rs.j = rs.i;
}
#ifndef __CYGWIN__
static size_t
arc4_sysctl(u_char *buf, size_t size)
{
int mib[2];
size_t len, done;
mib[0] = CTL_KERN;
mib[1] = KERN_ARND;
done = 0;
do {
len = size;
if (__sysctl(mib, 2, buf, &len, NULL, 0) == -1)
return (done);
done += len;
buf += len;
size -= len;
} while (size > 0);
return (done);
}
#endif
static void
arc4_stir(void)
{
int done, fd, i;
struct {
struct timeval tv;
pid_t pid;
u_char rnd[KEYSIZE];
} rdat;
if (!rs_initialized) {
arc4_init();
rs_initialized = 1;
}
done = 0;
#ifndef __CYGWIN__
if (arc4_sysctl((u_char *)&rdat, KEYSIZE) == KEYSIZE)
done = 1;
#endif
if (!done) {
fd = _open(RANDOMDEV, O_RDONLY | O_CLOEXEC, 0);
if (fd >= 0) {
if (_read(fd, &rdat, KEYSIZE) == KEYSIZE)
done = 1;
(void)_close(fd);
}
}
if (!done) {
(void)gettimeofday(&rdat.tv, NULL);
rdat.pid = getpid();
/* We'll just take whatever was on the stack too... */
}
arc4_addrandom((u_char *)&rdat, KEYSIZE);
/*
* Discard early keystream, as per recommendations in:
* "(Not So) Random Shuffles of RC4" by Ilya Mironov.
*/
for (i = 0; i < 1024; i++)
(void)arc4_getbyte();
arc4_count = 1600000;
}
static void
arc4_stir_if_needed(void)
{
pid_t pid = getpid();
if (arc4_count <= 0 || !rs_initialized || arc4_stir_pid != pid)
{
arc4_stir_pid = pid;
arc4_stir();
}
}
static inline u_int8_t
arc4_getbyte(void)
{
u_int8_t si, sj;
rs.i = (rs.i + 1);
si = rs.s[rs.i];
rs.j = (rs.j + si);
sj = rs.s[rs.j];
rs.s[rs.i] = sj;
rs.s[rs.j] = si;
return (rs.s[(si + sj) & 0xff]);
}
static inline u_int32_t
arc4_getword(void)
{
u_int32_t val;
val = arc4_getbyte() << 24;
val |= arc4_getbyte() << 16;
val |= arc4_getbyte() << 8;
val |= arc4_getbyte();
return val;
}
void
arc4random_stir(void)
{
_ARC4_LOCK();
arc4_stir();
_ARC4_UNLOCK();
}
void
arc4random_addrandom(u_char *dat, int datlen)
{
_ARC4_LOCK();
if (!rs_initialized)
arc4_stir();
arc4_addrandom(dat, datlen);
_ARC4_UNLOCK();
}
u_int32_t
arc4random(void)
{
u_int32_t val;
_ARC4_LOCK();
arc4_count -= 4;
arc4_stir_if_needed();
val = arc4_getword();
_ARC4_UNLOCK();
return val;
}
void
arc4random_buf(void *_buf, size_t n)
{
u_char *buf = (u_char *)_buf;
_ARC4_LOCK();
arc4_stir_if_needed();
while (n--) {
if (--arc4_count <= 0)
arc4_stir();
buf[n] = arc4_getbyte();
}
_ARC4_UNLOCK();
}
/*
* 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;
}
#if 0
/*-------- Test code for i386 --------*/
#include <stdio.h>
#include <machine/pctr.h>
int
main(int argc, char **argv)
{
const int iter = 1000000;
int i;
pctrval v;
v = rdtsc();
for (i = 0; i < iter; i++)
arc4random();
v = rdtsc() - v;
v /= iter;
printf("%qd cycles\n", v);
}
#endif

View File

@ -11,7 +11,6 @@ See the copyright at the bottom of this file. */
#include <unistd.h> #include <unistd.h>
static int _gettemp(char *, int *, int, size_t, int); static int _gettemp(char *, int *, int, size_t, int);
static uint32_t arc4random ();
static const char padchar[] = static const char padchar[] =
"0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"; "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
@ -153,20 +152,6 @@ _gettemp(char *path, int *doopen, int domkdir, size_t suffixlen, int flags)
/*NOTREACHED*/ /*NOTREACHED*/
} }
static uint32_t
arc4random ()
{
union
{
uint32_t rand;
char buf[sizeof (int) / 8];
} r;
int fd = open ("/dev/urandom", O_RDONLY);
read (fd, r.buf, 4);
close (fd);
return r.rand;
}
/* /*
* Copyright (c) 1987, 1993 * Copyright (c) 1987, 1993
* The Regents of the University of California. All rights reserved. * The Regents of the University of California. All rights reserved.

View File

@ -956,6 +956,11 @@ also IEEE Std 1003.1-2008 (POSIX.1-2008).</para>
<screen> <screen>
__b64_ntop __b64_ntop
__b64_pton __b64_pton
arc4random
arc4random_addrandom
arc4random_buf
arc4random_stir
arc4random_uniform
bindresvport bindresvport
bindresvport_sa bindresvport_sa
cfmakeraw cfmakeraw

View File

@ -9,6 +9,9 @@ What's new:
- Add support for the AFS filesystem. - Add support for the AFS filesystem.
- New APIs: __b64_ntop, __b64_pton, arc4random, arc4random_addrandom,
arc4random_buf, arc4random_stir, arc4random_uniform.
Bug fixes: Bug fixes:
---------- ----------