VirtualBox

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

Last change on this file since 14021 was 11523, checked in by vboxsync, 16 years ago

iprt: Implemented the /dev/urandom base random generator as a RTRAND opaque. Made the simple RTRand API just serve as a wrapper using the RTRandAdv API with a global RTRAND handle.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 11.1 KB
Line 
1/* $Id: randadv.cpp 11523 2008-08-20 20:48:52Z 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 <iprt/mem.h>
37#include <iprt/err.h>
38#include <iprt/assert.h>
39#include "internal/magics.h"
40#include "internal/rand.h"
41
42
43RTDECL(int) RTRandAdvDestroy(RTRAND hRand) RT_NO_THROW
44{
45 /* Validate. */
46 if (hRand == NIL_RTRAND)
47 return VINF_SUCCESS;
48 PRTRANDINT pThis = hRand;
49 AssertPtrReturn(pThis, VERR_INVALID_HANDLE);
50 AssertReturn(pThis->u32Magic == RTRANDINT_MAGIC, VERR_INVALID_HANDLE);
51
52 /* forward the call */
53 return pThis->pfnDestroy(pThis);
54}
55
56
57RTDECL(int) RTRandAdvSeed(RTRAND hRand, uint64_t u64Seed) RT_NO_THROW
58{
59 /* Validate. */
60 PRTRANDINT pThis = hRand;
61 AssertPtrReturn(pThis, VERR_INVALID_HANDLE);
62 AssertReturn(pThis->u32Magic == RTRANDINT_MAGIC, VERR_INVALID_HANDLE);
63
64 /* forward the call */
65 return pThis->pfnSeed(pThis, u64Seed);
66}
67
68
69RTDECL(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
83RTDECL(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
96RTDECL(void) RTRandAdvBytes(RTRAND hRand, void *pv, size_t cb) RT_NO_THROW
97{
98 /* Validate. */
99 PRTRANDINT pThis = hRand;
100 AssertPtrReturnVoid(pThis);
101 AssertReturnVoid(pThis->u32Magic == RTRANDINT_MAGIC);
102 AssertPtr(pv);
103
104 /* forward the call */
105 return pThis->pfnGetBytes(pThis, (uint8_t *)pv, cb);
106}
107
108
109RTDECL(int32_t) RTRandAdvS32Ex(RTRAND hRand, int32_t i32First, int32_t i32Last) RT_NO_THROW
110{
111 /* Validate. */
112 PRTRANDINT pThis = hRand;
113 AssertPtrReturn(pThis, INT32_MAX);
114 AssertReturn(pThis->u32Magic == RTRANDINT_MAGIC, INT32_MAX);
115
116 /* wrap the call */
117 return pThis->pfnGetU32(pThis, 0, i32Last - i32First) + i32First;
118}
119
120
121RTDECL(int32_t) RTRandAdvS32(RTRAND hRand) RT_NO_THROW
122{
123 /* Validate. */
124 PRTRANDINT pThis = hRand;
125 AssertPtrReturn(pThis, INT32_MAX);
126 AssertReturn(pThis->u32Magic == RTRANDINT_MAGIC, INT32_MAX);
127
128 /* wrap the call */
129 return pThis->pfnGetU32(pThis, 0, UINT32_MAX) + INT32_MAX;
130}
131
132
133RTDECL(uint32_t) RTRandAdvU32Ex(RTRAND hRand, uint32_t u32First, uint32_t u32Last) RT_NO_THROW
134{
135 /* Validate. */
136 PRTRANDINT pThis = hRand;
137 AssertPtrReturn(pThis, UINT32_MAX);
138 AssertReturn(pThis->u32Magic == RTRANDINT_MAGIC, UINT32_MAX);
139
140 /* forward the call */
141 return pThis->pfnGetU32(pThis, u32First, u32Last);
142}
143
144
145RTDECL(uint32_t) RTRandAdvU32(RTRAND hRand) RT_NO_THROW
146{
147 /* Validate. */
148 PRTRANDINT pThis = hRand;
149 AssertPtrReturn(pThis, UINT32_MAX);
150 AssertReturn(pThis->u32Magic == RTRANDINT_MAGIC, UINT32_MAX);
151
152 /* forward the call */
153 return pThis->pfnGetU32(pThis, 0, UINT32_MAX);
154}
155
156
157RTDECL(int64_t) RTRandAdvS64Ex(RTRAND hRand, int64_t i64First, int64_t i64Last) RT_NO_THROW
158{
159 /* Validate. */
160 PRTRANDINT pThis = hRand;
161 AssertPtrReturn(pThis, INT64_MAX);
162 AssertReturn(pThis->u32Magic == RTRANDINT_MAGIC, INT64_MAX);
163
164 /* wrap the call */
165 return pThis->pfnGetU64(pThis, 0, i64Last - i64First) + i64First;
166}
167
168
169RTDECL(int64_t) RTRandAdvS64(RTRAND hRand) RT_NO_THROW
170{
171 /* Validate. */
172 PRTRANDINT pThis = hRand;
173 AssertPtrReturn(pThis, INT64_MAX);
174 AssertReturn(pThis->u32Magic == RTRANDINT_MAGIC, INT64_MAX);
175
176 /* wrap the call */
177 return pThis->pfnGetU64(pThis, 0, UINT64_MAX) + INT64_MAX;
178}
179
180
181RTDECL(uint64_t) RTRandAdvU64Ex(RTRAND hRand, uint64_t u64First, uint64_t u64Last) RT_NO_THROW
182{
183 /* Validate. */
184 PRTRANDINT pThis = hRand;
185 AssertPtrReturn(pThis, UINT64_MAX);
186 AssertReturn(pThis->u32Magic == RTRANDINT_MAGIC, UINT64_MAX);
187
188 /* forward the call */
189 return pThis->pfnGetU64(pThis, u64First, u64Last);
190}
191
192
193RTDECL(uint64_t) RTRandAdvU64(RTRAND hRand) RT_NO_THROW
194{
195 /* Validate. */
196 PRTRANDINT pThis = hRand;
197 AssertPtrReturn(pThis, UINT64_MAX);
198 AssertReturn(pThis->u32Magic == RTRANDINT_MAGIC, UINT64_MAX);
199
200 /* forward the call */
201 return pThis->pfnGetU64(pThis, 0, UINT64_MAX);
202}
203
204
205DECLCALLBACK(void) rtRandAdvSynthesizeBytesFromU32(PRTRANDINT pThis, uint8_t *pb, size_t cb)
206{
207 while (cb > 0)
208 {
209 uint32_t u32 = pThis->pfnGetU32(pThis, 0, UINT32_MAX);
210 switch (cb)
211 {
212 case 4:
213 pb[3] = (uint8_t)(u32 >> 24);
214 case 3:
215 pb[2] = (uint8_t)(u32 >> 16);
216 case 2:
217 pb[1] = (uint8_t)(u32 >> 8);
218 case 1:
219 pb[0] = (uint8_t)u32;
220 return; /* done */
221
222 default:
223 pb[0] = (uint8_t)u32;
224 pb[1] = (uint8_t)(u32 >> 8);
225 pb[2] = (uint8_t)(u32 >> 16);
226 pb[3] = (uint8_t)(u32 >> 24);
227 break;
228 }
229
230 /* advance */
231 cb -= 4;
232 pb += 4;
233 }
234}
235
236
237DECLCALLBACK(void) rtRandAdvSynthesizeBytesFromU64(PRTRANDINT pThis, uint8_t *pb, size_t cb)
238{
239 while (cb > 0)
240 {
241 uint64_t u64 = pThis->pfnGetU64(pThis, 0, UINT64_MAX);
242 switch (cb)
243 {
244 case 8:
245 pb[7] = (uint8_t)(u64 >> 56);
246 case 7:
247 pb[6] = (uint8_t)(u64 >> 48);
248 case 6:
249 pb[5] = (uint8_t)(u64 >> 40);
250 case 5:
251 pb[4] = (uint8_t)(u64 >> 32);
252 case 4:
253 pb[3] = (uint8_t)(u64 >> 24);
254 case 3:
255 pb[2] = (uint8_t)(u64 >> 16);
256 case 2:
257 pb[1] = (uint8_t)(u64 >> 8);
258 case 1:
259 pb[0] = (uint8_t)u64;
260 return; /* done */
261
262 default:
263 pb[0] = (uint8_t)u64;
264 pb[1] = (uint8_t)(u64 >> 8);
265 pb[2] = (uint8_t)(u64 >> 16);
266 pb[3] = (uint8_t)(u64 >> 24);
267 pb[4] = (uint8_t)(u64 >> 32);
268 pb[5] = (uint8_t)(u64 >> 40);
269 pb[6] = (uint8_t)(u64 >> 48);
270 pb[7] = (uint8_t)(u64 >> 56);
271 break;
272 }
273
274 /* advance */
275 cb -= 8;
276 pb += 8;
277 }
278}
279
280
281DECLCALLBACK(uint32_t) rtRandAdvSynthesizeU32FromBytes(PRTRANDINT pThis, uint32_t u32First, uint32_t u32Last)
282{
283 union
284 {
285 uint32_t off;
286 uint8_t ab[5];
287 } u;
288
289 const uint32_t offLast = u32Last - u32First;
290 if (offLast == UINT32_MAX)
291 /* get 4 random bytes and return them raw. */
292 pThis->pfnGetBytes(pThis, &u.ab[0], sizeof(u.off));
293 else if (!(offLast & UINT32_C(0xf0000000)))
294 {
295 /* get 4 random bytes and do simple squeeze. */
296 pThis->pfnGetBytes(pThis, &u.ab[0], sizeof(u.off));
297 u.off %= offLast + 1;
298 u.off += u32First;
299 }
300 else
301 {
302 /* get 5 random bytes and do shifted squeeze. (this ain't perfect) */
303 pThis->pfnGetBytes(pThis, &u.ab[0], sizeof(u.ab));
304 u.off %= (offLast >> 4) + 1;
305 u.off <<= 4;
306 u.off |= u.ab[4] & 0xf;
307 if (u.off > offLast)
308 u.off = offLast;
309 u.off += u32First;
310 }
311 return u.off;
312}
313
314
315DECLCALLBACK(uint32_t) rtRandAdvSynthesizeU32FromU64(PRTRANDINT pThis, uint32_t u32First, uint32_t u32Last)
316{
317 return pThis->pfnGetU64(pThis, u32First, u32Last);
318}
319
320
321DECLCALLBACK(uint64_t) rtRandAdvSynthesizeU64FromBytes(PRTRANDINT pThis, uint64_t u64First, uint64_t u64Last)
322{
323 union
324 {
325 uint64_t off;
326 uint32_t off32;
327 uint8_t ab[9];
328 } u;
329
330 const uint64_t offLast = u64Last - u64First;
331 if (offLast == UINT64_MAX)
332 /* get 8 random bytes and return them raw. */
333 pThis->pfnGetBytes(pThis, &u.ab[0], sizeof(u.off));
334 else if (!(offLast & UINT64_C(0xf000000000000000)))
335 {
336 /* get 8 random bytes and do simple squeeze. */
337 pThis->pfnGetBytes(pThis, &u.ab[0], sizeof(u.off));
338 u.off %= offLast + 1;
339 u.off += u64First;
340 }
341 else
342 {
343 /* get 9 random bytes and do shifted squeeze. (this ain't perfect) */
344 pThis->pfnGetBytes(pThis, &u.ab[0], sizeof(u.ab));
345 u.off %= (offLast >> 4) + 1;
346 u.off <<= 4;
347 u.off |= u.ab[8] & 0xf;
348 if (u.off > offLast)
349 u.off = offLast;
350 u.off += u64First;
351 }
352 return u.off;
353}
354
355
356DECLCALLBACK(uint64_t) rtRandAdvSynthesizeU64FromU32(PRTRANDINT pThis, uint64_t u64First, uint64_t u64Last)
357{
358 uint64_t off = u64Last - u64First;
359 if (off <= UINT32_MAX)
360 return pThis->pfnGetU32(pThis, 0, off) + u64First;
361
362 return ( pThis->pfnGetU32(pThis, 0, UINT32_MAX)
363 | ((uint64_t)pThis->pfnGetU32(pThis, 0, off >> 32) << 32))
364 + u64First;
365}
366
367
368/** @copydoc RTRANDINT::pfnSeed */
369DECLCALLBACK(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 */
378DECLCALLBACK(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 */
388DECLCALLBACK(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 */
397DECLCALLBACK(int) rtRandAdvDefaultDestroy(PRTRANDINT pThis)
398{
399 pThis->u32Magic = ~RTRANDINT_MAGIC;
400 RTMemFree(pThis);
401 return VINF_SUCCESS;
402}
403
404
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