- Timestamp:
- Aug 20, 2008 8:48:52 PM (16 years ago)
- Location:
- trunk
- Files:
-
- 2 added
- 1 deleted
- 8 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/include/iprt/rand.h
r11347 r11523 140 140 141 141 /** 142 * Create an instance of the default non-pseudo random number generator. 143 * 144 * @returns IPRT status code. 145 * @retval VERR_NOT_SUPPORTED on platforms which doesn't have this feature 146 * (Windows & OS/2). 147 * @param phRand Where to store the handle to the generator. 148 * 149 * @remarks Think /dev/urandom. 150 */ 151 RTDECL(int) RTRandAdvCreateNonPseudo(PRTRAND phRand) RT_NO_THROW; 152 153 /** 154 * Create an instance of the default pure non-pseudo random number generator. 155 * 156 * Don't use this unless you seriously need good random numbers because most 157 * systems will have will have problems producing sufficient randomness for this 158 * and you'll end up blocking. 159 * 160 * @returns IPRT status code. 161 * @retval VERR_NOT_SUPPORTED on platforms which doesn't have this feature 162 * (Windows & OS/2). 163 * @param phRand Where to store the handle to the generator. 164 * 165 * @remarks Think /dev/random. 166 */ 167 RTDECL(int) RTRandAdvCreatePureNonPseudo(PRTRAND phRand) RT_NO_THROW; 168 169 /** 142 170 * Destroys a random number generator. 143 171 * … … 155 183 * 156 184 * @returns IPRT status code. 185 * @retval VERR_NOT_SUPPORTED if it isn't a pseudo generator. 186 * 157 187 * @param hRand Handle to the random number generator. 158 188 * @param u64Seed Seed. 159 189 */ 160 190 RTDECL(int) RTRandAdvSeed(RTRAND hRand, uint64_t u64Seed) RT_NO_THROW; 191 192 /** 193 * Save the current state of a pseudo generator. 194 * 195 * This can be use to save the state so it can later be resumed at the same 196 * position. 197 * 198 * @returns IPRT status code. 199 * @retval VINF_SUCCESS on success. *pcbState contains the length of the 200 * returned string and pszState contains the state string. 201 * @retval VERR_BUFFER_OVERFLOW if the supplied buffer is too small. *pcbState 202 * will contain the necessary buffer size. 203 * @retval VERR_NOT_SUPPORTED by non-psuedo generators. 204 * 205 * @param hRand Handle to the random number generator. 206 * @param pszState Where to store the state. The returned string will be 207 * null terminated and printable. 208 * @param pcbState The size of the buffer pszState points to on input, the 209 * size required / used on return (including the 210 * terminator, thus the 'cb' instead of 'cch'). 211 */ 212 RTDECL(int) RTRandAdvSaveState(RTRAND hRand, char *pszState, size_t *pcbState) RT_NO_THROW; 213 214 /** 215 * Restores the state of a pseudo generator. 216 * 217 * The state must've been obtained using RTRandAdvGetState. 218 * 219 * @returns IPRT status code. 220 * @retval VERR_PARSE_ERROR if the state string is malformed. 221 * @retval VERR_NOT_SUPPORTED by non-psuedo generators. 222 * 223 * @param hRand Handle to the random number generator. 224 * @param pszState The state to load. 225 */ 226 RTDECL(int) RTRandAdvRestoreState(RTRAND hRand, char const *pszState) RT_NO_THROW; 161 227 162 228 /** -
trunk/src/VBox/Runtime/Makefile.kmk
r11352 r11523 282 282 283 283 RuntimeR3_SOURCES.win = \ 284 generic/rand-stubs-generic.cpp \285 284 generic/RTDirQueryInfo-generic.cpp \ 286 285 generic/RTDirSetTimes-generic.cpp \ 286 generic/RTMpGetCurFrequency-generic.cpp \ 287 generic/RTMpGetMaxFrequency-generic.cpp \ 288 generic/RTRandAdvCreateNonPseudo-generic.cpp \ 289 generic/RTRandAdvCreatePureNonPseudo-generic.cpp \ 287 290 generic/semnoint-generic.cpp \ 288 291 generic/semsrw-generic.cpp \ 289 generic/RTMpGetCurFrequency-generic.cpp \290 generic/RTMpGetMaxFrequency-generic.cpp \291 292 nt/RTErrConvertFromNtStatus.cpp \ 292 293 r3/posix/env-posix.cpp \ … … 366 367 RuntimeR3_SOURCES.os2 = \ 367 368 generic/pathhost-generic.cpp \ 368 generic/rand-stubs-generic.cpp \369 369 generic/RTDirQueryInfo-generic.cpp \ 370 370 generic/RTDirSetTimes-generic.cpp \ 371 371 generic/RTFileMove-generic.cpp \ 372 372 generic/RTLogWriteDebugger-generic.cpp \ 373 generic/RTRandAdvCreateNonPseudo-generic.cpp \ 374 generic/RTRandAdvCreatePureNonPseudo-generic.cpp \ 373 375 generic/RTTimeLocalNow-generic.cpp \ 374 376 generic/RTTimerCreate-generic.cpp \ -
trunk/src/VBox/Runtime/common/rand/rand.cpp
r11172 r11523 1 1 /* $Id$ */ 2 2 /** @file 3 * IPRT - Random Number 3 * IPRT - Random Numbers. 4 4 */ 5 5 6 6 /* 7 * Copyright (C) 2006-200 7Sun Microsystems, Inc.7 * Copyright (C) 2006-2008 Sun Microsystems, Inc. 8 8 * 9 9 * This file is part of VirtualBox Open Source Edition (OSE), as … … 39 39 #include <iprt/assert.h> 40 40 #include <iprt/thread.h> 41 #include <iprt/once.h> 41 42 #include "internal/rand.h" 42 43 … … 45 46 * Global Variables * 46 47 *******************************************************************************/ 47 /** Lazy init. */ 48 static volatile bool g_fInitialized = false; 49 /** The context variable for the fallback path. */ 50 static uint32_t g_u32Ctx; 51 52 53 /******************************************************************************* 54 * Internal Functions * 55 *******************************************************************************/ 56 static uint32_t rtRandGenBytesFallbackU31(uint32_t *pCtx); 48 /** For lazily initializating of the random generator. */ 49 static RTONCE g_rtRandOnce = RTONCE_INITIALIZER; 50 /** The default random generator. */ 51 static RTRAND g_hRand = NIL_RTRAND; 57 52 58 53 59 54 /** 60 * Lazy initialization of the native and fallback random byte sources.55 * Perform lazy initialization. 61 56 * 57 * @returns IPRT status code. 58 * @param pvUser1 Ignored. 59 * @param pvUser2 Ignored. 62 60 */ 63 static void rtRandLazyInit(void)61 static DECLCALLBACK(int) rtRandInitOnce(void *pvUser1, void *pvUser2) 64 62 { 65 /* 66 * Seed the fallback random code. 67 */ 68 g_u32Ctx = (uint32_t)(ASMReadTSC() >> 8); 63 NOREF(pvUser1); 64 NOREF(pvUser2); 69 65 70 /* 71 * Call host specific init. 72 */ 73 rtRandLazyInitNative(); 74 g_fInitialized = true; 66 RTRAND hRand; 67 int rc = RTRandAdvCreateNonPseudo(&hRand); 68 if (RT_FAILURE(rc)) 69 rc = RTRandAdvCreateParkMiller(&hRand); 70 if (RT_SUCCESS(rc)) 71 { 72 RTRandAdvSeed(hRand, ASMReadTSC() >> 8); 73 g_hRand = hRand; 74 } 75 else 76 AssertRC(rc); 77 78 return rc; 75 79 } 76 80 77 81 78 /** 79 * Internal wrapper for the native and generic random byte methods. 80 * 81 * @param pv Where to store the random bytes. 82 * @param cb Number of bytes to generate. 83 */ 84 static void rtRandGenBytes(void *pv, size_t cb) 82 RTDECL(void) RTRandBytes(void *pv, size_t cb) RT_NO_THROW 85 83 { 86 Assert(cb); 87 if (RT_UNLIKELY(!g_fInitialized)) 88 rtRandLazyInit(); 89 90 int rc = rtRandGenBytesNative(pv, cb); 91 if (RT_FAILURE(rc)) 92 rtRandGenBytesFallback(pv, cb); 84 RTOnce(&g_rtRandOnce, rtRandInitOnce, NULL, NULL); 85 RTRandAdvBytes(g_hRand, pv, cb); 93 86 } 94 87 95 88 96 /** 97 * Fills a buffer with random bytes. 98 * 99 * @param pv Where to store the random bytes. 100 * @param cb Number of bytes to generate. 101 */ 102 RTDECL(void) RTRandBytes(void *pv, size_t cb) RT_NO_THROW 89 RTDECL(uint32_t) RTRandU32Ex(uint32_t u32First, uint32_t u32Last) RT_NO_THROW 103 90 { 104 if (cb)105 rtRandGenBytes(pv, cb);91 RTOnce(&g_rtRandOnce, rtRandInitOnce, NULL, NULL); 92 return RTRandAdvU32Ex(g_hRand, u32First, u32Last); 106 93 } 107 94 108 95 109 /** 110 * Generate a 32-bit unsigned random number in the set [u32First..u32Last]. 111 * 112 * @returns The random number. 113 * @param u32First First number in the set. 114 * @param u32Last Last number in the set. 115 */ 116 RTDECL(uint32_t) RTRandU32Ex(uint32_t u32First, uint32_t u32Last) RT_NO_THROW 96 RTDECL(uint32_t) RTRandU32(void) RT_NO_THROW 117 97 { 118 union 119 { 120 uint32_t off; 121 uint8_t ab[5]; 122 } u; 123 124 const uint32_t offLast = u32Last - u32First; 125 if (offLast == UINT32_MAX) 126 /* get 4 random bytes and return them raw. */ 127 rtRandGenBytes(&u.ab[0], sizeof(u.off)); 128 else if (!(offLast & UINT32_C(0xf0000000))) 129 { 130 /* get 4 random bytes and do simple squeeze. */ 131 rtRandGenBytes(&u.ab[0], sizeof(u.off)); 132 u.off %= offLast + 1; 133 u.off += u32First; 134 } 135 else 136 { 137 /* get 5 random bytes and do shifted squeeze. (this ain't perfect) */ 138 rtRandGenBytes(&u.ab[0], sizeof(u.ab)); 139 u.off %= (offLast >> 4) + 1; 140 u.off <<= 4; 141 u.off |= u.ab[4] & 0xf; 142 if (u.off > offLast) 143 u.off = offLast; 144 u.off += u32First; 145 } 146 return u.off; 98 RTOnce(&g_rtRandOnce, rtRandInitOnce, NULL, NULL); 99 return RTRandAdvU32(g_hRand); 147 100 } 148 101 149 102 150 /** 151 * Generate a 32-bit unsigned random number. 152 * 153 * @returns The random number. 154 */ 155 RTDECL(uint32_t) RTRandU32(void) RT_NO_THROW 103 RTDECL(int32_t) RTRandS32Ex(int32_t i32First, int32_t i32Last) RT_NO_THROW 156 104 { 157 return RTRandU32Ex(0, UINT32_MAX); 105 RTOnce(&g_rtRandOnce, rtRandInitOnce, NULL, NULL); 106 return RTRandAdvS32Ex(g_hRand, i32First, i32Last); 158 107 } 159 108 160 109 161 /** 162 * Generate a 32-bit signed random number in the set [i32First..i32Last]. 163 * 164 * @returns The random number. 165 * @param i32First First number in the set. 166 * @param i32Last Last number in the set. 167 */ 168 RTDECL(int32_t) RTRandS32Ex(int32_t i32First, int32_t i32Last) RT_NO_THROW 110 RTDECL(int32_t) RTRandS32(void) RT_NO_THROW 169 111 { 170 if (i32First == INT32_MIN && i32Last == INT32_MAX) 171 return (int32_t)RTRandU32Ex(0, UINT32_MAX); 172 return RTRandU32Ex(0, i32Last - i32First) + i32First; 112 RTOnce(&g_rtRandOnce, rtRandInitOnce, NULL, NULL); 113 return RTRandAdvS32(g_hRand); 173 114 } 174 115 175 116 176 /** 177 * Generate a 32-bit signed random number. 178 * 179 * @returns The random number. 180 */ 181 RTDECL(int32_t) RTRandS32(void) RT_NO_THROW 117 RTDECL(uint64_t) RTRandU64Ex(uint64_t u64First, uint64_t u64Last) RT_NO_THROW 182 118 { 183 return (int32_t)RTRandU32Ex(0, UINT32_MAX); 119 RTOnce(&g_rtRandOnce, rtRandInitOnce, NULL, NULL); 120 return RTRandAdvU64Ex(g_hRand, u64First, u64Last); 184 121 } 185 122 186 123 187 /** 188 * Generate a 64-bit unsigned random number in the set [u64First..u64Last]. 189 * 190 * @returns The random number. 191 * @param u64First First number in the set. 192 * @param u64Last Last number in the set. 193 */ 194 RTDECL(uint64_t) RTRandU64Ex(uint64_t u64First, uint64_t u64Last) RT_NO_THROW 124 RTDECL(uint64_t) RTRandU64(void) RT_NO_THROW 195 125 { 196 union 197 { 198 uint64_t off; 199 uint32_t off32; 200 uint8_t ab[9]; 201 } u; 202 203 const uint64_t offLast = u64Last - u64First; 204 if (offLast == UINT64_MAX) 205 /* get 8 random bytes and return them raw. */ 206 rtRandGenBytes(&u.ab[0], sizeof(u.off)); 207 else if (!(offLast & UINT64_C(0xf000000000000000))) 208 { 209 /* get 8 random bytes and do simple squeeze. */ 210 rtRandGenBytes(&u.ab[0], sizeof(u.off)); 211 u.off %= offLast + 1; 212 u.off += u64First; 213 } 214 else 215 { 216 /* get 9 random bytes and do shifted squeeze. (this ain't perfect) */ 217 rtRandGenBytes(&u.ab[0], sizeof(u.ab)); 218 u.off %= (offLast >> 4) + 1; 219 u.off <<= 4; 220 u.off |= u.ab[8] & 0xf; 221 if (u.off > offLast) 222 u.off = offLast; 223 u.off += u64First; 224 } 225 return u.off; 126 RTOnce(&g_rtRandOnce, rtRandInitOnce, NULL, NULL); 127 return RTRandAdvU64(g_hRand); 226 128 } 227 129 228 130 229 /** 230 * Generate a 64-bit unsigned random number. 231 * 232 * @returns The random number. 233 */ 234 RTDECL(uint64_t) RTRandU64(void) RT_NO_THROW 131 RTDECL(int64_t) RTRandS64Ex(int64_t i64First, int64_t i64Last) RT_NO_THROW 235 132 { 236 return RTRandU64Ex(0, UINT64_MAX); 133 RTOnce(&g_rtRandOnce, rtRandInitOnce, NULL, NULL); 134 return RTRandAdvS64Ex(g_hRand, i64First, i64Last); 237 135 } 238 136 239 137 240 /** 241 * Generate a 64-bit signed random number in the set [i64First..i64Last]. 242 * 243 * @returns The random number. 244 * @param i64First First number in the set. 245 * @param i64Last Last number in the set. 246 */ 247 RTDECL(int64_t) RTRandS64Ex(int64_t i64First, int64_t i64Last) RT_NO_THROW 138 RTDECL(int64_t) RTRandS64(void) RT_NO_THROW 248 139 { 249 if (i64First == INT64_MIN && i64Last == INT64_MAX) 250 return (int64_t)RTRandU64Ex(0, UINT64_MAX); 251 return (int64_t)RTRandU64Ex(0, i64Last - i64First) + i64First; 140 RTOnce(&g_rtRandOnce, rtRandInitOnce, NULL, NULL); 141 return RTRandAdvS32(g_hRand); 252 142 } 253 143 254 255 /**256 * Generate a 64-bit signed random number.257 *258 * @returns The random number.259 */260 RTDECL(int64_t) RTRandS64(void) RT_NO_THROW261 {262 return (int64_t)RTRandU64Ex(0, UINT64_MAX);263 }264 265 266 /**267 * Fallback random byte source.268 *269 * @param pv Where to store the random bytes.270 * @param cb Number of bytes to generate.271 */272 void rtRandGenBytesFallback(void *pv, size_t cb) RT_NO_THROW273 {274 uint64_t u64Last = 0;275 uint8_t *pb = (uint8_t *)pv;276 for (unsigned i = 0;; i++)277 {278 uint32_t u32 = rtRandGenBytesFallbackU31(&g_u32Ctx);279 280 *pb++ = (uint8_t)u32;281 if (!--cb)282 break;283 284 u32 >>= 8;285 *pb++ = (uint8_t)u32;286 if (!--cb)287 break;288 289 u32 >>= 8;290 *pb++ = (uint8_t)u32;291 if (!--cb)292 break;293 294 /*295 * Is this really a good idea? Looks like we cannot296 * quite trust the lower bits here for instance...297 */298 if (!(i % 3))299 {300 uint64_t u64 = ASMReadTSC();301 uint64_t u64Delta = u64 - u64Last;302 if (u64Delta > 0xff)303 {304 u32 >>= 8;305 *pb++ = ((uint8_t)u64 >> 5) | (u32 << 3);306 if (!--cb)307 break;308 u64Last = u64;309 }310 }311 }312 }313 314 315 /*-316 * Copyright (c) 1990, 1993317 * The Regents of the University of California. All rights reserved.318 *319 * Redistribution and use in source and binary forms, with or without320 * modification, are permitted provided that the following conditions321 * are met:322 * 1. Redistributions of source code must retain the above copyright323 * notice, this list of conditions and the following disclaimer.324 * 2. Redistributions in binary form must reproduce the above copyright325 * notice, this list of conditions and the following disclaimer in the326 * documentation and/or other materials provided with the distribution.327 * 4. Neither the name of the University nor the names of its contributors328 * may be used to endorse or promote products derived from this software329 * without specific prior written permission.330 *331 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND332 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE333 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE334 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE335 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL336 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS337 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)338 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT339 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY340 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF341 * SUCH DAMAGE.342 */343 344 /* The core of:345 __FBSDID("$FreeBSD: /repoman/r/ncvs/src/lib/libc/stdlib/rand.c,v 1.16 2007/01/09 00:28:10 imp Exp $");346 */347 348 /**349 * Generates an unsigned 31 bit pseudo random number.350 *351 * @returns pseudo random number.352 * @param pCtx The context.353 */354 static uint32_t rtRandGenBytesFallbackU31(uint32_t *pCtx)355 {356 /*357 * Compute x = (7^5 * x) mod (2^31 - 1)358 * without overflowing 31 bits:359 * (2^31 - 1) = 127773 * (7^5) + 2836360 *361 * From "Random number generators: good ones are hard to find", Park and362 * Miller, Communications of the ACM, vol. 31, no. 10, October 1988, p. 1195.363 */364 uint32_t Ctx = *pCtx;365 if (!Ctx) /* must not be zero. */366 Ctx = 0x20070212;367 uint32_t Hi = Ctx / 127773;368 uint32_t Lo = Ctx % 127773;369 int32_t x = 16807 * Lo - 2836 * Hi;370 if (x < 0)371 x += INT32_MAX;372 *pCtx = x;373 return x % INT32_MAX;374 }375 -
trunk/src/VBox/Runtime/common/rand/randadv.cpp
r11380 r11523 67 67 68 68 69 RTDECL(int) RTRandAdvSaveState(RTRAND hRand, char *pszState, size_t *pcbState) RT_NO_THROW 70 { 71 /* Validate. */ 72 PRTRANDINT pThis = hRand; 73 AssertPtrReturn(pThis, VERR_INVALID_HANDLE); 74 AssertReturn(pThis->u32Magic == RTRANDINT_MAGIC, VERR_INVALID_HANDLE); 75 AssertPtrNull(pszState); 76 AssertPtr(pcbState); 77 78 /* forward the call */ 79 return pThis->pfnSaveState(pThis, pszState, pcbState); 80 } 81 82 83 RTDECL(int) RTRandAdvRestoreState(RTRAND hRand, char const *pszState) RT_NO_THROW 84 { 85 /* Validate. */ 86 PRTRANDINT pThis = hRand; 87 AssertPtrReturn(pThis, VERR_INVALID_HANDLE); 88 AssertReturn(pThis->u32Magic == RTRANDINT_MAGIC, VERR_INVALID_HANDLE); 89 AssertPtr(pszState); 90 91 /* forward the call */ 92 return pThis->pfnRestoreState(pThis, pszState); 93 } 94 95 69 96 RTDECL(void) RTRandAdvBytes(RTRAND hRand, void *pv, size_t cb) RT_NO_THROW 70 97 { … … 338 365 } 339 366 367 368 /** @copydoc RTRANDINT::pfnSeed */ 369 DECLCALLBACK(int) rtRandAdvStubSeed(PRTRANDINT pThis, uint64_t u64Seed) 370 { 371 NOREF(pThis); 372 NOREF(u64Seed); 373 return VERR_NOT_SUPPORTED; 374 } 375 376 377 /** @copydoc RTRANDINT::pfnSaveState */ 378 DECLCALLBACK(int) rtRandAdvStubSaveState(PRTRANDINT pThis, char *pszState, size_t *pcbState) 379 { 380 NOREF(pThis); 381 NOREF(pszState); 382 NOREF(pcbState); 383 return VERR_NOT_SUPPORTED; 384 } 385 386 387 /** @copydoc RTRANDINT::pfnRestoreState */ 388 DECLCALLBACK(int) rtRandAdvStubRestoreState(PRTRANDINT pThis, char const *pszState) 389 { 390 NOREF(pThis); 391 NOREF(pszState); 392 return VERR_NOT_SUPPORTED; 393 } 394 395 396 /** @copydoc RTRANDINT::pfnDestroy */ 397 DECLCALLBACK(int) rtRandAdvDefaultDestroy(PRTRANDINT pThis) 398 { 399 pThis->u32Magic = ~RTRANDINT_MAGIC; 400 RTMemFree(pThis); 401 return VINF_SUCCESS; 402 } 403 404 -
trunk/src/VBox/Runtime/common/rand/randparkmiller.cpp
r11347 r11523 35 35 #include <iprt/asm.h> 36 36 #include <iprt/mem.h> 37 #include <iprt/string.h> 37 38 #include <iprt/err.h> 38 39 #include "internal/rand.h" … … 65 66 66 67 /** @copydoc RTRANDINT::pfnGetU32 */ 67 static uint32_trtRandParkMillerGetU32(PRTRANDINT pThis, uint32_t u32First, uint32_t u32Last)68 static DECLCALLBACK(uint32_t) rtRandParkMillerGetU32(PRTRANDINT pThis, uint32_t u32First, uint32_t u32Last) 68 69 { 69 70 uint32_t off; … … 115 116 116 117 /** @copydoc RTRANDINT::pfnSeed */ 117 static intrtRandParkMillerSeed(PRTRANDINT pThis, uint64_t u64Seed)118 static DECLCALLBACK(int) rtRandParkMillerSeed(PRTRANDINT pThis, uint64_t u64Seed) 118 119 { 119 120 pThis->u.ParkMiller.u32Ctx = u64Seed; … … 124 125 125 126 126 /** @copydoc RTRANDINT::pfnDestroy */ 127 static int rtRandParkMillerDestroy(PRTRANDINT pThis) 128 { 129 pThis->u32Magic = ~RTRANDINT_MAGIC; 130 RTMemFree(pThis); 127 /** @copydoc RTRANDINT::pfnSaveState */ 128 static DECLCALLBACK(int) rtRandParkMillerSaveState(PRTRANDINT pThis, char *pszState, size_t *pcbState) 129 { 130 #define RTRAND_PARKMILLER_STATE_SIZE (3+8+1+8+1+2+1+1) 131 132 if (*pcbState < RTRAND_PARKMILLER_STATE_SIZE) 133 { 134 *pcbState = RTRAND_PARKMILLER_STATE_SIZE; 135 return VERR_BUFFER_OVERFLOW; 136 } 137 RTStrPrintf(pszState, *pcbState, "PM:%08RX32,%08RX32,%02x;", 138 pThis->u.ParkMiller.u32Ctx, 139 pThis->u.ParkMiller.u32Bits, 140 pThis->u.ParkMiller.cBits); 141 return VINF_SUCCESS; 142 } 143 144 145 /** @copydoc RTRANDINT::pfnRestoreState */ 146 static DECLCALLBACK(int) rtRandParkMillerRestoreState(PRTRANDINT pThis, char const *pszState) 147 { 148 /* marker */ 149 if ( pszState[0] != 'P' 150 || pszState[1] != 'M' 151 || pszState[2] != ':') 152 return VERR_PARSE_ERROR; 153 pszState += 3; 154 155 /* u32Ctx */ 156 char *pszNext = NULL; 157 uint32_t u32Ctx; 158 int rc = RTStrToUInt32Ex(pszState, &pszNext, 16, &u32Ctx); 159 if ( rc != VWRN_TRAILING_CHARS 160 || pszNext != pszState + 8 161 || *pszNext != ',') 162 return VERR_PARSE_ERROR; 163 pszState += 8 + 1; 164 165 /* u32Bits */ 166 uint32_t u32Bits; 167 rc = RTStrToUInt32Ex(pszState, &pszNext, 16, &u32Bits); 168 if ( rc != VWRN_TRAILING_CHARS 169 || pszNext != pszState + 8 170 || *pszNext != ',') 171 return VERR_PARSE_ERROR; 172 pszState += 8 + 1; 173 174 /* cBits */ 175 uint32_t cBits; 176 rc = RTStrToUInt32Ex(pszState, &pszNext, 16, &cBits); 177 if ( rc != VWRN_TRAILING_CHARS 178 || pszNext != pszState + 2 179 || *pszNext != ';' 180 || pszNext[1] != '\0') 181 return VERR_PARSE_ERROR; 182 183 /* commit */ 184 pThis->u.ParkMiller.u32Ctx = u32Ctx; 185 pThis->u.ParkMiller.u32Bits = u32Bits; 186 pThis->u.ParkMiller.cBits = cBits; 131 187 return VINF_SUCCESS; 132 188 } … … 143 199 pThis->pfnGetU64 = rtRandAdvSynthesizeU64FromU32; 144 200 pThis->pfnSeed = rtRandParkMillerSeed; 145 pThis->pfnDestroy = rtRandParkMillerDestroy; 201 pThis->pfnSaveState = rtRandParkMillerSaveState; 202 pThis->pfnRestoreState = rtRandParkMillerRestoreState; 203 pThis->pfnDestroy = rtRandAdvDefaultDestroy; 146 204 pThis->u.ParkMiller.u32Ctx = 0x20080806; 147 205 pThis->u.ParkMiller.u32Bits = 0; -
trunk/src/VBox/Runtime/include/internal/rand.h
r11347 r11523 85 85 * 86 86 * @returns IPRT status code. 87 * @retval VERR_NOT_SUPPORTED if it isn't a pseudo generator. 88 * 87 89 * @param pThis Pointer to the instance data. 88 90 * @param u64Seed The seed. 89 91 */ 90 92 DECLCALLBACKMEMBER(int, pfnSeed)(PRTRANDINT pThis, uint64_t u64Seed); 93 94 /** 95 * Save the current state of a pseudo generator. 96 * 97 * This can be use to save the state so it can later be resumed at the same 98 * position. 99 * 100 * @returns IPRT status code. 101 * @retval VINF_SUCCESS on success. *pcbState contains the length of the 102 * returned string and pszState contains the state string. 103 * @retval VERR_BUFFER_OVERFLOW if the supplied buffer is too small. *pcbState 104 * will contain the necessary buffer size. 105 * @retval VERR_NOT_SUPPORTED by non-psuedo generators. 106 * 107 * @param hRand Handle to the random number generator. 108 * @param pszState Where to store the state. The returned string will be 109 * null terminated and printable. 110 * @param pcbState The size of the buffer pszState points to on input, the 111 * size required / used on return (including the 112 * terminator, thus the 'cb' instead of 'cch'). 113 */ 114 DECLCALLBACKMEMBER(int, pfnSaveState)(RTRAND hRand, char *pszState, size_t *pcbState); 115 116 /** 117 * Restores the state of a pseudo generator. 118 * 119 * The state must've been obtained using pfnGetState. 120 * 121 * @returns IPRT status code. 122 * @retval VERR_PARSE_ERROR if the state string is malformed. 123 * @retval VERR_NOT_SUPPORTED by non-psuedo generators. 124 * 125 * @param hRand Handle to the random number generator. 126 * @param pszState The state to load. 127 */ 128 DECLCALLBACKMEMBER(int, pfnRestoreState)(RTRAND hRand, char const *pszState); 91 129 92 130 /** … … 113 151 uint32_t cBits; 114 152 } ParkMiller; 153 154 struct RTRandFile 155 { 156 /** The file handle. */ 157 RTFILE hFile; 158 } File; 115 159 } u; 116 160 } RTRANDINT; … … 141 185 DECLCALLBACK(uint64_t) rtRandAdvSynthesizeU64FromBytes(PRTRANDINT pThis, uint64_t u64First, uint64_t u64Last); 142 186 DECLCALLBACK(uint64_t) rtRandAdvSynthesizeU64FromU32(PRTRANDINT pThis, uint64_t u64First, uint64_t u64Last); 187 DECLCALLBACK(int) rtRandAdvStubSeed(PRTRANDINT pThis, uint64_t u64Seed); 188 DECLCALLBACK(int) rtRandAdvStubSaveState(PRTRANDINT pThis, char *pszState, size_t *pcbState); 189 DECLCALLBACK(int) rtRandAdvStubRestoreState(PRTRANDINT pThis, char const *pszState); 190 DECLCALLBACK(int) rtRandAdvDefaultDestroy(PRTRANDINT pThis); 143 191 144 192 __END_DECLS -
trunk/src/VBox/Runtime/r3/posix/rand-posix.cpp
r8245 r11523 48 48 49 49 #include <iprt/rand.h> 50 #include <iprt/mem.h> 50 51 #include <iprt/err.h> 51 52 #include <iprt/assert.h> 52 53 #include "internal/rand.h" 54 #include "internal/magics.h" 53 55 54 56 55 /*******************************************************************************56 * Global Variables *57 *******************************************************************************/58 /** File handle of /dev/random. */59 static int g_fhDevRandom = -1;60 57 61 62 void rtRandLazyInitNative(void)58 /** @copydoc RTRANDINT::pfnGetBytes */ 59 static DECLCALLBACK(void) rtRandAdvPosixGetBytes(PRTRANDINT pThis, uint8_t *pb, size_t cb) 63 60 { 64 if (g_fhDevRandom != -1) 65 return; 66 67 int fh = open("/dev/urandom", O_RDONLY); 68 if (fh <= 0) 69 fh = open("/dev/random", O_RDONLY | O_NONBLOCK); 70 if (fh >= 0) 61 ssize_t cbRead = read(pThis->u.File.hFile, pb, cb); 62 if ((size_t)cbRead != cb) 71 63 { 72 fcntl(fh, F_SETFD, FD_CLOEXEC); 73 g_fhDevRandom = fh; 64 ssize_t cTries = RT_MIN(cb, 256); 65 do 66 { 67 if (cbRead > 0) 68 { 69 cb -= cbRead; 70 pb += cbRead; 71 } 72 cbRead = read(pThis->u.File.hFile, pb, cb); 73 } while ( (size_t)cbRead != cb 74 && cTries-- > 0); 75 AssertReleaseMsg((size_t)cbRead == cb, ("%zu != %zu, cTries=%zd errno=%d\n", cbRead, cb, cTries, errno)); 74 76 } 75 77 } 76 78 77 79 78 int rtRandGenBytesNative(void *pv, size_t cb) 80 /** @copydoc RTRANDINT::pfnDestroy */ 81 static DECLCALLBACK(int) rtRandAdvPosixDestroy(PRTRANDINT pThis) 79 82 { 80 int fh = g_fhDevRandom; 81 if (fh == -1) 82 return VERR_NOT_SUPPORTED; 83 84 ssize_t cbRead = read(fh, pv, cb); 85 if ((size_t)cbRead != cb) 86 { 87 /* 88 * Use the fallback for the remainder if /dev/urandom / /dev/random 89 * is out to lunch. 90 */ 91 if (cbRead <= 0) 92 rtRandGenBytesFallback(pv, cb); 93 else 94 { 95 AssertRelease((size_t)cbRead < cb); 96 rtRandGenBytesFallback((uint8_t *)pv + cbRead, cb - cbRead); 97 } 98 } 83 pThis->u32Magic = ~RTRANDINT_MAGIC; 84 int fd = pThis->u.File.hFile; 85 pThis->u.File.hFile = NIL_RTFILE; 86 RTMemFree(pThis); 87 close(fd); 99 88 return VINF_SUCCESS; 100 89 } 101 90 91 92 static int rtRandAdvPosixCreateNonPseudo(PRTRAND phRand, const char *pszDev) RT_NO_THROW 93 { 94 /* 95 * Try open it first and then setup the handle structure. 96 */ 97 int fd = open(pszDev, O_RDONLY); 98 if (fd < 0) 99 return RTErrConvertFromErrno(errno); 100 int rc; 101 if (fcntl(fd, F_SETFD, FD_CLOEXEC) != -1) 102 { 103 PRTRANDINT pThis = (PRTRANDINT)RTMemAlloc(sizeof(*pThis)); 104 if (pThis) 105 { 106 pThis->u32Magic = RTRANDINT_MAGIC; 107 pThis->pfnGetBytes = rtRandAdvPosixGetBytes; 108 pThis->pfnGetU32 = rtRandAdvSynthesizeU32FromBytes; 109 pThis->pfnGetU64 = rtRandAdvSynthesizeU64FromBytes; 110 pThis->pfnSeed = rtRandAdvStubSeed; 111 pThis->pfnSaveState = rtRandAdvStubSaveState; 112 pThis->pfnRestoreState = rtRandAdvStubRestoreState; 113 pThis->pfnDestroy = rtRandAdvPosixDestroy; 114 pThis->u.File.hFile = fd; 115 116 *phRand = pThis; 117 return VINF_SUCCESS; 118 } 119 120 /* bail out */ 121 rc = VERR_NO_MEMORY; 122 } 123 else 124 rc = RTErrConvertFromErrno(errno); 125 close(fd); 126 return rc; 127 } 128 129 130 RTDECL(int) RTRandAdvCreateNonPseudo(PRTRAND phRand) RT_NO_THROW 131 { 132 return rtRandAdvPosixCreateNonPseudo(phRand, "/dev/urandom"); 133 } 134 135 136 RTDECL(int) RTRandAdvCreatePureNonPseudo(PRTRAND phRand) RT_NO_THROW 137 { 138 return rtRandAdvPosixCreateNonPseudo(phRand, "/dev/random"); 139 } 140 141 -
trunk/src/VBox/Runtime/testcase/tstRand.cpp
r11347 r11523 317 317 318 318 /* 319 * Test saving and restoring the state. 320 */ 321 RTPrintf("tstRand: TESTING RTRandAdvSave/RestoreSave\n"); 322 char szState[256]; 323 size_t cbState = sizeof(szState); 324 int rc = RTRandAdvSaveState(hRand, szState, &cbState); 325 if (rc != VERR_NOT_SUPPORTED) 326 { 327 CHECK_EXPR_MSG(rc == VINF_SUCCESS, ("RTRandAdvSaveState(%p,,256) -> %Rrc (%d)\n", (uintptr_t)hRand, rc, rc)); 328 uint32_t const u32A1 = RTRandAdvU32(hRand); 329 uint32_t const u32B1 = RTRandAdvU32(hRand); 330 RTPrintf("tstRand: state:\"%s\" A=%RX32 B=%RX32\n", szState, u32A1, u32B1); 331 332 rc = RTRandAdvRestoreState(hRand, szState); 333 CHECK_EXPR_MSG(rc == VINF_SUCCESS, ("RTRandAdvRestoreState(%p,\"%s\") -> %Rrc (%d)\n", (uintptr_t)hRand, szState, rc, rc)); 334 uint32_t const u32A2 = RTRandAdvU32(hRand); 335 uint32_t const u32B2 = RTRandAdvU32(hRand); 336 CHECK_EXPR_MSG(u32A1 == u32A2, ("u32A1=%RX32 u32A2=%RX32\n", u32A1, u32A2)); 337 CHECK_EXPR_MSG(u32B1 == u32B2, ("u32B1=%RX32 u32B2=%RX32\n", u32B1, u32B2)); 338 } 339 else 340 { 341 szState[0] = '\0'; 342 rc = RTRandAdvRestoreState(hRand, szState); 343 CHECK_EXPR_MSG(rc == VERR_NOT_SUPPORTED, ("RTRandAdvRestoreState(%p,\"\") -> %Rrc (%d)\n", (uintptr_t)hRand, rc, rc)); 344 } 345 346 347 /* 319 348 * Destroy it. 320 349 */ 321 intrc = RTRandAdvDestroy(hRand);350 rc = RTRandAdvDestroy(hRand); 322 351 CHECK_EXPR_MSG(rc == VINF_SUCCESS, ("RTRandAdvDestroy(%p) -> %Rrc (%d)\n", (uintptr_t)hRand, rc, rc)); 323 352
Note:
See TracChangeset
for help on using the changeset viewer.