* autoload.cc (CryptAcquireContextW): Remove.

(CryptGenRandom): Remove.
	(CryptReleaseContext): Remove.
	(SystemFunction036): Define.  Add comment to explain that this is
	actually the RtlGenRandom function.
	* fhandler.h (class fhandler_dev_random): Drop crypt_prov member.
	(fhandler_dev_random::fhandler_dev_random): Define inline.
	(fhandler_dev_random::dup): Drop declaration.
	* fhandler_random.cc (fhandler_dev_random::fhandler_dev_random): Remove
	here.
	(fhandler_dev_random::crypt_gen_random): Use RtlGenRandom to drop
	dependency to old Crypto API.
	(fhandler_dev_random::read): Implement an enhanced version of reading
	random bytes from RtlGenRandom for the sake of a better /dev/random
	emulation.
	(fhandler_dev_random::close): Just return 0 since crypt_prov doesn't
	exisyt anymore.
	(fhandler_dev_random::dup): Drop entirely for the same reason.
This commit is contained in:
Corinna Vinschen 2013-10-15 14:00:37 +00:00
parent 45ec2b422e
commit 2cbd31fe26
4 changed files with 62 additions and 49 deletions

View File

@ -1,3 +1,24 @@
2013-10-15 Corinna Vinschen <corinna@vinschen.de>
* autoload.cc (CryptAcquireContextW): Remove.
(CryptGenRandom): Remove.
(CryptReleaseContext): Remove.
(SystemFunction036): Define. Add comment to explain that this is
actually the RtlGenRandom function.
* fhandler.h (class fhandler_dev_random): Drop crypt_prov member.
(fhandler_dev_random::fhandler_dev_random): Define inline.
(fhandler_dev_random::dup): Drop declaration.
* fhandler_random.cc (fhandler_dev_random::fhandler_dev_random): Remove
here.
(fhandler_dev_random::crypt_gen_random): Use RtlGenRandom to drop
dependency to old Crypto API.
(fhandler_dev_random::read): Implement an enhanced version of reading
random bytes from RtlGenRandom for the sake of a better /dev/random
emulation.
(fhandler_dev_random::close): Just return 0 since crypt_prov doesn't
exisyt anymore.
(fhandler_dev_random::dup): Drop entirely for the same reason.
2013-10-15 Corinna Vinschen <corinna@vinschen.de> 2013-10-15 Corinna Vinschen <corinna@vinschen.de>
* mmap.cc (mmap64): Convert pagesize from DWORD to size_t to avoid * mmap.cc (mmap64): Convert pagesize from DWORD to size_t to avoid

View File

@ -537,9 +537,6 @@ wsock_init ()
LoadDLLprime (ws2_32, _wsock_init, 0) LoadDLLprime (ws2_32, _wsock_init, 0)
LoadDLLfunc (CreateProcessAsUserW, 44, advapi32) LoadDLLfunc (CreateProcessAsUserW, 44, advapi32)
LoadDLLfunc (CryptAcquireContextW, 20, advapi32)
LoadDLLfunc (CryptGenRandom, 12, advapi32)
LoadDLLfunc (CryptReleaseContext, 8, advapi32)
LoadDLLfunc (DeregisterEventSource, 4, advapi32) LoadDLLfunc (DeregisterEventSource, 4, advapi32)
LoadDLLfunc (LogonUserW, 24, advapi32) LoadDLLfunc (LogonUserW, 24, advapi32)
LoadDLLfunc (LookupAccountNameW, 28, advapi32) LoadDLLfunc (LookupAccountNameW, 28, advapi32)
@ -563,6 +560,7 @@ LoadDLLfunc (RegQueryInfoKeyW, 48, advapi32)
LoadDLLfunc (RegQueryValueExW, 24, advapi32) LoadDLLfunc (RegQueryValueExW, 24, advapi32)
LoadDLLfunc (RegisterEventSourceW, 8, advapi32) LoadDLLfunc (RegisterEventSourceW, 8, advapi32)
LoadDLLfunc (ReportEventW, 36, advapi32) LoadDLLfunc (ReportEventW, 36, advapi32)
LoadDLLfunc (SystemFunction036, 8, advapi32) /* Aka "RtlGenRandom" */
LoadDLLfunc (DnsQuery_A, 24, dnsapi) LoadDLLfunc (DnsQuery_A, 24, dnsapi)
LoadDLLfunc (DnsRecordListFree, 8, dnsapi) LoadDLLfunc (DnsRecordListFree, 8, dnsapi)

View File

