VirtualBox

source: vbox/trunk/src/VBox/Runtime/common/rand/randadv.cpp@ 26761

Last change on this file since 26761 was 21337, checked in by vboxsync, 15 years ago

IPRT,HostDrv,AddDrv: Export public IPRT symbols for the linux kernel (pain).

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 11.6 KB
Line 
1/* $Id: randadv.cpp 21337 2009-07-07 14:58:27Z vboxsync $ */
2/** @file
3 * IPRT - Random Numbers, Generic Glue.
4 */
5
6/*
7 * Copyright (C) 2008 Sun Microsystems, Inc.
8 *
9 * This file is part of VirtualBox Open Source Edition (OSE), as
10 * available from http://www.virtualbox.org. This file is free software;
11 * you can redistribute it and/or modify it under the terms of the GNU
12 * General Public License (GPL) as published by the Free Software
13 * Foundation, in version 2 as it comes in the "COPYING" file of the
14 * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
15 * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
16 *
17 * The contents of this file may alternatively be used under the terms
18 * of the Common Development and Distribution License Version 1.0
19 * (CDDL) only, as it comes in the "COPYING.CDDL" file of the
20 * VirtualBox OSE distribution, in which case the provisions of the
21 * CDDL are applicable instead of those of the GPL.
22 *
23 * You may elect to license modified versions of this file under the
24 * terms and conditions of either the GPL or the CDDL or both.
25 *
26 * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa
27 * Clara, CA 95054 USA or visit http://www.sun.com if you need
28 * additional information or have any questions.
29 */
30
31
32/*******************************************************************************
33* Header Files *
34*******************************************************************************/
35#include <iprt/rand.h>
36#include "internal/iprt.h"
37
38#include <iprt/mem.h>
39#include <iprt/err.h>
40#include <iprt/assert.h>
41#include "internal/magics.h"
42#include "internal/rand.h"
43
44
45RTDECL(int) RTRandAdvDestroy(RTRAND hRand) RT_NO_THROW
46{
47 /* Validate. */
48 if (hRand == NIL_RTRAND)
49 return VINF_SUCCESS;
50 PRTRANDINT pThis = hRand;
51 AssertPtrReturn(pThis, VERR_INVALID_HANDLE);
52 AssertReturn(pThis->u32Magic == RTRANDINT_MAGIC, VERR_INVALID_HANDLE);
53
54 /* forward the call */
55 return pThis->pfnDestroy(pThis);
56}
57RT_EXPORT_SYMBOL(RTRandAdvDestroy);
58
59
60RTDECL(int) RTRandAdvSeed(RTRAND hRand, uint64_t u64Seed) RT_NO_THROW
61{
62 /* Validate. */
63 PRTRANDINT pThis = hRand;
64 AssertPtrReturn(pThis, VERR_INVALID_HANDLE);
65 AssertReturn(pThis->u32Magic == RTRANDINT_MAGIC, VERR_INVALID_HANDLE);
66
67 /* forward the call */
68 return pThis->pfnSeed(pThis, u64Seed);
69}
70RT_EXPORT_SYMBOL(RTRandAdvSeed);
71
72
73RTDECL(int) RTRandAdvSaveState(RTRAND hRand, char *pszState, size_t *pcbState) RT_NO_THROW
74{
75 /* Validate. */
76 PRTRANDINT pThis = hRand;
77 AssertPtrReturn(pThis, VERR_INVALID_HANDLE);
78 AssertReturn(pThis->u32Magic == RTRANDINT_MAGIC, VERR_INVALID_HANDLE);
79 AssertPtrNull(pszState);
80 AssertPtr(pcbState);
81
82 /* forward the call */
83 return pThis->pfnSaveState(pThis, pszState, pcbState);
84}
85RT_EXPORT_SYMBOL(RTRandAdvSaveState);
86
87
88RTDECL(int) RTRandAdvRestoreState(RTRAND hRand, char const *pszState) RT_NO_THROW
89{
90 /* Validate. */
91 PRTRANDINT pThis = hRand;
92 AssertPtrReturn(pThis, VERR_INVALID_HANDLE);
93 AssertReturn(pThis->u32Magic == RTRANDINT_MAGIC, VERR_INVALID_HANDLE);
94 AssertPtr(pszState);
95
96 /* forward the call */
97 return pThis->pfnRestoreState(pThis, pszState);
98}
99RT_EXPORT_SYMBOL(RTRandAdvRestoreState);
100
101
102RTDECL(void) RTRandAdvBytes(RTRAND hRand, void *pv, size_t cb) RT_NO_THROW
103{
104 /* Validate. */
105 PRTRANDINT pThis = hRand;
106 AssertPtrReturnVoid(pThis);
107 AssertReturnVoid(pThis->u32Magic == RTRANDINT_MAGIC);
108 AssertPtr(pv);
109
110 /* forward the call */
111 return pThis->pfnGetBytes(pThis, (uint8_t *)pv, cb);
112}
113RT_EXPORT_SYMBOL(RTRandAdvBytes);
114
115
116RTDECL(int32_t) RTRandAdvS32Ex(RTRAND hRand, int32_t i32First, int32_t i32Last) RT_NO_THROW
117{
118 /* Validate. */
119 PRTRANDINT pThis = hRand;
120 AssertPtrReturn(pThis, INT32_MAX);
121 AssertReturn(pThis->u32Magic == RTRANDINT_MAGIC, INT32_MAX);
122
123 /* wrap the call */
124 return pThis->pfnGetU32(pThis, 0, i32Last - i32First) + i32First;
125}
126RT_EXPORT_SYMBOL(RTRandAdvS32Ex);
127
128
129RTDECL(int32_t) RTRandAdvS32(RTRAND hRand) RT_NO_THROW
130{
131 /* Validate. */
132 PRTRANDINT pThis = hRand;
133 AssertPtrReturn(pThis, INT32_MAX);
134 AssertReturn(pThis->u32Magic == RTRANDINT_MAGIC, INT32_MAX);
135
136 /* wrap the call */
137 return pThis->pfnGetU32(pThis, 0, UINT32_MAX) + INT32_MAX;
138}
139RT_EXPORT_SYMBOL(RTRandAdvS32);
140
141
142RTDECL(uint32_t) RTRandAdvU32Ex(RTRAND hRand, uint32_t u32First, uint32_t u32Last) RT_NO_THROW
143{
144 /* Validate. */
145 PRTRANDINT pThis = hRand;
146 AssertPtrReturn(pThis, UINT32_MAX);
147 AssertReturn(pThis->u32Magic == RTRANDINT_MAGIC, UINT32_MAX);
148
149 /* forward the call */
150 return pThis->pfnGetU32(pThis, u32First, u32Last);
151}
152RT_EXPORT_SYMBOL(RTRandAdvU32Ex);
153
154
155RTDECL(uint32_t) RTRandAdvU32(RTRAND hRand) RT_NO_THROW
156{
157 /* Validate. */
158 PRTRANDINT pThis = hRand;
159 AssertPtrReturn(pThis, UINT32_MAX);
160 AssertReturn(pThis->u32Magic == RTRANDINT_MAGIC, UINT32_MAX);
161
162 /* forward the call */
163 return pThis->pfnGetU32(pThis, 0, UINT32_MAX);
164}
165RT_EXPORT_SYMBOL(RTRandAdvU32);
166
167
168RTDECL(int64_t) RTRandAdvS64Ex(RTRAND hRand, int64_t i64First, int64_t i64Last) RT_NO_THROW
169{
170 /* Validate. */
171 PRTRANDINT pThis = hRand;
172 AssertPtrReturn(pThis, INT64_MAX);
173 AssertReturn(pThis->u32Magic == RTRANDINT_MAGIC, INT64_MAX);
174
175 /* wrap the call */
176 return pThis->pfnGetU64(pThis, 0, i64Last - i64First) + i64First;
177}
178RT_EXPORT_SYMBOL(RTRandAdvS64Ex);
179
180
181RTDECL(int64_t) RTRandAdvS64(RTRAND hRand) RT_NO_THROW
182{
183 /* Validate. */
184 PRTRANDINT pThis = hRand;
185 AssertPtrReturn(pThis, INT64_MAX);
186 AssertReturn(pThis->u32Magic == RTRANDINT_MAGIC, INT64_MAX);
187
188 /* wrap the call */
189 return pThis->pfnGetU64(pThis, 0, UINT64_MAX) + INT64_MAX;
190}
191RT_EXPORT_SYMBOL(RTRandAdvS64);
192
193
194RTDECL(uint64_t) RTRandAdvU64Ex(RTRAND hRand, uint64_t u64First, uint64_t u64Last) RT_NO_THROW
195{
196 /* Validate. */
197 PRTRANDINT pThis = hRand;
198 AssertPtrReturn(pThis, UINT64_MAX);
199 AssertReturn(pThis->u32Magic == RTRANDINT_MAGIC, UINT64_MAX);
200
201 /* forward the call */
202 return pThis->pfnGetU64(pThis, u64First, u64Last);
203}
204RT_EXPORT_SYMBOL(RTRandAdvU64Ex);
205
206
207RTDECL(uint64_t) RTRandAdvU64(RTRAND hRand) RT_NO_THROW
208{
209 /* Validate. */
210 PRTRANDINT pThis = hRand;
211 AssertPtrReturn(pThis, UINT64_MAX);
212 AssertReturn(pThis->u32Magic == RTRANDINT_MAGIC, UINT64_MAX);
213
214 /* forward the call */
215 return pThis->pfnGetU64(pThis, 0, UINT64_MAX);
216}
217RT_EXPORT_SYMBOL(RTRandAdvU64);
218
219
220DECLCALLBACK(void) rtRandAdvSynthesizeBytesFromU32(PRTRANDINT pThis, uint8_t *pb, size_t cb)
221{
222 while (cb > 0)
223 {
224 uint32_t u32 = pThis->pfnGetU32(pThis, 0, UINT32_MAX);
225 switch (cb)
226 {
227 case 4:
228 pb[3] = (uint8_t)(u32 >> 24);
229 case 3:
230 pb[2] = (uint8_t)(u32 >> 16);
231 case 2:
232 pb[1] = (uint8_t)(u32 >> 8);
233 case 1:
234 pb[0] = (uint8_t)u32;
235 return; /* done */
236
237 default:
238 pb[0] = (uint8_t)u32;
239 pb[1] = (uint8_t)(u32 >> 8);
240 pb[2] = (uint8_t)(u32 >> 16);
241 pb[3] = (uint8_t)(u32 >> 24);
242 break;
243 }
244
245 /* advance */
246 cb -= 4;
247 pb += 4;
248 }
249}
250
251
252DECLCALLBACK(void) rtRandAdvSynthesizeBytesFromU64(PRTRANDINT pThis, uint8_t *pb, size_t cb)
253{
254 while (cb > 0)
255 {
256 uint64_t u64 = pThis->pfnGetU64(pThis, 0, UINT64_MAX);
257 switch (cb)
258 {
259 case 8:
260 pb[7] = (uint8_t)(u64 >> 56);
261 case 7:
262 pb[6] = (uint8_t)(u64 >> 48);
263 case 6:
264 pb[5] = (uint8_t)(u64 >> 40);
265 case 5:
266 pb[4] = (uint8_t)(u64 >> 32);
267 case 4:
268 pb[3] = (uint8_t)(u64 >> 24);
269 case 3:
270 pb[2] = (uint8_t)(u64 >> 16);
271 case 2:
272 pb[1] = (uint8_t)(u64 >> 8);
273 case 1:
274 pb[0] = (uint8_t)u64;
275 return; /* done */
276
277 default:
278 pb[0] = (uint8_t)u64;
279 pb[1] = (uint8_t)(u64 >> 8);
280 pb[2] = (uint8_t)(u64 >> 16);
281 pb[3] = (uint8_t)(u64 >> 24);
282 pb[4] = (uint8_t)(u64 >> 32);
283 pb[5] = (uint8_t)(u64 >> 40);
284 pb[6] = (uint8_t)(u64 >> 48);
285 pb[7] = (uint8_t)(u64 >> 56);
286 break;
287 }
288
289 /* advance */
290 cb -= 8;
291 pb += 8;
292 }
293}
294
295
296DECLCALLBACK(uint32_t) rtRandAdvSynthesizeU32FromBytes(PRTRANDINT pThis, uint32_t u32First, uint32_t u32Last)
297{
298 union
299 {
300 uint32_t off;
301 uint8_t ab[5];
302 } u;
303
304 const uint32_t offLast = u32Last - u32First;
305 if (offLast == UINT32_MAX)
306 /* get 4 random bytes and return them raw. */
307 pThis->pfnGetBytes(pThis, &u.ab[0], sizeof(u.off));
308 else if (!(offLast & UINT32_C(0xf0000000)))
309 {
310 /* get 4 random bytes and do simple squeeze. */
311 pThis->pfnGetBytes(pThis, &u.ab[0], sizeof(u.off));
312 u.off %= offLast + 1;
313 u.off += u32First;
314 }
315 else
316 {
317 /* get 5 random bytes and do shifted squeeze. (this ain't perfect) */
318 pThis->pfnGetBytes(pThis, &u.ab[0], sizeof(u.ab));
319 u.off %= (offLast >> 4) + 1;
320 u.off <<= 4;
321 u.off |= u.ab[4] & 0xf;
322 if (u.off > offLast)
323 u.off = offLast;
324 u.off += u32First;
325 }
326 return u.off;
327}
328
329
330DECLCALLBACK(uint32_t) rtRandAdvSynthesizeU32FromU64(PRTRANDINT pThis, uint32_t u32First, uint32_t u32Last)
331{
332 return (uint32_t)pThis->pfnGetU64(pThis, u32First, u32Last);
333}
334
335
336DECLCALLBACK(uint64_t) rtRandAdvSynthesizeU64FromBytes(PRTRANDINT pThis, uint64_t u64First, uint64_t u64Last)
337{
338 union
339 {
340 uint64_t off;
341 uint32_t off32;
342 uint8_t ab[9];
343 } u;
344
345 const uint64_t offLast = u64Last - u64First;
346 if (offLast == UINT64_MAX)
347 /* get 8 random bytes and return them raw. */
348 pThis->pfnGetBytes(pThis, &u.ab[0], sizeof(u.off));
349 else if (!(offLast & UINT64_C(0xf000000000000000)))
350 {
351 /* get 8 random bytes and do simple squeeze. */
352 pThis->pfnGetBytes(pThis, &u.ab[0], sizeof(u.off));
353 u.off %= offLast + 1;
354 u.off += u64First;
355 }
356 else
357 {
358 /* get 9 random bytes and do shifted squeeze. (this ain't perfect) */
359 pThis->pfnGetBytes(pThis, &u.ab[0], sizeof(u.ab));
360 u.off %= (offLast >> 4) + 1;
361 u.off <<= 4;
362 u.off |= u.ab[8] & 0xf;
363 if (u.off > offLast)
364 u.off = offLast;
365 u.off += u64First;
366 }
367 return u.off;
368}
369
370
371DECLCALLBACK(uint64_t) rtRandAdvSynthesizeU64FromU32(PRTRANDINT pThis, uint64_t u64First, uint64_t u64Last)
372{
373 uint64_t off = u64Last - u64First;
374 if (off <= UINT32_MAX)
375 return (uint64_t)pThis->pfnGetU32(pThis, 0, off) + u64First;
376
377 return ( (uint64_t)pThis->pfnGetU32(pThis, 0, UINT32_MAX)
378 | ((uint64_t)pThis->pfnGetU32(pThis, 0, off >> 32) << 32))
379 + u64First;
380}
381
382
383/** @copydoc RTRANDINT::pfnSeed */
384DECLCALLBACK(int) rtRandAdvStubSeed(PRTRANDINT pThis, uint64_t u64Seed)
385{
386 NOREF(pThis);
387 NOREF(u64Seed);
388 return VERR_NOT_SUPPORTED;
389}
390
391
392/** @copydoc RTRANDINT::pfnSaveState */
393DECLCALLBACK(int) rtRandAdvStubSaveState(PRTRANDINT pThis, char *pszState, size_t *pcbState)
394{
395 NOREF(pThis);
396 NOREF(pszState);
397 NOREF(pcbState);
398 return VERR_NOT_SUPPORTED;
399}
400
401
402/** @copydoc RTRANDINT::pfnRestoreState */
403DECLCALLBACK(int) rtRandAdvStubRestoreState(PRTRANDINT pThis, char const *pszState)
404{
405 NOREF(pThis);
406 NOREF(pszState);
407 return VERR_NOT_SUPPORTED;
408}
409
410
411/** @copydoc RTRANDINT::pfnDestroy */
412DECLCALLBACK(int) rtRandAdvDefaultDestroy(PRTRANDINT pThis)
413{
414 pThis->u32Magic = ~RTRANDINT_MAGIC;
415 RTMemFree(pThis);
416 return VINF_SUCCESS;
417}
418
Note: See TracBrowser for help on using the repository browser.

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette