* 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> | ||||
|  | ||||
| 	* fhandler.h: Add comment. | ||||
|   | ||||
| @@ -743,6 +743,11 @@ class fhandler_dev_random: public fhandler_base | ||||
| protected: | ||||
|   int unit; | ||||
|   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: | ||||
|   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. | ||||
|  | ||||
| @@ -11,11 +11,15 @@ Cygwin license.  Please consult the file "CYGWIN_LICENSE" for | ||||
| details. */ | ||||
|  | ||||
| #include <errno.h> | ||||
| #include <limits.h> | ||||
| #include "winsup.h" | ||||
|  | ||||
| #define RANDOM   8 | ||||
| #define URANDOM  9 | ||||
|  | ||||
| #define PSEUDO_MULTIPLIER       (6364136223846793005LL) | ||||
| #define PSEUDO_SHIFTVAL         (21) | ||||
|  | ||||
| fhandler_dev_random::fhandler_dev_random (const char *name, int nunit) | ||||
|   : fhandler_base (FH_RANDOM, name), | ||||
|     unit(nunit), | ||||
| @@ -31,9 +35,76 @@ fhandler_dev_random::open (const char *, int flags, mode_t) | ||||
|   return 1; | ||||
| } | ||||
|  | ||||
| int | ||||
| fhandler_dev_random::write (const void *, size_t len) | ||||
| BOOL | ||||
| 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; | ||||
| } | ||||
|  | ||||
| @@ -42,22 +113,22 @@ fhandler_dev_random::read (void *ptr, size_t len) | ||||
| { | ||||
|   if (!len) | ||||
|     return 0; | ||||
|   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 )) | ||||
|   if (!ptr) | ||||
|     { | ||||
|       __seterrno (); | ||||
|       return -1; | ||||
|     } | ||||
|   if (!CryptGenRandom (crypt_prov, len, (BYTE *)ptr)) | ||||
|     { | ||||
|       __seterrno (); | ||||
|       set_errno (EINVAL); | ||||
|       return -1; | ||||
|     } | ||||
|  | ||||
|   if (crypt_gen_random (ptr, len)) | ||||
|     return len; | ||||
|   /* 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 | ||||
|      very high quality randomness. */ | ||||
|   if (unit == URANDOM) | ||||
|     return pseudo_read (ptr, len); | ||||
|  | ||||
|   __seterrno (); | ||||
|   return -1; | ||||
| } | ||||
|  | ||||
| off_t | ||||
|   | ||||
		Reference in New Issue
	
	Block a user