/* Portable arc4random.c based on arc4random.c from OpenBSD. *PortableversionbyChrisDavis,adaptedforLibeventbyNickMathewson *Copyright(c)2010ChrisDavis,NielsProvos,andNickMathewson *Copyright(c)2010-2012NielsProvosandNickMathewson * *NotethatinLibevent,thisfileisn'tcompileddirectly.Instead, *it'sincludedfromevutil_rand.c
*/
while (numread < count) {
result = read(fd, buf+numread, count-numread);
if (result<0) return -1; else if (result == 0) break;
numread += result;
}
return (ssize_t)numread;
} #endif
#ifdef _WIN32 #define TRY_SEED_WIN32 static int
arc4_seed_win32(void)
{ /* This is adapted from Tor's crypto_seed_rng() */ static int provider_set = 0; static HCRYPTPROV provider; unsigned char buf[ADD_ENTROPY];
if (!provider_set) {
if (!CryptAcquireContext(&provider, NULL, NULL, PROV_RSA_FULL,
CRYPT_VERIFYCONTEXT)) {
if (GetLastError() != (DWORD)NTE_BAD_KEYSET) return -1;
}
provider_set = 1;
}
if (!CryptGenRandom(provider, sizeof(buf), buf)) return -1;
arc4_addrandom(buf, sizeof(buf));
evutil_memclear_(buf, sizeof(buf)); return0;
} #endif
#ifdefined(EVENT__HAVE_GETRANDOM) #define TRY_SEED_GETRANDOM static int
arc4_seed_getrandom(void)
{ unsigned char buf[ADD_ENTROPY];
size_t len, n; unsigned i;
int any_set;
memset(buf, 0, sizeof(buf));
for (len = 0; len < sizeof(buf); len += n) {
n = sizeof(buf) - len;
if (0 == getrandom(&buf[len], n, 0)) return -1;
} /* make sure that the buffer actually got set. */
for (i=0,any_set=0; i<sizeof(buf); ++i) {
any_set |= buf[i];
}
if (!any_set) return -1;
#ifdefined(EVENT__HAVE_SYS_SYSCTL_H) && defined(EVENT__HAVE_SYSCTL) #if EVENT__HAVE_DECL_CTL_KERN && EVENT__HAVE_DECL_KERN_ARND #define TRY_SEED_SYSCTL_BSD static int
arc4_seed_sysctl_bsd(void)
{ /* Based on code from William Ahern and from OpenBSD, this function *triestousetheKERN_ARNDsyscalltogetentropyfromthekernel. *Thiscanworkevenif/dev/urandomisinaccessibleforsomereason
* (e.g., we're running in a chroot). */
int mib[] = { CTL_KERN, KERN_ARND }; unsigned char buf[ADD_ENTROPY];
size_t len, n;
int i, any_set;
memset(buf, 0, sizeof(buf));
len = sizeof(buf);
if (sysctl(mib, 2, buf, &len, NULL, 0) == -1) {
for (len = 0; len < sizeof(buf); len += sizeof(unsigned)) {
n = sizeof(unsigned);
if (n + len > sizeof(buf))
n = len - sizeof(buf);
if (sysctl(mib, 2, &buf[len], &n, NULL, 0) == -1) return -1;
}
} /* make sure that the buffer actually got set. */
for (i=any_set=0; i<sizeof(buf); ++i) {
any_set |= buf[i];
}
if (!any_set) return -1;
static int arc4_seed_urandom_helper_(const char *fname)
{ unsigned char buf[ADD_ENTROPY];
int fd;
size_t n;
fd = evutil_open_closeonexec_(fname, O_RDONLY, 0);
if (fd<0) return -1;
n = read_all(fd, buf, sizeof(buf));
close(fd);
if (n != sizeof(buf)) return -1;
arc4_addrandom(buf, sizeof(buf));
evutil_memclear_(buf, sizeof(buf)); return0;
}
static int
arc4_seed_urandom(void)
{ /* This is adapted from Tor's crypto_seed_rng() */ staticconst char *filenames[] = { "/dev/srandom", "/dev/urandom", "/dev/random", NULL
};
int i;
if (arc4random_urandom_filename) return arc4_seed_urandom_helper_(arc4random_urandom_filename);
for (i = 0; filenames[i]; ++i) {
if (arc4_seed_urandom_helper_(filenames[i]) == 0) { return0;
}
}
return -1;
} #endif
static int
arc4_seed(void)
{
int ok = 0; /* We try every method that might work, and don't give up even if one *doesseemtowork.There'snorealharminover-seeding,andif
* one of these sources turns out to be broken, that would be bad. */ #ifdef TRY_SEED_WIN32
if (0 == arc4_seed_win32())
ok = 1; #endif #ifdef TRY_SEED_GETRANDOM
if (0 == arc4_seed_getrandom())
ok = 1; #endif #ifdef TRY_SEED_URANDOM
if (0 == arc4_seed_urandom())
ok = 1; #endif #ifdef TRY_SEED_PROC_SYS_KERNEL_RANDOM_UUID
if (arc4random_urandom_filename == NULL && 0 == arc4_seed_proc_sys_kernel_random_uuid())
ok = 1; #endif #ifdef TRY_SEED_SYSCTL_BSD
if (0 == arc4_seed_sysctl_bsd())
ok = 1; #endif return ok ? 0 : -1;
}
static int
arc4_stir(void)
{
int i;
if (!rs_initialized) {
arc4_init();
rs_initialized = 1;
}
if (0 != arc4_seed()) return -1;
/* *Discardearlykeystream,asperrecommendationsin *"WeaknessesintheKeySchedulingAlgorithmofRC4"by *ScottFluhrer,ItsikMantin,andAdiShamir. *http://www.wisdom.weizmann.ac.il/~itsik/RC4/Papers/Rc4_ksa.ps * *IlyaMironov's"(NotSo)RandomShufflesofRC4"suggeststhat *wedropatleast2*256bytes,with12*256asaconservative *value. * *RFC4345saystodrop6*256. * *Atleastsomeversionsofthiscodedrop4*256,inamistaken *beliefthat"words"intheFluhrer/Mantin/Shamirpaperrefers *toprocessorwords. * *Weaddanothersecttothecargocult,andchoose12*256.
*/
for (i = 0; i < 12*256; i++)
(void)arc4_getbyte();
static inline unsigned int
arc4_getword(void)
{ unsigned int val;
val = arc4_getbyte() << 24;
val |= arc4_getbyte() << 16;
val |= arc4_getbyte() << 8;
val |= arc4_getbyte();
return val;
}
#ifndef ARC4RANDOM_NOSTIR
ARC4RANDOM_EXPORT int
arc4random_stir(void)
{
int val;
ARC4_LOCK_();
val = arc4_stir();
ARC4_UNLOCK_(); return val;
} #endif
#ifndef ARC4RANDOM_NOADDRANDOM
ARC4RANDOM_EXPORT void
arc4random_addrandom(constunsigned char *dat, int datlen)
{
int j;
ARC4_LOCK_();
if (!rs_initialized)
arc4_stir();
for (j = 0; j < datlen; j += 256) { /* arc4_addrandom() ignores all but the first 256 bytes of *itsinput.WewanttomakesuretolookatALLthe *datain'dat',justincasetheuserisdoingsomething
* crazy like passing us all the files in /var/log. */
arc4_addrandom(dat + j, datlen - j);
}
ARC4_UNLOCK_();
} #endif
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.