* fhandler.h (class fhandler_dev_random): Add members for managing
pseudo randomness.
        * fhandler_random.cc: Rearrange. Use pseudo random number generator
        as entropy source if system entropy isn't available and if device is
        used as /dev/urandom. Allow initializing device by calling write().
			
			
This commit is contained in:
		| @@ -1,3 +1,11 @@ | |||||||
|  | Mon Jul 24 13:26:00 2000  Corinna Vinschen <corinna@vinschen.de> | ||||||
|  |  | ||||||
|  | 	* fhandler.h (class fhandler_dev_random): Add members for managing | ||||||
|  | 	pseudo randomness. | ||||||
|  | 	* fhandler_random.cc: Rearrange. Use pseudo random number generator | ||||||
|  | 	as entropy source if system entropy isn't available and if device is | ||||||
|  | 	used as /dev/urandom. Allow initializing device by calling write(). | ||||||
|  |  | ||||||
| Sun Jul 23 23:11:00 2000  Corinna Vinschen <corinna@vinschen.de> | Sun Jul 23 23:11:00 2000  Corinna Vinschen <corinna@vinschen.de> | ||||||
|  |  | ||||||
| 	* fhandler.h: Add comment. | 	* fhandler.h: Add comment. | ||||||
|   | |||||||
| @@ -743,6 +743,11 @@ class fhandler_dev_random: public fhandler_base | |||||||
| protected: | protected: | ||||||
|   int unit; |   int unit; | ||||||
|   HCRYPTPROV crypt_prov; |   HCRYPTPROV crypt_prov; | ||||||
|  |   long pseudo; | ||||||
|  |  | ||||||
|  |   BOOL crypt_gen_random (void *ptr, size_t len); | ||||||
|  |   int pseudo_write (const void *ptr, size_t len); | ||||||
|  |   int pseudo_read (void *ptr, size_t len); | ||||||
|  |  | ||||||
| public: | public: | ||||||
|   fhandler_dev_random (const char *name, int unit); |   fhandler_dev_random (const char *name, int unit); | ||||||
|   | |||||||
| @@ -1,4 +1,4 @@ | |||||||
| /* fhandler_dev_random.cc: code to access /dev/random | /* fhandler_dev_random.cc: code to access /dev/random and /dev/urandom | ||||||
|  |  | ||||||
|    Copyright 2000 Cygnus Solutions. |    Copyright 2000 Cygnus Solutions. | ||||||
|  |  | ||||||
| @@ -11,11 +11,15 @@ Cygwin license.  Please consult the file "CYGWIN_LICENSE" for | |||||||
| details. */ | details. */ | ||||||
|  |  | ||||||
| #include <errno.h> | #include <errno.h> | ||||||
|  | #include <limits.h> | ||||||
| #include "winsup.h" | #include "winsup.h" | ||||||
|  |  | ||||||
| #define RANDOM   8 | #define RANDOM   8 | ||||||
| #define URANDOM  9 | #define URANDOM  9 | ||||||
|  |  | ||||||
|  | #define PSEUDO_MULTIPLIER       (6364136223846793005LL) | ||||||
|  | #define PSEUDO_SHIFTVAL         (21) | ||||||
|  |  | ||||||
| fhandler_dev_random::fhandler_dev_random (const char *name, int nunit) | fhandler_dev_random::fhandler_dev_random (const char *name, int nunit) | ||||||
|   : fhandler_base (FH_RANDOM, name), |   : fhandler_base (FH_RANDOM, name), | ||||||
|     unit(nunit), |     unit(nunit), | ||||||
| @@ -31,9 +35,76 @@ fhandler_dev_random::open (const char *, int flags, mode_t) | |||||||
|   return 1; |   return 1; | ||||||
| } | } | ||||||
|  |  | ||||||
| int | BOOL | ||||||
| fhandler_dev_random::write (const void *, size_t len) | fhandler_dev_random::crypt_gen_random (void *ptr, size_t len) | ||||||
| { | { | ||||||
|  |   if (!crypt_prov | ||||||
|  |       && !CryptAcquireContext (&crypt_prov, NULL, MS_DEF_PROV, PROV_RSA_FULL, | ||||||
|  |                                CRYPT_VERIFYCONTEXT | CRYPT_MACHINE_KEYSET) | ||||||
|  |       && !CryptAcquireContext (&crypt_prov, NULL, MS_DEF_PROV, PROV_RSA_FULL, | ||||||
|  |                                CRYPT_VERIFYCONTEXT | CRYPT_MACHINE_KEYSET | ||||||
|  |                                | CRYPT_NEWKEYSET)) | ||||||
|  |     { | ||||||
|  |       debug_printf ("%E = CryptAquireContext()"); | ||||||
|  |       return FALSE; | ||||||
|  |     } | ||||||
|  |   if (!CryptGenRandom (crypt_prov, len, (BYTE *)ptr)) | ||||||
|  |     { | ||||||
|  |       debug_printf ("%E = CryptGenRandom()"); | ||||||
|  |       return FALSE; | ||||||
|  |     } | ||||||
|  |   return TRUE; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | int | ||||||
|  | fhandler_dev_random::pseudo_write (const void *ptr, size_t len) | ||||||
|  | { | ||||||
|  |   /* Use buffer to mess up the pseudo random number generator. */ | ||||||
|  |   for (size_t i = 0; i < len; ++i) | ||||||
|  |     pseudo = (pseudo + ((unsigned char *)ptr)[i]) * PSEUDO_MULTIPLIER + 1; | ||||||
|  |   return len; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | int | ||||||
|  | fhandler_dev_random::write (const void *ptr, size_t len) | ||||||
|  | { | ||||||
|  |   if (!len) | ||||||
|  |     return 0; | ||||||
|  |   if (!ptr) | ||||||
|  |     { | ||||||
|  |       set_errno (EINVAL); | ||||||
|  |       return -1; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |   /* Limit len to a value <= 512 since we don't want to overact. | ||||||
|  |      Copy to local buffer because CryptGenRandom violates const. */ | ||||||
|  |   unsigned char buf[512]; | ||||||
|  |   size_t limited_len = len <= 512 ? len : 512; | ||||||
|  |   memcpy (buf, ptr, limited_len); | ||||||
|  |  | ||||||
|  |   /* Mess up system entropy source. Return error if device is /dev/random. */ | ||||||
|  |   if (!crypt_gen_random (buf, limited_len) && unit == RANDOM) | ||||||
|  |     { | ||||||
|  |       __seterrno (); | ||||||
|  |       return -1; | ||||||
|  |     } | ||||||
|  |   /* Mess up the pseudo random number generator. */ | ||||||
|  |   pseudo_write (buf, limited_len); | ||||||
|  |   return len; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | int | ||||||
|  | fhandler_dev_random::pseudo_read (void *ptr, size_t len) | ||||||
|  | { | ||||||
|  |   /* Use pseudo random number generator as fallback entropy source. | ||||||
|  |      This multiplier was obtained from Knuth, D.E., "The Art of | ||||||
|  |      Computer Programming," Vol 2, Seminumerical Algorithms, Third | ||||||
|  |      Edition, Addison-Wesley, 1998, p. 106 (line 26) & p. 108 */ | ||||||
|  |   for (size_t i = 0; i < len; ++i) | ||||||
|  |     { | ||||||
|  |       pseudo = pseudo * PSEUDO_MULTIPLIER + 1; | ||||||
|  |       ((unsigned char *)ptr)[i] = (pseudo >> PSEUDO_SHIFTVAL) & UCHAR_MAX; | ||||||
|  |     } | ||||||
|   return len; |   return len; | ||||||
| } | } | ||||||
|  |  | ||||||
| @@ -42,22 +113,22 @@ fhandler_dev_random::read (void *ptr, size_t len) | |||||||
| { | { | ||||||
|   if (!len) |   if (!len) | ||||||
|     return 0; |     return 0; | ||||||
|   if (!crypt_prov |   if (!ptr) | ||||||
|       && !CryptAcquireContext (&crypt_prov, NULL, MS_DEF_PROV, PROV_RSA_FULL, |  | ||||||
|                                CRYPT_VERIFYCONTEXT | CRYPT_MACHINE_KEYSET) |  | ||||||
|       && !CryptAcquireContext (&crypt_prov, NULL, MS_DEF_PROV, PROV_RSA_FULL, |  | ||||||
|                                CRYPT_VERIFYCONTEXT | CRYPT_MACHINE_KEYSET |  | ||||||
|                                | CRYPT_NEWKEYSET )) |  | ||||||
|     { |     { | ||||||
|       __seterrno (); |       set_errno (EINVAL); | ||||||
|       return -1; |       return -1; | ||||||
|     } |     } | ||||||
|   if (!CryptGenRandom (crypt_prov, len, (BYTE *)ptr)) |  | ||||||
|     { |   if (crypt_gen_random (ptr, len)) | ||||||
|       __seterrno (); |     return len; | ||||||
|       return -1; |   /* If device is /dev/urandom, use pseudo number generator as fallback. | ||||||
|     } |      Don't do this for /dev/random since it's intended for uses that need | ||||||
|   return len; |      very high quality randomness. */ | ||||||
|  |   if (unit == URANDOM) | ||||||
|  |     return pseudo_read (ptr, len); | ||||||
|  |  | ||||||
|  |   __seterrno (); | ||||||
|  |   return -1; | ||||||
| } | } | ||||||
|  |  | ||||||
| off_t | off_t | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user