@ -1652,7 +1652,6 @@ class fhandler_dev_zero: public fhandler_base
class fhandler_dev_random: public fhandler_base class fhandler_dev_random: public fhandler_base
{ {
protected: protected:
HCRYPTPROV crypt_prov;
uint32_t pseudo; uint32_t pseudo;
off_t dummy_offset; off_t dummy_offset;
@ -1661,14 +1660,13 @@ class fhandler_dev_random: public fhandler_base
int pseudo_read (void *ptr, size_t len); int pseudo_read (void *ptr, size_t len);
public: public:
fhandler_dev_random ();
int open (int flags, mode_t mode = 0); int open (int flags, mode_t mode = 0);
ssize_t __stdcall write (const void *ptr, size_t len); ssize_t __stdcall write (const void *ptr, size_t len);
void __reg3 read (void *ptr, size_t& len); void __reg3 read (void *ptr, size_t& len);
off_t lseek (off_t offset, int whence); off_t lseek (off_t offset, int whence);
int close (); int close ();
int dup (fhandler_base *child, int);
fhandler_dev_random () : fhandler_base () {}
fhandler_dev_random (void *) {} fhandler_dev_random (void *) {}
void copyto (fhandler_base *x) void copyto (fhandler_base *x)

View File

@ -1,8 +1,7 @@
/* fhandler_random.cc: code to access /dev/random and /dev/urandom /* fhandler_random.cc: code to access /dev/random and /dev/urandom
Copyright 2000, 2001, 2002, 2003, 2004, 2005, 2007, 2009, 2011 Red Hat, Inc. Copyright 2000, 2001, 2002, 2003, 2004, 2005, 2007, 2009, 2011, 2013
Red Hat, Inc.
Written by Corinna Vinschen (vinschen@cygnus.com)
This file is part of Cygwin. This file is part of Cygwin.
@ -23,14 +22,12 @@ details. */
#define RANDOM 8 #define RANDOM 8
#define URANDOM 9 #define URANDOM 9
/* The system PRNG is reseeded after reading 128K bytes. */
#define RESEED_INTERVAL (128 * 1024)
#define PSEUDO_MULTIPLIER (6364136223846793005LL) #define PSEUDO_MULTIPLIER (6364136223846793005LL)
#define PSEUDO_SHIFTVAL (21) #define PSEUDO_SHIFTVAL (21)
fhandler_dev_random::fhandler_dev_random ()
: fhandler_base (), crypt_prov ((HCRYPTPROV) NULL)
{
}
int int
fhandler_dev_random::open (int flags, mode_t) fhandler_dev_random::open (int flags, mode_t)
{ {
@ -41,22 +38,18 @@ fhandler_dev_random::open (int flags, mode_t)
return 1; return 1;
} }
/* There's a bug in ntsecapi.h (Mingw as well as MSFT). SystemFunction036
is, in fact, a WINAPI function, but it's not defined as such. Therefore
we have to do it correctly here. */
#define RtlGenRandom SystemFunction036
extern "C" BOOLEAN WINAPI RtlGenRandom (PVOID, ULONG);
bool bool
fhandler_dev_random::crypt_gen_random (void *ptr, size_t len) fhandler_dev_random::crypt_gen_random (void *ptr, size_t len)
{ {
if (!crypt_prov if (!RtlGenRandom (ptr, len))
&& !CryptAcquireContextW (&crypt_prov, NULL, MS_DEF_PROV_W, PROV_RSA_FULL,
CRYPT_VERIFYCONTEXT | CRYPT_MACHINE_KEYSET)
&& !CryptAcquireContextW (&crypt_prov, NULL, MS_DEF_PROV_W, PROV_RSA_FULL,
CRYPT_VERIFYCONTEXT | CRYPT_MACHINE_KEYSET
| CRYPT_NEWKEYSET))
{ {
debug_printf ("%E = CryptAquireContext()"); debug_printf ("%E = RtlGenRandom()");
return false;
}
if (!CryptGenRandom (crypt_prov, len, (BYTE *)ptr))
{
debug_printf ("%E = CryptGenRandom()");
return false; return false;
} }
return true; return true;
@ -127,20 +120,35 @@ fhandler_dev_random::read (void *ptr, size_t& len)
return; return;
} }
if (crypt_gen_random (ptr, len)) /* /dev/random has to provide high quality random numbers. Therefore we
return; re-seed the system PRNG for each block of 512 bytes. This results in
sufficiently random sequences, comparable to the Linux /dev/random. */
/* If device is /dev/urandom, use pseudo number generator as fallback. if (dev () == FH_RANDOM)
Don't do this for /dev/random since it's intended for uses that need
very high quality randomness. */
if (dev () == FH_URANDOM)
{ {
len = pseudo_read (ptr, len); void *dummy = malloc (RESEED_INTERVAL);
return; if (!dummy)
{
__seterrno ();
len = (size_t) -1;
return;
}
for (size_t offset = 0; offset < len; offset += 512)
{
if (!crypt_gen_random (dummy, RESEED_INTERVAL) ||
!crypt_gen_random ((PBYTE) ptr + offset, len - offset))
{
__seterrno ();
len = (size_t) -1;
break;
}
}
free (dummy);
} }
__seterrno (); /* If device is /dev/urandom, just use system RNG as is, with our own
len = (size_t) -1; PRNG as fallback. */
else if (!crypt_gen_random (ptr, len))
len = pseudo_read (ptr, len);
} }
off_t off_t
@ -174,17 +182,5 @@ fhandler_dev_random::lseek (off_t off, int whence)
int int
fhandler_dev_random::close () fhandler_dev_random::close ()
{ {
if (!have_execed && crypt_prov)
while (!CryptReleaseContext (crypt_prov, 0)
&& GetLastError () == ERROR_BUSY)
Sleep (10);
return 0;
}
int
fhandler_dev_random::dup (fhandler_base *child, int)
{
fhandler_dev_random *fhr = (fhandler_dev_random *) child;
fhr->crypt_prov = (HCRYPTPROV)NULL;
return 0; return 0;
} }