2 * rand.c: System.Security.Cryptography.RNGCryptoServiceProvider support
5 * Mark Crichton (crichton@gimp.org)
6 * Patrik Torstensson (p@rxc.se)
8 * (C) 2001 Ximian, Inc.
14 #include <sys/types.h>
19 #include <mono/metadata/object.h>
20 #include <mono/metadata/rand.h>
21 #include <mono/metadata/exception.h>
23 #if defined (PLATFORM_WIN32)
27 static int s_providerInitialized = 0;
\r
28 static HCRYPTPROV s_provider;
\r
30 static HCRYPTPROV GetProvider()
\r
32 if (s_providerInitialized == 1)
\r
35 if (!CryptAcquireContext (&s_provider, NULL, NULL, PROV_RSA_FULL, 0))
\r
37 if (GetLastError() != NTE_BAD_KEYSET)
\r
38 mono_raise_exception (mono_get_exception_execution_engine ("Failed to acquire crypt context"));
\r
40 // Generate a new keyset if needed
\r
41 if (!CryptAcquireContext (&s_provider, NULL, NULL, PROV_RSA_FULL, CRYPT_NEWKEYSET))
\r
42 mono_raise_exception (mono_get_exception_execution_engine ("Failed to acquire crypt context (new keyset)"));
\r
45 s_providerInitialized = 1;
\r
50 void ves_icall_System_Security_Cryptography_RNGCryptoServiceProvider_InternalGetBytes(MonoObject *self, MonoArray *arry)
55 len = mono_array_length (arry);
56 buf = mono_array_addr (arry, guchar, 0);
58 if (0 == CryptGenRandom (GetProvider(), len, buf))
59 mono_raise_exception (mono_get_exception_execution_engine ("Failed to generate random bytes from CryptAPI"));
\r
62 #elif defined (NAME_DEV_RANDOM) && defined (HAVE_CRYPT_RNG)
64 #ifndef NAME_DEV_URANDOM
65 #define NAME_DEV_URANDOM "/dev/urandom"
69 ves_icall_System_Security_Cryptography_RNGCryptoServiceProvider_InternalGetBytes (MonoObject *self, MonoArray *arry)
77 len = mono_array_length(arry);
78 buf = mono_array_addr(arry, guchar, 0);
80 file = open (NAME_DEV_URANDOM, O_RDONLY);
83 file = open (NAME_DEV_RANDOM, O_RDONLY);
86 g_warning ("Entropy problem! Can't open %s or %s", NAME_DEV_URANDOM, NAME_DEV_RANDOM);
88 mono_raise_exception (mono_get_exception_execution_engine ("Failed to open /dev/urandom or /dev/random device"));
\r
91 /* Read until the buffer is filled. This may block if using NAME_DEV_RANDOM. */
94 err = read(file, buf + count, len - count);
96 } while (err >= 0 && count < len);
99 g_warning("Entropy error! Error in read.");
100 mono_raise_exception (mono_get_exception_execution_engine ("Failed to read a random byte from /dev/urandom or /dev/random device"));
\r
108 void ves_icall_System_Security_Cryptography_RNGCryptoServiceProvider_InternalGetBytes(MonoObject *self, MonoArray *arry)
110 mono_raise_exception(mono_get_exception_not_implemented(NULL));
113 #endif /* OS definition */