* Sebastien Pouliot (sebastien@ximian.com)
*
* (C) 2001 Ximian, Inc.
- * (C) 2004 Novell (http://www.novell.com)
+ * Copyright (C) 2004-2005 Novell, Inc (http://www.novell.com)
*/
#include <config.h>
#if defined (PLATFORM_WIN32)
-#include <WinCrypt.h>
+#include <windows.h>
+#include <wincrypt.h>
#ifndef PROV_INTEL_SEC
#define PROV_INTEL_SEC 22
#define CRYPT_VERIFY_CONTEXT 0xF0000000
#endif
+MonoBoolean
+ves_icall_System_Security_Cryptography_RNGCryptoServiceProvider_RngOpen (void)
+{
+ /* FALSE == Local (instance) handle for randomness */
+ return FALSE;
+}
+
gpointer
ves_icall_System_Security_Cryptography_RNGCryptoServiceProvider_RngInitialize (MonoArray *seed)
{
if (!CryptGenRandom (provider, len, buf)) {
CryptReleaseContext (provider, 0);
/* we may have lost our context with CryptoAPI, but all hope isn't lost yet! */
- provider = ves_icall_System_Security_Cryptography_RNGCryptoServiceProvider_RngInitialize (NULL);
+ provider = (HCRYPTPROV) ves_icall_System_Security_Cryptography_RNGCryptoServiceProvider_RngInitialize (NULL);
if (!CryptGenRandom (provider, len, buf)) {
CryptReleaseContext (provider, 0);
provider = 0;
/* exception will be thrown in managed code */
}
- }
+ }
+ return (gpointer) provider;
}
void
#endif
static gboolean egd = FALSE;
+static gint file = -1;
-gpointer
-ves_icall_System_Security_Cryptography_RNGCryptoServiceProvider_RngInitialize (MonoArray *seed)
+MonoBoolean
+ves_icall_System_Security_Cryptography_RNGCryptoServiceProvider_RngOpen (void)
{
- gint file = -1;
-
- if (egd)
- return -1;
+ if (egd || (file >= 0))
+ return TRUE;
#if defined (NAME_DEV_URANDOM)
file = open (NAME_DEV_URANDOM, O_RDONLY);
if (file < 0) {
const char *socket_path = g_getenv("MONO_EGD_SOCKET");
egd = (socket_path != NULL);
- return -1;
}
+ /* TRUE == Global handle for randomness */
+ return TRUE;
+}
+
+gpointer
+ves_icall_System_Security_Cryptography_RNGCryptoServiceProvider_RngInitialize (MonoArray *seed)
+{
/* if required exception will be thrown in managed code */
- return ((file < 0) ? NULL : (gpointer) file);
+ return ((!egd && (file < 0)) ? NULL : GINT_TO_POINTER (file));
}
gpointer
ves_icall_System_Security_Cryptography_RNGCryptoServiceProvider_RngGetBytes (gpointer handle, MonoArray *arry)
{
- gint file = (gint) handle;
+ gint file = GPOINTER_TO_INT (handle);
guint32 len = mono_array_length (arry);
guchar *buf = mono_array_addr (arry, guchar, 0);
if (egd) {
- const char *socket_path = getenv ("MONO_EGD_SOCKET");
+ const char *socket_path = g_getenv ("MONO_EGD_SOCKET");
/* exception will be thrown in managed code */
if (socket_path == NULL)
return NULL;
get_entropy_from_server (socket_path, mono_array_addr (arry, guchar, 0), mono_array_length (arry));
- return -1;
- }
- else {
+ return (gpointer) -1;
+ } else {
/* Read until the buffer is filled. This may block if using NAME_DEV_RANDOM. */
gint count = 0;
gint err;
do {
err = read (file, buf + count, len - count);
+ if (err < 0) {
+ if (errno == EINTR)
+ continue;
+ break;
+ }
count += err;
- } while (err >= 0 && count < len);
+ } while (count < len);
if (err < 0) {
g_warning("Entropy error! Error in read (%s).", strerror (errno));
void
ves_icall_System_Security_Cryptography_RNGCryptoServiceProvider_RngClose (gpointer handle)
{
- if (!egd)
- close ((gint) handle);
}
#endif /* OS definition */