X-Git-Url: http://wien.tomnetworks.com/gitweb/?a=blobdiff_plain;f=mono%2Futils%2Fmono-rand.c;h=fc6b61f2c4f35e07cb76b816c269411391dba48c;hb=010fcfb9ecfef1654b415dbb909a01148a89e827;hp=d1e4bb2c496963979c87d0fbe3cffa9a006e5a9d;hpb=1c6b82896fd4f2079e76af7acd784d516189b05c;p=mono.git diff --git a/mono/utils/mono-rand.c b/mono/utils/mono-rand.c index d1e4bb2c496..fc6b61f2c4f 100644 --- a/mono/utils/mono-rand.c +++ b/mono/utils/mono-rand.c @@ -1,5 +1,5 @@ -/* - * mono-rand.c: +/** + * \file * * Authors: * Mark Crichton (crichton@gimp.org) @@ -10,9 +10,9 @@ * Copyright 2001-2003 Ximian, Inc (http://www.ximian.com) * Copyright 2004-2009 Novell, Inc (http://www.novell.com) * Copyright 2001 Xamarin, Inc (http://www.novell.com) + * Licensed under the MIT license. See LICENSE file in the project root for full license information. */ - #include #include @@ -25,126 +25,8 @@ #include "metadata/object.h" #ifdef HOST_WIN32 - -#include -#include - -#ifndef PROV_INTEL_SEC -#define PROV_INTEL_SEC 22 -#endif -#ifndef CRYPT_VERIFY_CONTEXT -#define CRYPT_VERIFY_CONTEXT 0xF0000000 -#endif - -/** - * mono_rand_open: - * - * Returns: True if random source is global, false if mono_rand_init can be called repeatedly to get randomness instances. - * - * Initializes entire RNG system. Must be called once per process before calling mono_rand_init. - */ -gboolean -mono_rand_open (void) -{ - return FALSE; -} - -/** - * mono_rand_init: - * @seed: A string containing seed data - * @seed_size: Length of seed string - * - * Returns: On success, a non-NULL handle which can be used to fetch random data from mono_rand_try_get_bytes. On failure, NULL. - * - * Initializes an RNG client. - */ -gpointer -mono_rand_init (guchar *seed, gint seed_size) -{ - HCRYPTPROV provider = 0; - - /* There is no need to create a container for just random data, - * so we can use CRYPT_VERIFY_CONTEXT (one call) see: - * http://blogs.msdn.com/dangriff/archive/2003/11/19/51709.aspx */ - - /* We first try to use the Intel PIII RNG if drivers are present */ - if (!CryptAcquireContext (&provider, NULL, NULL, PROV_INTEL_SEC, CRYPT_VERIFY_CONTEXT)) { - /* not a PIII or no drivers available, use default RSA CSP */ - if (!CryptAcquireContext (&provider, NULL, NULL, PROV_RSA_FULL, CRYPT_VERIFY_CONTEXT)) { - /* exception will be thrown in managed code */ - provider = 0; - } - } - - /* seed the CSP with the supplied buffer (if present) */ - if (provider != 0 && seed) { - /* the call we replace the seed with random - this isn't what is - * expected from the class library user */ - guchar *data = g_malloc (seed_size); - if (data) { - memcpy (data, seed, seed_size); - /* add seeding material to the RNG */ - CryptGenRandom (provider, seed_size, data); - /* zeroize and free */ - memset (data, 0, seed_size); - g_free (data); - } - } - - return (gpointer) provider; -} - -/** - * mono_rand_try_get_bytes: - * @handle: A pointer to an RNG handle. Handle is set to NULL on failure. - * @buffer: A buffer into which to write random data. - * @buffer_size: Number of bytes to write into buffer. - * @error: Set on error. - * - * Returns: FALSE on failure and sets @error, TRUE on success. - * - * Extracts bytes from an RNG handle. - */ -gboolean -mono_rand_try_get_bytes (gpointer *handle, guchar *buffer, gint buffer_size, MonoError *error) -{ - HCRYPTPROV provider; - - mono_error_init (error); - - g_assert (handle); - provider = (HCRYPTPROV) *handle; - - if (!CryptGenRandom (provider, buffer_size, buffer)) { - CryptReleaseContext (provider, 0); - /* we may have lost our context with CryptoAPI, but all hope isn't lost yet! */ - provider = (HCRYPTPROV) mono_rand_init (NULL, 0); - if (!CryptGenRandom (provider, buffer_size, buffer)) { - /* exception will be thrown in managed code */ - CryptReleaseContext (provider, 0); - *handle = 0; - mono_error_set_execution_engine (error, "Failed to gen random bytes (%d)", GetLastError ()); - return FALSE; - } - } - return TRUE; -} - -/** - * mono_rand_close: - * @handle: An RNG handle. - * @buffer: A buffer into which to write random data. - * @buffer_size: Number of bytes to write into buffer. - * - * Releases an RNG handle. - */ -void -mono_rand_close (gpointer handle) -{ - CryptReleaseContext ((HCRYPTPROV) handle, 0); -} - -#elif defined (HAVE_SYS_UN_H) && !defined(__native_client__) +// Windows specific implementation in mono-rand-windows.c +#elif defined (HAVE_SYS_UN_H) #include #include @@ -164,27 +46,27 @@ static void get_entropy_from_egd (const char *path, guchar *buffer, int buffer_size, MonoError *error) { struct sockaddr_un egd_addr; - gint file; + gint socket_fd; gint ret; guint offset = 0; int err = 0; - mono_error_init (error); + error_init (error); - file = socket (PF_UNIX, SOCK_STREAM, 0); - if (file < 0) { + socket_fd = socket (PF_UNIX, SOCK_STREAM, 0); + if (socket_fd < 0) { ret = -1; err = errno; } else { egd_addr.sun_family = AF_UNIX; - strncpy (egd_addr.sun_path, path, sizeof (egd_addr.sun_path) - 1); + memcpy (egd_addr.sun_path, path, sizeof (egd_addr.sun_path) - 1); egd_addr.sun_path [sizeof (egd_addr.sun_path) - 1] = '\0'; - ret = connect (file, (struct sockaddr*) &egd_addr, sizeof (egd_addr)); + ret = connect (socket_fd, (struct sockaddr*) &egd_addr, sizeof (egd_addr)); err = errno; } if (ret == -1) { - if (file >= 0) - close (file); + if (socket_fd >= 0) + close (socket_fd); g_warning ("Entropy problem! Can't create or connect to egd socket %s", path); mono_error_set_execution_engine (error, "Failed to open egd socket %s: %s", path, strerror (err)); return; @@ -198,14 +80,14 @@ get_entropy_from_egd (const char *path, guchar *buffer, int buffer_size, MonoErr request [0] = 2; request [1] = buffer_size < 255 ? buffer_size : 255; while (count < 2) { - int sent = write (file, request + count, 2 - count); + int sent = write (socket_fd, request + count, 2 - count); err = errno; if (sent >= 0) { count += sent; } else if (err == EINTR) { continue; } else { - close (file); + close (socket_fd); g_warning ("Send egd request failed %d", err); mono_error_set_execution_engine (error, "Failed to send request to egd socket: %s", strerror (err)); return; @@ -215,7 +97,7 @@ get_entropy_from_egd (const char *path, guchar *buffer, int buffer_size, MonoErr count = 0; while (count != request [1]) { int received; - received = read (file, buffer + offset, request [1] - count); + received = read (socket_fd, buffer + offset, request [1] - count); err = errno; if (received > 0) { count += received; @@ -223,7 +105,7 @@ get_entropy_from_egd (const char *path, guchar *buffer, int buffer_size, MonoErr } else if (received < 0 && err == EINTR) { continue; } else { - close (file); + close (socket_fd); g_warning ("Receive egd request failed %d", err); mono_error_set_execution_engine (error, "Failed to get response from egd socket: %s", strerror(err)); return; @@ -233,7 +115,7 @@ get_entropy_from_egd (const char *path, guchar *buffer, int buffer_size, MonoErr buffer_size -= request [1]; } - close (file); + close (socket_fd); } gboolean @@ -254,7 +136,7 @@ mono_rand_open (void) file = open (NAME_DEV_RANDOM, O_RDONLY); #endif if (file < 0) - use_egd = g_getenv("MONO_EGD_SOCKET") != NULL; + use_egd = g_hasenv ("MONO_EGD_SOCKET"); status = 2; @@ -273,16 +155,17 @@ mono_rand_try_get_bytes (gpointer *handle, guchar *buffer, gint buffer_size, Mon { g_assert (handle); - mono_error_init (error); + error_init (error); if (use_egd) { - const char *socket_path = g_getenv ("MONO_EGD_SOCKET"); + char *socket_path = g_getenv ("MONO_EGD_SOCKET"); /* exception will be thrown in managed code */ if (socket_path == NULL) { *handle = NULL; return FALSE; } get_entropy_from_egd (socket_path, buffer, buffer_size, error); + g_free (socket_path); } else { /* Read until the buffer is filled. This may block if using NAME_DEV_RANDOM. */ gint count = 0; @@ -342,7 +225,7 @@ mono_rand_try_get_bytes (gpointer *handle, guchar *buffer, gint buffer_size, Mon { gint count = 0; - mono_error_init (error); + error_init (error); do { if (buffer_size - count >= sizeof (gint32) && RAND_MAX >= 0xFFFFFFFF) { @@ -372,14 +255,12 @@ mono_rand_close (gpointer provider) /** * mono_rand_try_get_uint32: - * @handle: A pointer to an RNG handle. Handle is set to NULL on failure. - * @val: A pointer to a 32-bit unsigned int, to which the result will be written. - * @min: Result will be greater than or equal to this value. - * @max: Result will be less than or equal to this value. - * - * Returns: FALSE on failure, TRUE on success. - * + * \param handle A pointer to an RNG handle. Handle is set to NULL on failure. + * \param val A pointer to a 32-bit unsigned int, to which the result will be written. + * \param min Result will be greater than or equal to this value. + * \param max Result will be less than or equal to this value. * Extracts one 32-bit unsigned int from an RNG handle. + * \returns FALSE on failure, TRUE on success. */ gboolean mono_rand_try_get_uint32 (gpointer *handle, guint32 *val, guint32 min, guint32 max, MonoError *error)