3 * Windows rand support for Mono.
5 * Copyright 2016 Microsoft
6 * Licensed under the MIT license. See LICENSE file in the project root for full license information.
11 #include "mono-error.h"
12 #include "mono-error-internals.h"
13 #include "mono-rand.h"
18 // This implementation requires Windows 7 or newer.
20 #define BCRYPT_USE_SYSTEM_PREFERRED_RNG 0x00000002
21 const static char mono_rand_provider
[ ] = "BCryptGenRandom";
26 * Returns: True if random source is global, false if mono_rand_init can be called repeatedly to get randomness instances.
28 * Initializes entire RNG system. Must be called once per process before calling mono_rand_init.
38 * \param seed A string containing seed data
39 * \param seed_size Length of seed string
40 * Initializes an RNG client.
41 * \returns On success, a non-NULL handle which can be used to fetch random data from \c mono_rand_try_get_bytes. On failure, NULL.
44 mono_rand_init (const guchar
*seed
, gssize seed_size
)
46 // NULL will be interpreted as failure; return arbitrary nonzero pointer
47 return (gpointer
)mono_rand_provider
;
51 * mono_rand_try_get_bytes:
52 * \param handle A pointer to an RNG handle. Handle is set to NULL on failure.
53 * \param buffer A buffer into which to write random data.
54 * \param buffer_size Number of bytes to write into buffer.
55 * \param error Set on error.
56 * Extracts bytes from an RNG handle.
57 * \returns FALSE on failure and sets \p error, TRUE on success.
60 mono_rand_try_get_bytes (gpointer
*handle
, guchar
*buffer
, gssize buffer_size
, MonoError
*error
)
62 g_assert (buffer
|| !buffer_size
);
65 gpointer
const handle_value
= *handle
;
66 g_assert (handle_value
== 0 || handle_value
== mono_rand_provider
);
69 while (buffer_size
> 0) {
70 ULONG
const size
= (ULONG
)MIN (buffer_size
, ULONG_MAX
);
71 NTSTATUS
const status
= BCryptGenRandom (0, buffer
, size
, BCRYPT_USE_SYSTEM_PREFERRED_RNG
);
72 if (!BCRYPT_SUCCESS (status
)) {
73 mono_error_set_execution_engine (error
, "Failed to gen random bytes (%ld)", status
);
74 // failure, clear provider for future attempts
86 * \param handle An RNG handle.
87 * Releases an RNG handle.
90 mono_rand_close (gpointer handle
)
92 g_assert (handle
== 0 || handle
== mono_rand_provider
);
94 #endif /* HOST_WIN32 */