|
| 1 | +# Hardware Random Number Generator (hRng) |
| 2 | + |
| 3 | +The `/dev/urandom/` of Windows. |
| 4 | + |
| 5 | +--- |
| 6 | + |
| 7 | +<details> |
| 8 | +<summary>Outdated documentation for v1.0.0 - hRng.c</summary> |
| 9 | + |
| 10 | +## hRng.c |
| 11 | + |
| 12 | +Implements a hardware random number generator using the RDRAND instruction (if supported by the CPU). |
| 13 | + |
| 14 | +### Key Function |
| 15 | +- `int read_hwrng(unsigned char* buffer, int size)` |
| 16 | + - Fills `buffer` with `size` random bytes from the hardware RNG. |
| 17 | + - Returns 1 on success, 0 if RDRAND is not supported or fails. |
| 18 | + - Exported for use by Python via ctypes. |
| 19 | + |
| 20 | +### Notes |
| 21 | +- Checks for RDRAND support using CPUID. |
| 22 | +- Used by `pyCTools.hwrng`. |
| 23 | +</details> |
| 24 | + |
| 25 | +--- |
| 26 | + |
| 27 | +## Overview |
| 28 | + |
| 29 | +The Hardware Random Number Generator (hRng) is a high-security random number generation library designed for Windows systems. It provides cryptographically secure random numbers by combining multiple entropy sources with hardware-based random number generation when available. |
| 30 | + |
| 31 | +## Key Features |
| 32 | + |
| 33 | +- Hardware-accelerated random number generation using Intel RDRAND instruction (when available) |
| 34 | +- Multiple entropy sources for enhanced security: |
| 35 | + - CPU-specific entropy (RDTSC, CPUID) |
| 36 | + - System performance metrics (timing, memory usage) |
| 37 | + - Process memory information |
| 38 | + - Disk space statistics |
| 39 | + - Network adapter and TCP statistics |
| 40 | + - Battery and power status information |
| 41 | +- Secure entropy mixing using SHA-256 via Windows BCrypt API |
| 42 | +- Thread-safe operation with proper synchronization |
| 43 | +- Configurable complexity levels for enhanced security |
| 44 | +- Fallback mechanisms when hardware RNG is unavailable |
| 45 | + |
| 46 | +## API Reference |
| 47 | + |
| 48 | +### `int test_rng_available(void)` |
| 49 | +Detects if the CPU supports the RDRAND instruction. |
| 50 | + |
| 51 | +**Returns:** |
| 52 | +- `1` if RDRAND is supported |
| 53 | +- `0` if RDRAND is not supported |
| 54 | + |
| 55 | +### `int test_threading_available(void)` |
| 56 | +Checks if threading primitives are initialized. |
| 57 | + |
| 58 | +**Returns:** |
| 59 | +- `1` if threading primitives are initialized |
| 60 | +- `0` otherwise |
| 61 | + |
| 62 | +### `int maxrng(unsigned char* buffer, const int size)` |
| 63 | +The primary RNG function that combines multiple entropy sources with basic complexity. |
| 64 | + |
| 65 | +**Parameters:** |
| 66 | +- `buffer`: Pointer to the buffer to fill with random bytes |
| 67 | +- `size`: Number of bytes to generate |
| 68 | + |
| 69 | +**Returns:** |
| 70 | +- `1` on success |
| 71 | +- `0` on failure |
| 72 | + |
| 73 | +### `void maxrng_init(void)` |
| 74 | +Initializes threading primitives for thread-safe operation. |
| 75 | +This function must be called before using the thread-safe RNG functions. |
| 76 | + |
| 77 | +If not called, the thread-safe RNG functions will not work correctly (crashing with invalid pointer errors). |
| 78 | + |
| 79 | +> `test_threading_available` will always return `0` if this function has not been called. |
| 80 | +
|
| 81 | +**Returns:** |
| 82 | +- None |
| 83 | + |
| 84 | +### `int maxrng_threadsafe(unsigned char* buffer, const int size)` |
| 85 | +Thread-safe wrapper for the RNG function. |
| 86 | + |
| 87 | +**Parameters:** |
| 88 | +- `buffer`: Pointer to the buffer to fill with random bytes |
| 89 | +- `size`: Number of bytes to generate |
| 90 | + |
| 91 | +**Returns:** |
| 92 | +- `1` on success |
| 93 | +- `0` on failure |
| 94 | + |
| 95 | +### `int maxrng_ultra(unsigned char* buffer, const int size, int complexity)` |
| 96 | +Enhanced random number generation with configurable complexity level. |
| 97 | + |
| 98 | +**Parameters:** |
| 99 | +- `buffer`: Pointer to the buffer to fill with random bytes |
| 100 | +- `size`: Number of bytes to generate |
| 101 | +- `complexity`: Level of entropy gathering intensity (1-10): |
| 102 | + - Higher values increase the number of entropy gathering rounds |
| 103 | + - Values are automatically clamped between 1 and 10 |
| 104 | + |
| 105 | +**Returns:** |
| 106 | +- `1` on success |
| 107 | +- `0` on failure |
| 108 | + |
| 109 | +## Usage Examples |
| 110 | + |
| 111 | +> [!IMPORTANT] |
| 112 | +> The following examples have not been tested in `C` - but the DLL worked in `Python` so minor tweaks should fix any issues in the provided examples. |
| 113 | +
|
| 114 | +### Basic Usage |
| 115 | + |
| 116 | +```c |
| 117 | +#include <stdio.h> |
| 118 | +#include <windows.h> |
| 119 | + |
| 120 | +// Import the DLL functions |
| 121 | +typedef int (*MaxRNG_Func)(unsigned char*, int); |
| 122 | +typedef int (*RngAvailable_Func)(void); |
| 123 | + |
| 124 | +int main() { |
| 125 | + // Load the DLL |
| 126 | + HMODULE hRngDll = LoadLibrary("hRng.dll"); |
| 127 | + if (!hRngDll) { |
| 128 | + printf("Failed to load hRng.dll\n"); |
| 129 | + return 1; |
| 130 | + } |
| 131 | + |
| 132 | + // Get function pointers |
| 133 | + MaxRNG_Func rng = (MaxRNG_Func)GetProcAddress(hRngDll, "maxrng"); |
| 134 | + RngAvailable_Func rngAvailable = (RngAvailable_Func)GetProcAddress(hRngDll, "test_rng_available"); |
| 135 | + |
| 136 | + if (!rng || !rngAvailable) { |
| 137 | + printf("Failed to get function addresses\n"); |
| 138 | + FreeLibrary(hRngDll); |
| 139 | + return 1; |
| 140 | + } |
| 141 | + |
| 142 | + // Check if hardware RNG is available |
| 143 | + printf("Hardware RNG available: %s\n", rngAvailable() ? "Yes" : "No"); |
| 144 | + |
| 145 | + // Generate random bytes |
| 146 | + unsigned char buffer[32] = {0}; |
| 147 | + if (rng(buffer, sizeof(buffer))) { |
| 148 | + printf("Random bytes generated successfully:\n"); |
| 149 | + for (int i = 0; i < sizeof(buffer); i++) { |
| 150 | + printf("%02X ", buffer[i]); |
| 151 | + } |
| 152 | + printf("\n"); |
| 153 | + } else { |
| 154 | + printf("Failed to generate random bytes\n"); |
| 155 | + } |
| 156 | + |
| 157 | + FreeLibrary(hRngDll); |
| 158 | + return 0; |
| 159 | +} |
| 160 | +``` |
| 161 | +
|
| 162 | +### Thread-Safe Usage |
| 163 | +
|
| 164 | +```c |
| 165 | +#include <windows.h> |
| 166 | +#include <stdio.h> |
| 167 | +
|
| 168 | +// Import the DLL functions |
| 169 | +typedef void (*Init_Func)(void); |
| 170 | +typedef int (*ThreadSafe_RNG_Func)(unsigned char*, int); |
| 171 | +
|
| 172 | +DWORD WINAPI ThreadFunc(LPVOID lpParam) { |
| 173 | + ThreadSafe_RNG_Func rng = (ThreadSafe_RNG_Func)lpParam; |
| 174 | + |
| 175 | + unsigned char buffer[16] = {0}; |
| 176 | + int result = rng(buffer, sizeof(buffer)); |
| 177 | + |
| 178 | + // Print thread ID and result |
| 179 | + printf("Thread %lu: %s\n", GetCurrentThreadId(), |
| 180 | + result ? "Success" : "Failed"); |
| 181 | + |
| 182 | + return 0; |
| 183 | +} |
| 184 | +
|
| 185 | +int main() { |
| 186 | + HMODULE hRngDll = LoadLibrary("hRng.dll"); |
| 187 | + if (!hRngDll) { |
| 188 | + printf("Failed to load hRng.dll\n"); |
| 189 | + return 1; |
| 190 | + } |
| 191 | + |
| 192 | + Init_Func init = (Init_Func)GetProcAddress(hRngDll, "maxrng_init"); |
| 193 | + ThreadSafe_RNG_Func threadSafeRng = |
| 194 | + (ThreadSafe_RNG_Func)GetProcAddress(hRngDll, "maxrng_threadsafe"); |
| 195 | + |
| 196 | + if (!init || !threadSafeRng) { |
| 197 | + printf("Failed to get function addresses\n"); |
| 198 | + FreeLibrary(hRngDll); |
| 199 | + return 1; |
| 200 | + } |
| 201 | + |
| 202 | + // Initialize threading primitives |
| 203 | + init(); |
| 204 | + |
| 205 | + // Create multiple threads to test thread safety |
| 206 | + HANDLE threads[5]; |
| 207 | + for (int i = 0; i < 5; i++) { |
| 208 | + threads[i] = CreateThread(NULL, 0, ThreadFunc, |
| 209 | + (LPVOID)threadSafeRng, 0, NULL); |
| 210 | + } |
| 211 | + |
| 212 | + // Wait for all threads to complete |
| 213 | + WaitForMultipleObjects(5, threads, TRUE, INFINITE); |
| 214 | + |
| 215 | + for (int i = 0; i < 5; i++) { |
| 216 | + CloseHandle(threads[i]); |
| 217 | + } |
| 218 | + |
| 219 | + FreeLibrary(hRngDll); |
| 220 | + return 0; |
| 221 | +} |
| 222 | +``` |
| 223 | + |
| 224 | +### Using Ultra Mode for Maximum Security |
| 225 | + |
| 226 | +```c |
| 227 | +#include <stdio.h> |
| 228 | +#include <windows.h> |
| 229 | + |
| 230 | +// Import the DLL function |
| 231 | +typedef int (*MaxRNG_Ultra_Func)(unsigned char*, int, int); |
| 232 | + |
| 233 | +int main() { |
| 234 | + HMODULE hRngDll = LoadLibrary("hRng.dll"); |
| 235 | + if (!hRngDll) { |
| 236 | + printf("Failed to load hRng.dll\n"); |
| 237 | + return 1; |
| 238 | + } |
| 239 | + |
| 240 | + MaxRNG_Ultra_Func ultraRng = |
| 241 | + (MaxRNG_Ultra_Func)GetProcAddress(hRngDll, "maxrng_ultra"); |
| 242 | + |
| 243 | + if (!ultraRng) { |
| 244 | + printf("Failed to get function address\n"); |
| 245 | + FreeLibrary(hRngDll); |
| 246 | + return 1; |
| 247 | + } |
| 248 | + |
| 249 | + // Generate high-security random bytes (complexity level 10) |
| 250 | + unsigned char buffer[64] = {0}; |
| 251 | + printf("Generating high-entropy random bytes...\n"); |
| 252 | + |
| 253 | + if (ultraRng(buffer, sizeof(buffer), 10)) { |
| 254 | + printf("Random bytes generated successfully:\n"); |
| 255 | + for (int i = 0; i < sizeof(buffer); i++) { |
| 256 | + printf("%02X ", buffer[i]); |
| 257 | + if ((i + 1) % 16 == 0) printf("\n"); |
| 258 | + } |
| 259 | + } else { |
| 260 | + printf("Failed to generate random bytes\n"); |
| 261 | + } |
| 262 | + |
| 263 | + FreeLibrary(hRngDll); |
| 264 | + return 0; |
| 265 | +} |
| 266 | +``` |
| 267 | +
|
| 268 | +## Technical Details |
| 269 | +
|
| 270 | +### Entropy Sources |
| 271 | +
|
| 272 | +The library collects entropy from multiple sources: |
| 273 | +
|
| 274 | +1. **Hardware RNG (RDRAND)** |
| 275 | + - Uses Intel's RDRAND instruction when available |
| 276 | + - Implements retry logic for reliability (up to 10 retries) |
| 277 | +
|
| 278 | +2. **CPU-specific Sources** |
| 279 | + - RDTSC (Read Time-Stamp Counter) |
| 280 | + - CPUID information |
| 281 | +
|
| 282 | +3. **System Performance Metrics** |
| 283 | + - Process memory information via GetProcessMemoryInfo |
| 284 | + - High-precision performance counters via QueryPerformanceCounter |
| 285 | +
|
| 286 | +4. **Storage Information** |
| 287 | + - Disk free space statistics via GetDiskFreeSpaceEx |
| 288 | +
|
| 289 | +5. **Audio Timing** |
| 290 | + - Timing-based entropy collection with sleep intervals |
| 291 | + - Used as a fallback entropy source |
| 292 | +
|
| 293 | +6. **Battery/Power Information** |
| 294 | + - System power status via GetSystemPowerStatus |
| 295 | +
|
| 296 | +7. **Network Statistics** |
| 297 | + - TCP statistics via GetTcpStatistics |
| 298 | + - Network adapter information via GetAdaptersInfo |
| 299 | +
|
| 300 | +### Entropy Mixing |
| 301 | +
|
| 302 | +All entropy sources are securely combined using SHA-256 through the Windows BCrypt API: |
| 303 | +
|
| 304 | +- Multiple rounds of hashing based on the complexity parameter |
| 305 | +- Secure handling of hash state between rounds |
| 306 | +- Proper cleanup of cryptographic resources |
| 307 | +
|
| 308 | +### Thread Safety |
| 309 | +
|
| 310 | +- Uses Windows critical sections for thread synchronization |
| 311 | +- Initialization of threading primitives via maxrng_init() |
| 312 | +- Thread-safe API via maxrng_threadsafe() |
| 313 | +
|
| 314 | +### Security Considerations |
| 315 | +
|
| 316 | +- Multiple fallback mechanisms ensure reliability when hardware RNG is unavailable |
| 317 | +- Complexity parameter allows for trading off performance vs. security |
| 318 | +- Clean error handling with proper resource cleanup |
| 319 | +
|
| 320 | +## Building and Integration |
| 321 | +
|
| 322 | +### Requirements |
| 323 | +
|
| 324 | +- Windows operating system (Windows 7 or later) |
| 325 | +- Visual Studio or compatible C compiler |
| 326 | +- Required Windows libraries: |
| 327 | + - bcrypt.lib |
| 328 | + - winmm.lib |
| 329 | + - iphlpapi.lib |
| 330 | + - psapi.lib |
| 331 | +
|
| 332 | +### Linking with Your Application |
| 333 | +
|
| 334 | +When compiling your application, make sure to link against the required libraries: |
| 335 | +
|
| 336 | +```c |
| 337 | +#pragma comment(lib, "bcrypt.lib") |
| 338 | +#pragma comment(lib, "winmm.lib") |
| 339 | +#pragma comment(lib, "iphlpapi.lib") |
| 340 | +#pragma comment(lib, "psapi.lib") |
| 341 | +``` |
| 342 | + |
| 343 | +#### Dynamic Loading |
| 344 | + |
| 345 | +```c |
| 346 | +HMODULE hRngDll = LoadLibrary("hRng.dll"); |
| 347 | +if (hRngDll) { |
| 348 | + // Get function pointers using GetProcAddress |
| 349 | + // ... |
| 350 | +} |
| 351 | +``` |
0 commit comments