BSD-arc4random-1.50004075500000000000000000000000001157300776000127115ustar00rootwheelBSD-arc4random-1.50/lib004075500000000000000000000000001157300774100134565ustar00rootwheelBSD-arc4random-1.50/lib/BSD004075500000000000000000000000001157300774100140665ustar00rootwheelBSD-arc4random-1.50/lib/BSD/arc4random.pm010064400000000000000000000216251157300740000165300ustar00rootwheel# $MirOS: contrib/hosted/tg/code/BSD::arc4random/lib/BSD/arc4random.pm,v 1.10 2011/06/05 23:19:04 tg Exp $ #- # Copyright (c) 2008, 2009, 2010, 2011 # Thorsten Glaser # Copyright (c) 2009 # Benny Siegert # # Provided that these terms and disclaimer and all copyright notices # are retained or reproduced in an accompanying document, permission # is granted to deal in this work without restriction, including un- # limited rights to use, publicly perform, distribute, sell, modify, # merge, give away, or sublicence. # # This work is provided "AS IS" and WITHOUT WARRANTY of any kind, to # the utmost extent permitted by applicable law, neither express nor # implied; without malicious intent or gross negligence. In no event # may a licensor, author or contributor be held liable for indirect, # direct, other damage, loss, or other issues arising in any way out # of dealing in the work, even if advised of the possibility of such # damage or existence of a defect, except proven that it results out # of said person's immediate fault when using the work as intended. package BSD::arc4random; use strict; use warnings; BEGIN { require Exporter; require DynaLoader; use vars qw($VERSION @ISA @EXPORT @EXPORT_OK %EXPORT_TAGS); $VERSION = "1.50"; @ISA = qw(Exporter DynaLoader); @EXPORT = qw(); @EXPORT_OK = qw( $RANDOM &arc4random &arc4random_addrandom &arc4random_bytes &arc4random_pushb &arc4random_pushk &arc4random_stir &arc4random_uniform ); %EXPORT_TAGS = ( all => [ @EXPORT_OK ], ); } use vars qw($RANDOM); # public tied integer variable sub have_kintf() {} # public constant function, prototyped my $have_threadlock = 1; my $arcfour_lock; eval { require threads::shared; }; if ($@) { $have_threadlock = 0; # module not available } else { # private thread lock threads::shared::share($arcfour_lock); }; bootstrap BSD::arc4random $BSD::arc4random::VERSION; # public thread-safe functions sub arc4random() { lock($arcfour_lock) if $have_threadlock; return &arc4random_xs(); } sub arc4random_addrandom($) { my $buf = shift; lock($arcfour_lock) if $have_threadlock; return &arc4random_addrandom_xs($buf); } sub arc4random_pushb($) { my $buf = shift; lock($arcfour_lock) if $have_threadlock; return &arc4random_pushb_xs($buf); } sub arc4random_pushk($) { my $buf = shift; lock($arcfour_lock) if $have_threadlock; return &arc4random_pushk_xs($buf); } sub arc4random_stir() { lock($arcfour_lock) if $have_threadlock; &arc4random_stir_xs(); return; } sub arc4random_bytes($;$) { my ($len, $buf) = @_; my $val; my $vleft = 0; my $rv = ''; my $idx = 0; if (defined($buf)) { $val = arc4random_pushb($buf); $vleft = 4; } while (($len - $idx) >= 4) { if ($vleft < 4) { $val = arc4random(); $vleft = 4; } vec($rv, $idx / 4, 32) = $val; $idx += 4; $vleft = 0; } while ($idx < $len) { if ($vleft == 0) { $val = arc4random(); $vleft = 4; } vec($rv, $idx, 8) = $val & 0xFF; $idx++; $val >>= 8; $vleft--; } return $rv; } # Perl implementation of arc4random_uniform(3) # C implementation contributed by djm@openbsd.org, Jinmei_Tatuya@isc.org # # 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. sub arc4random_uniform($) { my $upper_bound = shift; my $r; my $min; return 0 unless defined($upper_bound); # convert upper_bound to 32-bit UV (unsigned integer value) $upper_bound &= 0xFFFFFFFF; return 0 if $upper_bound < 2 || $upper_bound > 0xFFFFFFFF; # Calculate (2**32 % upper_bound) avoiding 64-bit math if ($upper_bound > 0x80000000) { # 2**32 - upper_bound (only one "value area") $min = 1 + (~$upper_bound & 0xFFFFFFFF); } else { # (2**32 - x) % x == 2**32 % x when x <= 2**31 $min = (0xFFFFFFFF - $upper_bound + 1) % $upper_bound; } # 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. while (1) { $r = arc4random(); last if $r >= $min; } return ($r % $upper_bound); } # private implementation for a tied $RANDOM variable sub TIESCALAR { my $class = shift; my $max = shift; if (!defined($max) || ($max = int($max)) > 0xFFFFFFFE || $max < 0) { $max = 0; } return bless \$max, $class; } sub FETCH { my $self = shift; return ($$self == 0 ? arc4random() : arc4random_uniform($$self + 1)); } sub STORE { my $self = shift; my $value = shift; arc4random_pushb($value); } # tie the public $RANDOM variable to an mksh-style implementation tie $RANDOM, 'BSD::arc4random', 0x7FFF; # we are nice and re-seed perl's internal PRNG as well srand(arc4random_pushb(pack("F*", rand(), rand(), rand(), rand()))); 1; __END__ =head1 NAME BSD::arc4random - Perl interface to the arc4 random number generator =head1 SYNOPSIS use BSD::arc4random qw(:all); $v = arc4random(); $v = arc4random_uniform($hz); if (!BSD::arc4random::have_kintf()) { $v = arc4random_addrandom("entropy to pass to the system"); } else { $v = arc4random_pushb("entropy to pass to the system"); $v = arc4random_pushk("entropy to pass to the kernel"); } $s = arc4random_bytes(16, "entropy to pass to libc"); arc4random_stir(); $s = arc4random_bytes(16); print $RANDOM; =head1 DESCRIPTION This set of functions maps the L family of libc functions into Perl code. All functions listed below are ithreads-safe. The internal XS functions are not, but you are not supposed to call them, either. On module load, perl's internal PRNG is re-seeded, as a bonus, using B with an argument calculated from using B on some entropy returned from B's previous state. =head2 LOW-LEVEL FUNCTIONS =over 4 =item B() This function returns an unsigned 32-bit integer random value. =item B(I) This function adds the entropy from I into the libc pool and returns an unsigned 32-bit integer random value from it. =item B(I) This function first pushes the I argument to the kernel if possible, then the entropy returned by the kernel into the libc pool, then returns an unsigned 32-bit integer random value from it. =item B(I) This function first pushes the I argument to the kernel if possible, then returns an unsigned 32-bit integer random value from the kernel. This function is deprecated. Use B instead. =item B() This procedure attempts to retrieve new entropy from the kernel and add it to the libc pool. Usually, this means you must have access to the L device; create it inside L jails first if you use them. =item B() This constant function returns 1 if B and/or B actually call the kernel interfaces, 0 if they merely map to B instead. =back =head2 HIGH-LEVEL FUNCTIONS =over 4 =item B(I[, I]) This function returns a string containing as many random bytes as requested by the integral argument I. An optional I argument is passed to the system first. =item B(I) Calculate a uniformly distributed random number less than upper_bound avoiding "modulo bias". =back =head2 PACKAGE VARIABLES =over 4 =item B<$RANDOM> The B<$RANDOM> returns a random value in the range S<[0; 32767]> on each read attempt and pushes any value it is assigned to the kernel. It is tied at module load time. =item tie I, 'BSD::arc4random'[, I] You can tie any scalar variable to this package; the I argument is the maximum number returned; if undefined, 0 or S= 0xFFFFFFFF>, no bound is used, and values in the range S<[0; 2**32-1]> are returned. They will behave like B<$RANDOM>. =back =head1 AUTHOR Thorsten Glaser Etg@mirbsd.deE =head1 SEE ALSO The L manual page, available online at: L Perl's L and L functions via L and L. The B plugin for Irssi, implementing the MirOS RANDEX protocol (entropy exchange over IRC), with CVSweb at: L L when it's done being written. =head1 COPYRIGHT AND LICENSE Copyright (c) 2008, 2009, 2010, 2011 Thorsten "mirabilos" Glaser Copyright (c) 2009 Benny Siegert Credits to Sebastian "Vutral" Schwarz This module is covered by the MirOS Licence: L The original C implementation of arc4random_uniform was contributed by Damien Miller from OpenBSD, with simplifications by Jinmei Tatuya. =cut BSD-arc4random-1.50/MANIFEST010064400000000000000000000001441120400560000140730ustar00rootwheelMANIFEST META.yml Makefile.PL README TODO arc4random.c arc4rnd_xs.c lib/BSD/arc4random.pm t/check.t BSD-arc4random-1.50/META.yml010064400000000000000000000004701157300737700142430ustar00rootwheel# http://module-build.sourceforge.net/META-spec.html #XXXXXXX This is a prototype!!! It will change in the future!!! XXXXX# name: BSD-arc4random version: 1.50 version_from: lib/BSD/arc4random.pm installdirs: site requires: distribution_type: module generated_by: ExtUtils::MakeMaker version 6.30 BSD-arc4random-1.50/Makefile.PL010064400000000000000000000054021157300512000147240ustar00rootwheel# $MirOS: contrib/hosted/tg/code/BSD::arc4random/Makefile.PL,v 1.6 2011/06/05 22:59:04 tg Exp $ #- # Copyright (c) 2008, 2009, 2011 # Thorsten Glaser # # Provided that these terms and disclaimer and all copyright notices # are retained or reproduced in an accompanying document, permission # is granted to deal in this work without restriction, including un- # limited rights to use, publicly perform, distribute, sell, modify, # merge, give away, or sublicence. # # This work is provided "AS IS" and WITHOUT WARRANTY of any kind, to # the utmost extent permitted by applicable law, neither express nor # implied; without malicious intent or gross negligence. In no event # may a licensor, author or contributor be held liable for indirect, # direct, other damage, loss, or other issues arising in any way out # of dealing in the work, even if advised of the possibility of such # damage or existence of a defect, except proven that it results out # of said person's immediate fault when using the work as intended. use 5.000; use ExtUtils::MakeMaker; # configuration, set to auto or manual my $cfg = 'auto'; # override these values if manual mode my $libs = ''; my $defs = '-DHAVE_ARC4RANDOM_PUSHB=1'; my $incs = ''; my $objs = ''; # do not override below for auto mode if ($cfg eq 'auto') { # note order is important if ($^O ne 'mirbsd' && $^O ne 'cygwin') { $defs = '-DHAVE_ARC4RANDOM_PUSHB=0'; } if ($^O eq 'interix') { $libs = '-lcrypt'; } if (($^O eq 'gnu') || ($^O eq 'gnukfreebsd') || ($^O eq 'linux')) { # Debian GNU/HURD, GNU/kFreeBSD, GNU/Linux # either use libbsd (lenny and up): #$incs = '-include /usr/include/bsd/bsd.h'; #$libs = '-lbsd'; # or use the contributed arc4random.c file $objs = 'arc4random.o'; $defs .= ' -DHAVE_SYS_SYSCTL_H=0 -DHAVE_STDINT_H=1'; $defs .= ' -DNEED_ARC4RANDOM_DECL'; } if (($^O eq 'cygwin') || ($^O eq 'MSWin32') || ($^O eq 'irix') || ($^O eq 'solaris')) { # Cygwin, Solaris: use arc4random.c contributed file # IRIX: the same, except we don't know if it works there # XXX the presence of arc4random.c here is a KLUDGE going away! # XXX Solaris 10 has but Cygwin and Solaris 8 don't. $objs = 'arc4random.o'; $defs .= ' -DNEED_ARC4RANDOM_DECL'; if ($^O eq 'solaris') { $defs .= ' -DHAVE_SYS_SYSCTL_H=0 -DHAVE_STDINT_H=0'; $defs .= ' -DUSE_INTTYPES -DREDEF_USCORETYPES'; } } } if ($objs eq '') { $objs = 'arc4rnd_xs.o'; } else { $objs = 'arc4rnd_xs.o ' . $objs; } WriteMakefile( NAME => 'BSD::arc4random', VERSION_FROM => 'lib/BSD/arc4random.pm', PREREQ_PM => {}, ($] >= 5.005 ? ( ABSTRACT_FROM => 'lib/BSD/arc4random.pm', AUTHOR => 'Thorsten Glaser ' ) : ()), LIBS => $libs, DEFINE => $defs, INC => $incs, OBJECT => $objs ); BSD-arc4random-1.50/README010064400000000000000000000070241157300737700136540ustar00rootwheelBSD::arc4random version 1.50 ============================ This module provides a Perl API for the BSDs' arc4random(3) suite of functions and adds a few high-level functions, such as the new arc4random_uniform(3). The Perl functions are ithreads-safe (only if threads::shared is required). Scalars can be tied to this pak- kage, yielding uniformly distributed random numbers with an arbi- trary upper bound on read access, contributing to the RC4 entropy pool on write access. An exported global $RANDOM variable returns 15-bit unsigned random numbers, from [0; 32767], similar to mksh. Furthermore, Perl's internal PRNG is seeded with entropy obtained from the arc4random generator once on module load time. INSTALLATION Makefile.PL tries to auto-detect existence of arc4random_pushb by looking at the operating system used; see below if this fails: If your system does not have arc4random_pushb(3), edit the DEFINE line in Makefile.PL to define HAVE_ARC4RANDOM_PUSHB to 0 and make sure at least arc4random_addrandom(3) exists. *HOWEVER* note that then, entropy pushed into the system will end up in the process's own pool instead of in the kernel. You can fix this by regularily calling arc4random() or arc4random_bytes() and writing the output to /dev/urandom or similar (after obtaining permissions) FROM THE SAME PROCESS/SCRIPT (other ithread is okay) or, better, providing at compile time an arc4random_pushb(3)* implementation collecting entropy, sending it to a sensible place, e.g. a gathering daemon. Using a seed file, similar to the randex.pl Irssi plugin, is also a viable option. Future versions of this module will have support for seed files and entropy daemons included. *) http://www.mirbsd.org/man3/arc4random If your system's arc4random(3) function suite is not in libc, edit the LIBS line in Makefile.PL to include the appropriate library, e.g. -lbsd on Debian or -lcrypt on Interix, and possibly the INC line to use the appropriate header, e.g. something like this for Debian libbsd: '-include /usr/include/bsd/bsd.h' NOTE: This version of BSD::arc4random comes with an experimental implementation tested on BSD, Cygwin, Debian and Solaris; this is a kludge and will most likely go away. It is only used automati- cally on Debian GNU/HURD, GNU/kFreeBSD, GNU/Linux, as well as Cygwin and Solaris. It can be used on some BSDs as well; support for pushing back entropy is available on Cygwin/WIN32 and MirBSD. To install this module type the following: perl Makefile.PL make make test make install DEPENDENCIES This module requires arc4random(3), arc4random_addrandom(3) and arc4random_stir(3) in libc. There are configuration options in Makefile.PL, to change for example, if a different library like libcrypt on Interix or libbsd on Debian is required to pull in these functions. COPYRIGHT AND LICENCE Copyright (c) 2008, 2009, 2010, 2011 Thorsten "mirabilos" Glaser, MirOS Project Copyright (c) 2009 Benny Siegert, MirOS Project Uploaded to CPAN by: Sebastian "Vutral" Schwarz (PAUSE ID: SJSZ) Credits to him for input, ideas and a lot of help. The arc4random(9) PRNG has been invented by the OpenBSD Project. The arc4random_uniform algorithm is derived from the code in the OpenBSD kernel, published by Damien Miller under the ISC licence (although no code was copied, acknowledgement is granted). This module is covered by the MirOS Licence: http://mirbsd.de/MirOS-Licence ________________________________________________________________________________________ $MirOS: contrib/hosted/tg/code/BSD::arc4random/README,v 1.6 2011/06/05 23:19:03 tg Exp $ BSD-arc4random-1.50/TODO010064400000000000000000000012511144622121400134430ustar00rootwheel$MirOS: contrib/hosted/tg/code/BSD::arc4random/TODO,v 1.4 2010/09/21 21:24:04 tg Exp $ • write an improved arc4random(3) et al. implementation, which can talk to an EGD/PRNGD as well as have more system interfaces • integrate seedfile support from the randex.pl irssi plugin ‣ 600 bytes, for gcrypt/GnuPG compatibility • reduce amount of data drawn from /dev/urandom on e.g. Linux • try /proc/sys/kernel/random/uuid (Linux), something kFreeBSD • expose some more APIs • move have_kintf to the arc4random implementation • write an entropy pool dæmon, use it • add arc4random_buf and deprecate arc4random_bytes • internally use, and maybe expose, oaat hash BSD-arc4random-1.50/arc4random.c010064400000000000000000000370641144314322300151640ustar00rootwheelstatic const char __vcsid[] = "@(#) MirOS contributed arc4random.c (old)" "\n @(#)rcsid_master: $MirOS: contrib/code/Snippets/arc4random.c,v 1.28 2010/09/12 12:24:27 tg Exp $" ; /*- * Arc4 random number generator for OpenBSD. * Copyright 1996 David Mazieres . * * Modification and redistribution in source and binary forms is * permitted provided that due credit is given to the author and the * OpenBSD project by leaving this copyright notice intact. */ /*- * 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. * * Here the stream cipher has been modified always to include the time * when initializing the state. That makes it impossible to * regenerate the same random sequence twice, so this can't be used * for encryption, but will generate good random numbers. * * RC4 is a registered trademark of RSA Laboratories. */ /*- * Modified by Robert Connolly from OpenBSD lib/libc/crypt/arc4random.c v1.11. * This is arc4random(3) using urandom. */ /*- * Copyright (c) 2008, 2009, 2010 * Thorsten Glaser * This is arc4random(3) made more portable, * as well as arc4random_pushb(3) for Cygwin. * * Provided that these terms and disclaimer and all copyright notices * are retained or reproduced in an accompanying document, permission * is granted to deal in this work without restriction, including un- * limited rights to use, publicly perform, distribute, sell, modify, * merge, give away, or sublicence. * * This work is provided "AS IS" and WITHOUT WARRANTY of any kind, to * the utmost extent permitted by applicable law, neither express nor * implied; without malicious intent or gross negligence. In no event * may a licensor, author or contributor be held liable for indirect, * direct, other damage, loss, or other issues arising in any way out * of dealing in the work, even if advised of the possibility of such * damage or existence of a defect, except proven that it results out * of said person's immediate fault when using the work as intended. */ #include #include #include #if defined(HAVE_SYS_SYSCTL_H) && HAVE_SYS_SYSCTL_H #include #endif #include #if defined(HAVE_STDINT_H) && HAVE_STDINT_H #include #elif defined(USE_INTTYPES) #include #endif #include #include #include #include #if defined(__CYGWIN__) || defined(WIN32) #define USE_MS_CRYPTOAPI #define REDEF_USCORETYPES #endif #ifdef USE_MS_CRYPTOAPI #define WIN32_WINNT 0x400 #define _WIN32_WINNT 0x400 #include #include static uint8_t w32_buf[16*16384]; /* force reseed */ static uint8_t w32_hklm[80]; /* registry key (MS, Admin) */ static uint8_t w32_hkcu[256]; /* registry key (per user) */ static struct timeval w32_last; /* last time CGR was used */ static char w32_subkey[] = "SOFTWARE\\Microsoft\\Cryptography\\RNG"; #endif #ifndef MIN #define MIN(a,b) (((a)<(b))?(a):(b)) #endif #ifndef MAX #define MAX(a,b) (((a)>(b))?(a):(b)) #endif #ifdef REDEF_USCORETYPES #define u_int32_t uint32_t #endif #ifndef _PATH_URANDOM #define _PATH_URANDOM "/dev/urandom" #endif static struct arc4_stream { uint8_t i; uint8_t j; uint8_t s[256]; } arc4_ctx; static int rs_initialized; static pid_t arc4_stir_pid; static int arc4_count; static const char __randomdev[] = _PATH_URANDOM; static uint8_t arc4_getbyte(void); static void stir_finish(uint8_t); static void arc4_atexit(void); static char arc4_writeback(uint8_t *, size_t, char); #ifndef arc4random_pushk u_int32_t arc4random(void); void arc4random_addrandom(u_char *, int); void arc4random_stir(void); #if defined(USE_MS_CRYPTOAPI) || defined(OPPORTUNISTIC_ROOT_PUSHB) uint32_t arc4random_pushb(const void *, size_t); #endif #endif #define NEED_UNIFORM_BUF_PROTO #if defined(__OpenBSD__) && defined(OpenBSD) && (OpenBSD > 200805) #undef NEED_UNIFORM_BUF_PROTO #elif defined(__MirBSD__) && defined(MirBSD) && (MirBSD > 0x0AA4) #undef NEED_UNIFORM_BUF_PROTO #endif #ifdef NEED_UNIFORM_BUF_PROTO u_int32_t arc4random_uniform(u_int32_t); void arc4random_buf(void *, size_t); #endif static void arc4_init(void) { int n; for (n = 0; n < 256; n++) arc4_ctx.s[n] = (uint8_t)n; arc4_ctx.i = 0; arc4_ctx.j = 0; } static void arc4_addrandom(const u_char *dat, size_t datlen) { size_t n = 0; uint8_t si; arc4_ctx.i--; while (n < 256) { arc4_ctx.i++; si = arc4_ctx.s[arc4_ctx.i]; arc4_ctx.j = (uint8_t)(arc4_ctx.j + si + dat[n++ % datlen]); arc4_ctx.s[arc4_ctx.i] = arc4_ctx.s[arc4_ctx.j]; arc4_ctx.s[arc4_ctx.j] = si; } arc4_ctx.i++; arc4_ctx.j = arc4_ctx.i; } #if defined(USE_MS_CRYPTOAPI) #define RNDEV_BYTES 128 #elif defined(__INTERIX) #define RNDEV_BYTES 4 /* slow /dev/urandom */ #elif defined(__OpenBSD__) #define RNDEV_BYTES (256 - (sizeof(struct timeval) + sizeof(pid_t))) #elif defined(__CYGWIN__) #define RNDEV_BYTES 64 /* /dev/urandom probably CryptoAPI */ #elif defined(__FreeBSD__) #define RNDEV_BYTES 16 /* Yarrow has few state */ #elif defined(__GLIBC__) #define RNDEV_BYTES 16 /* requested by maintainers */ #else #define RNDEV_BYTES 8 /* unknown OS? */ #endif static void arc4_stir(void) { int fd; struct { struct timeval tv; pid_t pid; u_int rnd[(RNDEV_BYTES + sizeof(u_int) - 1) / sizeof(u_int)]; } rdat; size_t sz = 0; gettimeofday(&rdat.tv, NULL); rdat.pid = getpid(); memcpy(rdat.rnd, __vcsid, MIN(sizeof(__vcsid), sizeof(rdat.rnd))); #ifdef USE_MS_CRYPTOAPI if (arc4_writeback((char *)rdat.rnd, sizeof(rdat.rnd), 1)) goto stir_okay; #endif /* /dev/urandom is a multithread interface, sysctl is not. */ /* Try to use /dev/urandom before sysctl. */ fd = open(__randomdev, O_RDONLY); if (fd != -1) { sz = (size_t)read(fd, rdat.rnd, sizeof(rdat.rnd)); close(fd); } if (sz > sizeof(rdat.rnd)) sz = 0; if (fd == -1 || sz != sizeof(rdat.rnd)) { /* /dev/urandom failed? Maybe we're in a chroot. */ #if /* Linux */ defined(_LINUX_SYSCTL_H) || \ /* OpenBSD */ (defined(CTL_KERN) && defined(KERN_ARND)) int mib[3], nmib = 3; size_t i = sz / sizeof(u_int), len; #ifdef _LINUX_SYSCTL_H mib[0] = CTL_KERN; mib[1] = KERN_RANDOM; mib[2] = RANDOM_UUID; #else mib[0] = CTL_KERN; mib[1] = KERN_ARND; nmib = 2; #endif while (i < sizeof(rdat.rnd) / sizeof(u_int)) { len = sizeof(u_int); if (sysctl(mib, nmib, &rdat.rnd[i++], &len, NULL, 0) == -1) { fputs("warning: no entropy source\n", stderr); break; } } #else /* XXX kFreeBSD doesn't seem to have KERN_ARND or so */ ; #endif } #ifdef USE_MS_CRYPTOAPI stir_okay: #endif fd = arc4_getbyte(); /* * Time to give up. If no entropy could be found then we will just * use gettimeofday and getpid. */ arc4_addrandom((u_char *)&rdat, sizeof(rdat)); stir_finish(fd); } static void stir_finish(uint8_t av) { size_t n; uint8_t tb[16]; arc4_stir_pid = getpid(); /* * Discard early keystream, as per recommendations in: * http://www.wisdom.weizmann.ac.il/~itsik/RC4/Papers/Rc4_ksa.ps * We discard 256 words. A long word is 4 bytes. * We also discard a randomly fuzzed amount. */ n = 256 * 4 + (arc4_getbyte() & 0x0FU) + (av & 0xF0U); av &= 0x0FU; while (n--) arc4_getbyte(); while (++n < sizeof(tb)) tb[n] = arc4_getbyte(); if (arc4_writeback(tb, sizeof(tb), 0)) arc4_getbyte(); while (av--) arc4_getbyte(); arc4_count = 1600000; } static uint8_t arc4_getbyte(void) { uint8_t si, sj; arc4_ctx.i++; si = arc4_ctx.s[arc4_ctx.i]; arc4_ctx.j = (uint8_t)(arc4_ctx.j + si); sj = arc4_ctx.s[arc4_ctx.j]; arc4_ctx.s[arc4_ctx.i] = sj; arc4_ctx.s[arc4_ctx.j] = si; return (arc4_ctx.s[(si + sj) & 0xff]); } static uint32_t arc4_getword(void) { uint32_t val; val = (uint32_t)arc4_getbyte() << 24; val |= (uint32_t)arc4_getbyte() << 16; val |= (uint32_t)arc4_getbyte() << 8; val |= (uint32_t)arc4_getbyte(); return (val); } void arc4random_stir(void) { if (!rs_initialized) { arc4_init(); rs_initialized = 1; atexit(arc4_atexit); } arc4_stir(); } void arc4random_addrandom(u_char *dat, int datlen) { if (!rs_initialized) arc4random_stir(); arc4_addrandom(dat, datlen); } u_int32_t arc4random(void) { arc4_count -= 4; if (arc4_count <= 0 || !rs_initialized || arc4_stir_pid != getpid()) arc4random_stir(); return arc4_getword(); } /* * Returns 0 if write error; 0 if do_rd and read error; * 1 if !do_rd and read error but not write error; * 1 if no error occured. */ static char arc4_writeback(uint8_t *buf, size_t len, char do_rd) { #ifdef USE_MS_CRYPTOAPI static char has_provider = 0; static HCRYPTPROV p; HKEY hKeyLM, hKeyCU; DWORD ksz; char rc = 6, has_rkey = 0, w32_a4b[16]; size_t i, j, xlen; struct timeval tv; for (i = 0; i < sizeof(w32_a4b); ++i) w32_a4b[i] = arc4_getbyte(); for (i = arc4_getbyte() & 15; i; --i) arc4_getbyte(); ksz = sizeof(w32_buf); if ((/* read-write */ RegOpenKeyEx(HKEY_LOCAL_MACHINE, w32_subkey, 0, KEY_QUERY_VALUE | KEY_SET_VALUE, &hKeyLM) == ERROR_SUCCESS || /* try read-only */ RegOpenKeyEx(HKEY_LOCAL_MACHINE, w32_subkey, 0, KEY_QUERY_VALUE, &hKeyLM) == ERROR_SUCCESS) && /* get value */ (RegQueryValueEx(hKeyLM, "Seed", NULL, NULL, w32_buf, &ksz) == ERROR_SUCCESS) && /* got any content? */ ksz) { /* we got HKLM key, read-write or read-only */ has_rkey |= 1; /* move content to destination */ memset(w32_hklm, '\0', sizeof(w32_hklm)); for (i = 0; i < MAX(ksz, sizeof(w32_hklm)); ++i) w32_hklm[i % sizeof(w32_hklm)] ^= w32_buf[i % ksz]; } ksz = sizeof(w32_buf); if ((/* read-write */ RegCreateKeyEx(HKEY_CURRENT_USER, w32_subkey, 0, NULL, 0, KEY_QUERY_VALUE | KEY_SET_VALUE, NULL, &hKeyCU, NULL) == ERROR_SUCCESS || /* R/O */ RegOpenKeyEx(HKEY_CURRENT_USER, w32_subkey, 0, KEY_QUERY_VALUE, &hKeyLM) == ERROR_SUCCESS) && /* get value */ (RegQueryValueEx(hKeyLM, "Seed", NULL, NULL, w32_buf, &ksz) == ERROR_SUCCESS) && /* got any content? */ ksz) { /* we got HKCU key, created, read-write or read-only */ has_rkey |= 2; /* move content to destination */ memset(w32_hkcu, '\0', sizeof(w32_hkcu)); for (i = 0; i < MAX(ksz, sizeof(w32_hkcu)); ++i) w32_hkcu[i % sizeof(w32_hkcu)] ^= w32_buf[i % ksz]; } if (!do_rd) goto nogen_out; if (has_rkey && gettimeofday(&tv, NULL) == 0) { /* we have registry key; rate-limit CryptGenRandom */ if (tv.tv_sec - w32_last.tv_sec < 128 + (arc4_getbyte() & 127)) goto nogen_out; /* nope, more than 2-4 minutes, call it */ w32_last.tv_sec = tv.tv_sec; } if (!has_provider) { if (!CryptAcquireContext(&p, NULL, NULL, PROV_RSA_FULL, 0)) { if ((HRESULT)GetLastError() != NTE_BAD_KEYSET) goto nogen_out; if (!CryptAcquireContext(&p, NULL, NULL, PROV_RSA_FULL, CRYPT_NEWKEYSET)) goto nogen_out; } has_provider = 1; } i = 0; while (i < 256) w32_buf[i++] = arc4_getbyte(); if (!CryptGenRandom(p, sizeof(w32_buf), w32_buf)) { w32_last.tv_sec = 0; nogen_out: rc |= 1; memset(w32_buf, '\0', 256); } xlen = MIN(sizeof(w32_buf) - sizeof(w32_hklm) - sizeof(w32_hkcu) - sizeof(w32_a4b), len); j = xlen + sizeof(w32_hklm) + sizeof(w32_hkcu) + sizeof(w32_a4b); for (i = 0; i < MAX(j, len); ++i) w32_buf[i % j] ^= w32_hklm[i % sizeof(w32_hklm)] ^ w32_hkcu[i % sizeof(w32_hkcu)] ^ buf[i % len] ^ arc4_getbyte(); if (has_rkey & 1) { if (RegSetValueEx(hKeyLM, "Seed", 0, REG_BINARY, w32_buf, sizeof(w32_hklm)) == ERROR_SUCCESS) rc &= ~2; RegCloseKey(hKeyLM); } if (has_rkey & 2) { if (RegSetValueEx(hKeyCU, "Seed", 0, REG_BINARY, w32_buf + sizeof(w32_hklm), sizeof(w32_hkcu)) == ERROR_SUCCESS) rc &= ~4; RegCloseKey(hKeyCU); } for (i = 0; i < sizeof(w32_a4b); ++i) w32_a4b[i] ^= w32_buf[sizeof(w32_hklm) + sizeof(w32_hkcu) + i]; arc4_addrandom(w32_a4b, sizeof(w32_a4b)); i = sizeof(w32_hklm) + sizeof(w32_hkcu) + sizeof(w32_a4b); while (len) { j = MIN(len, xlen); memcpy(buf, w32_buf + i, j); buf += j; len -= j; } memset(w32_buf, '\0', sizeof(w32_buf)); return ( /* read error occured */ (!has_rkey && (rc & 1)) ? 0 : /* don't care about write errors */ !do_rd ? 1 : /* couldn't write */ (rc & 6) == 6 ? 0 : /* at least one RegSetValueEx succeeded */ 1); #elif defined(arc4random_pushk) uint32_t num; num = arc4random_pushk(buf, len); memcpy(buf, &num, sizeof(num)); return (do_rd ? 0 : 1); #else int fd; if ((fd = open(__randomdev, O_WRONLY)) != -1) { if (write(fd, buf, len) < 4) do_rd = 1; close(fd); } return (do_rd || fd == -1 ? 0 : 1); #endif } #if defined(USE_MS_CRYPTOAPI) || defined(arc4random_pushk) || \ defined(OPPORTUNISTIC_ROOT_PUSHB) uint32_t arc4random_pushb(const void *src, size_t len) { size_t rlen; union { uint8_t buf[256]; struct { struct timeval tv; const void *sp, *dp; size_t sz; uint32_t vu; } s; uint32_t xbuf; } idat; uint32_t res = 1; if (!rs_initialized) { arc4_init(); rs_initialized = 1; } idat.s.sp = &idat; idat.s.dp = src; idat.s.sz = len; idat.s.vu = arc4_getword(); gettimeofday(&idat.s.tv, NULL); rlen = MAX(sizeof(idat.s), len); while (rlen--) idat.buf[rlen % sizeof(idat.buf)] ^= ((const uint8_t *)src)[rlen % len]; rlen = MIN(sizeof(idat), MAX(sizeof(idat.s), len)); if (arc4_writeback((void *)&idat, rlen, 1)) res = 0; arc4_addrandom((void *)&idat, rlen); rlen = arc4_getbyte() & 1; if (res) res = idat.xbuf; else /* we got entropy from the kernel, so consider us stirred */ stir_finish(idat.buf[5]); if (rlen) (void)arc4_getbyte(); return (res ^ arc4_getword()); } #endif static void arc4_atexit(void) { struct { pid_t spid; int cnt; uint8_t carr[240]; } buf; int i = 0; while (i < 240) buf.carr[i++] = arc4_getbyte(); buf.spid = arc4_stir_pid; buf.cnt = arc4_count; arc4_writeback((uint8_t *)&buf, sizeof(buf), 0); } void arc4random_buf(void *_buf, size_t n) { uint8_t *buf = (uint8_t *)_buf; if (!rs_initialized || arc4_stir_pid != getpid()) arc4random_stir(); buf[0] = arc4_getbyte() % 3; while (buf[0]--) (void)arc4_getbyte(); while (n--) { if (--arc4_count <= 0) arc4_stir(); buf[n] = arc4_getbyte(); } } /*- * Written by Damien Miller. * With simplifications by Jinmei Tatuya. */ /* * 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 the range * [2^32 % upper_bound, 2^32[ which maps back to * [0, upper_bound[ after reduction modulo upper_bound. */ uint32_t arc4random_uniform(uint32_t upper_bound) { uint32_t r, min; if (upper_bound < 2) return (0); #if defined(ULONG_MAX) && (ULONG_MAX > 0xFFFFFFFFUL) min = 0x100000000UL % upper_bound; #else /* calculate (2^32 % upper_bound) avoiding 64-bit math */ if (upper_bound > 0x80000000U) /* 2^32 - upper_bound (only one "value area") */ min = 1 + ~upper_bound; else /* ((2^32 - x) % x) == (2^32 % x) when x <= 2^31 */ min = (0xFFFFFFFFU - upper_bound + 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 (at all). */ arc4_count -= 4; if (!rs_initialized || arc4_stir_pid != getpid() || arc4_count <= 0) arc4random_stir(); if (arc4_getbyte() & 1) (void)arc4_getbyte(); do { r = arc4_getword(); } while (r < min); return (r % upper_bound); } BSD-arc4random-1.50/arc4rnd_xs.c010064400000000000000000000130261126420710100151660ustar00rootwheel/*- * Copyright (c) 2008, 2009 * Thorsten Glaser * * Provided that these terms and disclaimer and all copyright notices * are retained or reproduced in an accompanying document, permission * is granted to deal in this work without restriction, including un- * limited rights to use, publicly perform, distribute, sell, modify, * merge, give away, or sublicence. * * This work is provided "AS IS" and WITHOUT WARRANTY of any kind, to * the utmost extent permitted by applicable law, neither express nor * implied; without malicious intent or gross negligence. In no event * may a licensor, author or contributor be held liable for indirect, * direct, other damage, loss, or other issues arising in any way out * of dealing in the work, even if advised of the possibility of such * damage or existence of a defect, except proven that it results out * of said person's immediate fault when using the work as intended. */ #include #include #if defined(HAVE_STDINT_H) && HAVE_STDINT_H #include #elif defined(USE_INTTYPES) #include #endif #include "EXTERN.h" #include "perl.h" #include "XSUB.h" #if !defined(__attribute__) && (!defined(__GNUC__) || (__GNUC__ < 1) || (__GNUC__ == 2 && __GNUC_MINOR__ < 5)) #define __attribute__(x) /* nothing */ #endif #if !defined(__RCSID) || !defined(__IDSTRING) #undef __RCSID #undef __IDSTRING #undef __IDSTRING_CONCAT #undef __IDSTRING_EXPAND #define __IDSTRING_CONCAT(l,p) __LINTED__ ## l ## _ ## p #define __IDSTRING_EXPAND(l,p) __IDSTRING_CONCAT(l,p) #define __IDSTRING(prefix, string) \ static const char __IDSTRING_EXPAND(__LINE__,prefix) [] \ __attribute__((used)) = "@(""#)" #prefix ": " string #define __RCSID(x) __IDSTRING(rcsid,x) #endif __RCSID("$MirOS: contrib/hosted/tg/code/BSD::arc4random/arc4rnd_xs.c,v 1.5 2009/10/10 22:43:53 tg Exp $"); #ifdef REDEF_USCORETYPES #define u_int32_t uint32_t #endif #ifdef NEED_ARC4RANDOM_DECL u_int32_t arc4random(void); void arc4random_addrandom(u_char *, int); #endif XS(XS_BSD__arc4random_arc4random_xs); XS(XS_BSD__arc4random_arc4random_xs) { dXSARGS; dXSTARG; uint32_t rv; rv = arc4random(); XSprePUSH; PUSHu((UV)rv); XSRETURN(1); } XS(XS_BSD__arc4random_stir_xs); XS(XS_BSD__arc4random_stir_xs) { dXSARGS; arc4random_stir(); XSRETURN_EMPTY; } XS(XS_BSD__arc4random_arc4random_addrandom_xs); XS(XS_BSD__arc4random_arc4random_addrandom_xs) { dXSARGS; dXSTARG; SV *sv; char *buf; STRLEN len; uint32_t rv; sv = ST(0); buf = SvPV(sv, len); arc4random_addrandom((unsigned char *)buf, (int)len); rv = arc4random(); XSprePUSH; PUSHu((UV)rv); XSRETURN(1); } #ifndef HAVE_ARC4RANDOM_PUSHB #define HAVE_ARC4RANDOM_PUSHB 1 #endif #if HAVE_ARC4RANDOM_PUSHB XS(XS_BSD__arc4random_arc4random_pushb_xs); XS(XS_BSD__arc4random_arc4random_pushb_xs) { dXSARGS; dXSTARG; SV *sv; char *buf; STRLEN len; uint32_t rv; sv = ST(0); buf = SvPV(sv, len); rv = arc4random_pushb((void *)buf, (size_t)len); XSprePUSH; PUSHu((UV)rv); XSRETURN(1); } #elif defined(arc4random_pushk) #define XS_BSD__arc4random_arc4random_pushb_xs \ XS_BSD__arc4random_arc4random_pushk_xs #else #define XS_BSD__arc4random_arc4random_pushb_xs \ XS_BSD__arc4random_arc4random_addrandom_xs #endif #if defined(arc4random_pushk) XS(XS_BSD__arc4random_arc4random_pushk_xs); XS(XS_BSD__arc4random_arc4random_pushk_xs) { dXSARGS; dXSTARG; SV *sv; char *buf; STRLEN len; uint32_t rv; sv = ST(0); buf = SvPV(sv, len); rv = arc4random_pushk((void *)buf, (size_t)len); XSprePUSH; PUSHu((UV)rv); XSRETURN(1); } #elif HAVE_ARC4RANDOM_PUSHB #define XS_BSD__arc4random_arc4random_pushk_xs \ XS_BSD__arc4random_arc4random_pushb_xs #else #define XS_BSD__arc4random_arc4random_pushk_xs \ XS_BSD__arc4random_arc4random_addrandom_xs #endif #undef HAVE_ARC4RANDOM_KINTF #if HAVE_ARC4RANDOM_PUSHB || defined(arc4random_pushk) #define HAVE_ARC4RANDOM_KINTF 1 #else #define HAVE_ARC4RANDOM_KINTF 0 #endif /* * These may be needed because praeprocessor commands inside a * macro's argument list may not work */ #if HAVE_ARC4RANDOM_PUSHB #define IDT_ARC4RANDOM_PUSHB " arc4random_pushb" #else #define IDT_ARC4RANDOM_PUSHB "" #endif #if defined(arc4random_pushk) #define IDT_arc4random_pushk " arc4random_pushk" #else #define IDT_arc4random_pushk "" #endif #if HAVE_ARC4RANDOM_KINTF #define IDT_ARC4RANDOM_KINTF " have_kintf:=1" #else #define IDT_ARC4RANDOM_KINTF " have_kintf:=0" #endif __IDSTRING(api_text, "BSD::arc4random " XS_VERSION " with {" " arc4random" " arc4random_addrandom" IDT_ARC4RANDOM_PUSHB IDT_arc4random_pushk IDT_ARC4RANDOM_KINTF " }"); /* the Perl API is not const clean */ static char file[] = __FILE__; static char func_a4r[] = "BSD::arc4random::arc4random_xs"; static char func_a4add[] = "BSD::arc4random::arc4random_addrandom_xs"; static char func_a4rpb[] = "BSD::arc4random::arc4random_pushb_xs"; static char func_a4rpk[] = "BSD::arc4random::arc4random_pushk_xs"; static char func_astir[] = "BSD::arc4random::arc4random_stir_xs"; static char func_kintf[] = "BSD::arc4random::have_kintf"; #ifdef __cplusplus extern "C" #endif XS(boot_BSD__arc4random); XS(boot_BSD__arc4random) { dXSARGS; XS_VERSION_BOOTCHECK; newXS(func_a4r, XS_BSD__arc4random_arc4random_xs, file); newXS(func_a4add, XS_BSD__arc4random_arc4random_addrandom_xs, file); newXS(func_a4rpb, XS_BSD__arc4random_arc4random_pushb_xs, file); newXS(func_a4rpk, XS_BSD__arc4random_arc4random_pushk_xs, file); newXS(func_astir, XS_BSD__arc4random_stir_xs, file); newCONSTSUB(NULL, func_kintf, newSViv(HAVE_ARC4RANDOM_KINTF)); XSRETURN_YES; } BSD-arc4random-1.50/t004075500000000000000000000000001157300774100131535ustar00rootwheelBSD-arc4random-1.50/t/check.t010064400000000000000000000066451157300654100145010ustar00rootwheel# $MirOS: contrib/hosted/tg/code/BSD::arc4random/t/check.t,v 1.4 2011/06/05 23:12:09 tg Exp $ #- # Copyright (c) 2008, 2011 # Thorsten Glaser # # Provided that these terms and disclaimer and all copyright notices # are retained or reproduced in an accompanying document, permission # is granted to deal in this work without restriction, including un- # limited rights to use, publicly perform, distribute, sell, modify, # merge, give away, or sublicence. # # This work is provided "AS IS" and WITHOUT WARRANTY of any kind, to # the utmost extent permitted by applicable law, neither express nor # implied; without malicious intent or gross negligence. In no event # may a licensor, author or contributor be held liable for indirect, # direct, other damage, loss, or other issues arising in any way out # of dealing in the work, even if advised of the possibility of such # damage or existence of a defect, except proven that it results out # of said person's immediate fault when using the work as intended. print "1..23\n"; use BSD::arc4random qw(:all); my $enta = $RANDOM; my $entb = $RANDOM; # $RANDOM must output numerics print "not " unless $enta =~ /^[0-9]+$/; print "ok 1\n"; print "not " unless $entb =~ /^[0-9]+$/; print "ok 2\n"; # $RANDOM output must be inside [0; 32767] print "not " if (($enta < 0) || ($enta > 32767)); print "ok 3\n"; print "not " if (($entb < 0) || ($entb > 32767)); print "ok 4\n"; # $RANDOM output should differ each time print "not " if ($enta == $entb); print "ok 5\n"; # Check exported variables my $v = ${BSD::arc4random::VERSION}; my $k = BSD::arc4random::have_kintf(); print "not " unless (($v =~ /^[0-9]+.[0-9]+$/) && (($k == 0) || ($k == 1))); print "ok 6\n"; print STDERR "DIAG: BSD::arc4random $v with"; print STDERR "out" if $k == 0; print STDERR " kernel interface\n"; # test storing to the tied variable $RANDOM = 123; $enta = $RANDOM; $RANDOM = 456; $entb = $RANDOM; print "not " unless $enta =~ /^[0-9]+$/; print "ok 7\n"; print "not " unless $entb =~ /^[0-9]+$/; print "ok 8\n"; print "not " if (($enta < 0) || ($enta > 32767)); print "ok 9\n"; print "not " if (($entb < 0) || ($entb > 32767)); print "ok 10\n"; print "not " if ($enta == $entb); print "ok 11\n"; print "not " if (($enta == 123) && ($entb == 456)); print "ok 12\n"; sub timed_out { die "GOT TIRED OF WAITING"; } $SIG{ALRM} = \&timed_out; eval { alarm(10); # test arc4random_uniform lower half $enta = arc4random_uniform(10000); $entb = arc4random_uniform(10000); print "not " unless $enta =~ /^[0-9]+$/; print "ok 13\n"; print "not " unless $entb =~ /^[0-9]+$/; print "ok 14\n"; print "not " if (($enta < 0) || ($enta > 9999)); print "ok 15\n"; print "not " if (($entb < 0) || ($entb > 9999)); print "ok 16\n"; print "not " if ($enta == $entb); print "ok 17\n"; # test arc4random_uniform upper half $enta = arc4random_uniform(2999999901); $entb = arc4random_uniform(2999999901); print "not " unless $enta =~ /^[0-9]+$/; print "ok 18\n"; print "not " unless $entb =~ /^[0-9]+$/; print "ok 19\n"; print "not " if (($enta < 0) || ($enta > 2999999900)); print "ok 20\n"; print "not " if (($entb < 0) || ($entb > 2999999900)); print "ok 21\n"; print "not " if ($enta == $entb); print "ok 22\n"; alarm(0); }; if ($@ =~ /GOT TIRED OF WAITING/) { print STDERR "DIAG: 10 second timeout on execution reached\n"; print STDERR "DIAG: this is probably a bug wrt. use64bitint\n"; print "not ok 23\n"; } else { print "ok 23\n"; }