VirtualBox

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

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

export

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 9.6 KB
Line 
1/* $Id: randadv.cpp 11380 2008-08-13 08:44:46Z 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(void) RTRandAdvBytes(RTRAND hRand, void *pv, size_t cb) RT_NO_THROW
70{
71 /* Validate. */
72 PRTRANDINT pThis = hRand;
73 AssertPtrReturnVoid(pThis);
74 AssertReturnVoid(pThis->u32Magic == RTRANDINT_MAGIC);
75 AssertPtr(pv);
76
77 /* forward the call */
78 return pThis->pfnGetBytes(pThis, (uint8_t *)pv, cb);
79}
80
81
82RTDECL(int32_t) RTRandAdvS32Ex(RTRAND hRand, int32_t i32First, int32_t i32Last) RT_NO_THROW
83{
84 /* Validate. */
85 PRTRANDINT pThis = hRand;
86 AssertPtrReturn(pThis, INT32_MAX);
87 AssertReturn(pThis->u32Magic == RTRANDINT_MAGIC, INT32_MAX);
88
89 /* wrap the call */
90 return pThis->pfnGetU32(pThis, 0, i32Last - i32First) + i32First;
91}
92
93
94RTDECL(int32_t) RTRandAdvS32(RTRAND hRand) RT_NO_THROW
95{
96 /* Validate. */
97 PRTRANDINT pThis = hRand;
98 AssertPtrReturn(pThis, INT32_MAX);
99 AssertReturn(pThis->u32Magic == RTRANDINT_MAGIC, INT32_MAX);
100
101 /* wrap the call */
102 return pThis->pfnGetU32(pThis, 0, UINT32_MAX) + INT32_MAX;
103}
104
105
106RTDECL(uint32_t) RTRandAdvU32Ex(RTRAND hRand, uint32_t u32First, uint32_t u32Last) RT_NO_THROW
107{
108 /* Validate. */
109 PRTRANDINT pThis = hRand;
110 AssertPtrReturn(pThis, UINT32_MAX);
111 AssertReturn(pThis->u32Magic == RTRANDINT_MAGIC, UINT32_MAX);
112
113 /* forward the call */
114 return pThis->pfnGetU32(pThis, u32First, u32Last);
115}
116
117
118RTDECL(uint32_t) RTRandAdvU32(RTRAND hRand) RT_NO_THROW
119{
120 /* Validate. */
121 PRTRANDINT pThis = hRand;
122 AssertPtrReturn(pThis, UINT32_MAX);
123 AssertReturn(pThis->u32Magic == RTRANDINT_MAGIC, UINT32_MAX);
124
125 /* forward the call */
126 return pThis->pfnGetU32(pThis, 0, UINT32_MAX);
127}
128
129
130RTDECL(int64_t) RTRandAdvS64Ex(RTRAND hRand, int64_t i64First, int64_t i64Last) RT_NO_THROW
131{
132 /* Validate. */
133 PRTRANDINT pThis = hRand;
134 AssertPtrReturn(pThis, INT64_MAX);
135 AssertReturn(pThis->u32Magic == RTRANDINT_MAGIC, INT64_MAX);
136
137 /* wrap the call */
138 return pThis->pfnGetU64(pThis, 0, i64Last - i64First) + i64First;
139}
140
141
142RTDECL(int64_t) RTRandAdvS64(RTRAND hRand) RT_NO_THROW
143{
144 /* Validate. */
145 PRTRANDINT pThis = hRand;
146 AssertPtrReturn(pThis, INT64_MAX);
147 AssertReturn(pThis->u32Magic == RTRANDINT_MAGIC, INT64_MAX);
148
149 /* wrap the call */
150 return pThis->pfnGetU64(pThis, 0, UINT64_MAX) + INT64_MAX;
151}
152
153
154RTDECL(uint64_t) RTRandAdvU64Ex(RTRAND hRand, uint64_t u64First, uint64_t u64Last) RT_NO_THROW
155{
156 /* Validate. */
157 PRTRANDINT pThis = hRand;
158 AssertPtrReturn(pThis, UINT64_MAX);
159 AssertReturn(pThis->u32Magic == RTRANDINT_MAGIC, UINT64_MAX);
160
161 /* forward the call */
162 return pThis->pfnGetU64(pThis, u64First, u64Last);
163}
164
165
166RTDECL(uint64_t) RTRandAdvU64(RTRAND hRand) RT_NO_THROW
167{
168 /* Validate. */
169 PRTRANDINT pThis = hRand;
170 AssertPtrReturn(pThis, UINT64_MAX);
171 AssertReturn(pThis->u32Magic == RTRANDINT_MAGIC, UINT64_MAX);
172
173 /* forward the call */
174 return pThis->pfnGetU64(pThis, 0, UINT64_MAX);
175}
176
177
178DECLCALLBACK(void) rtRandAdvSynthesizeBytesFromU32(PRTRANDINT pThis, uint8_t *pb, size_t cb)
179{
180 while (cb > 0)
181 {
182 uint32_t u32 = pThis->pfnGetU32(pThis, 0, UINT32_MAX);
183 switch (cb)
184 {
185 case 4:
186 pb[3] = (uint8_t)(u32 >> 24);
187 case 3:
188 pb[2] = (uint8_t)(u32 >> 16);
189 case 2:
190 pb[1] = (uint8_t)(u32 >> 8);
191 case 1:
192 pb[0] = (uint8_t)u32;
193 return; /* done */
194
195 default:
196 pb[0] = (uint8_t)u32;
197 pb[1] = (uint8_t)(u32 >> 8);
198 pb[2] = (uint8_t)(u32 >> 16);
199 pb[3] = (uint8_t)(u32 >> 24);
200 break;
201 }
202
203 /* advance */
204 cb -= 4;
205 pb += 4;
206 }
207}
208
209
210DECLCALLBACK(void) rtRandAdvSynthesizeBytesFromU64(PRTRANDINT pThis, uint8_t *pb, size_t cb)
211{
212 while (cb > 0)
213 {
214 uint64_t u64 = pThis->pfnGetU64(pThis, 0, UINT64_MAX);
215 switch (cb)
216 {
217 case 8:
218 pb[7] = (uint8_t)(u64 >> 56);
219 case 7:
220 pb[6] = (uint8_t)(u64 >> 48);
221 case 6:
222 pb[5] = (uint8_t)(u64 >> 40);
223 case 5:
224 pb[4] = (uint8_t)(u64 >> 32);
225 case 4:
226 pb[3] = (uint8_t)(u64 >> 24);
227 case 3:
228 pb[2] = (uint8_t)(u64 >> 16);
229 case 2:
230 pb[1] = (uint8_t)(u64 >> 8);
231 case 1:
232 pb[0] = (uint8_t)u64;
233 return; /* done */
234
235 default:
236 pb[0] = (uint8_t)u64;
237 pb[1] = (uint8_t)(u64 >> 8);
238 pb[2] = (uint8_t)(u64 >> 16);
239 pb[3] = (uint8_t)(u64 >> 24);
240 pb[4] = (uint8_t)(u64 >> 32);
241 pb[5] = (uint8_t)(u64 >> 40);
242 pb[6] = (uint8_t)(u64 >> 48);
243 pb[7] = (uint8_t)(u64 >> 56);
244 break;
245 }
246
247 /* advance */
248 cb -= 8;
249 pb += 8;
250 }
251}
252
253
254DECLCALLBACK(uint32_t) rtRandAdvSynthesizeU32FromBytes(PRTRANDINT pThis, uint32_t u32First, uint32_t u32Last)
255{
256 union
257 {
258 uint32_t off;
259 uint8_t ab[5];
260 } u;
261
262 const uint32_t offLast = u32Last - u32First;
263 if (offLast == UINT32_MAX)
264 /* get 4 random bytes and return them raw. */
265 pThis->pfnGetBytes(pThis, &u.ab[0], sizeof(u.off));
266 else if (!(offLast & UINT32_C(0xf0000000)))
267 {
268 /* get 4 random bytes and do simple squeeze. */
269 pThis->pfnGetBytes(pThis, &u.ab[0], sizeof(u.off));
270 u.off %= offLast + 1;
271 u.off += u32First;
272 }
273 else
274 {
275 /* get 5 random bytes and do shifted squeeze. (this ain't perfect) */
276 pThis->pfnGetBytes(pThis, &u.ab[0], sizeof(u.ab));
277 u.off %= (offLast >> 4) + 1;
278 u.off <<= 4;
279 u.off |= u.ab[4] & 0xf;
280 if (u.off > offLast)
281 u.off = offLast;
282 u.off += u32First;
283 }
284 return u.off;
285}
286
287
288DECLCALLBACK(uint32_t) rtRandAdvSynthesizeU32FromU64(PRTRANDINT pThis, uint32_t u32First, uint32_t u32Last)
289{
290 return pThis->pfnGetU64(pThis, u32First, u32Last);
291}
292
293
294DECLCALLBACK(uint64_t) rtRandAdvSynthesizeU64FromBytes(PRTRANDINT pThis, uint64_t u64First, uint64_t u64Last)
295{
296 union
297 {
298 uint64_t off;
299 uint32_t off32;
300 uint8_t ab[9];
301 } u;
302
303 const uint64_t offLast = u64Last - u64First;
304 if (offLast == UINT64_MAX)
305 /* get 8 random bytes and return them raw. */
306 pThis->pfnGetBytes(pThis, &u.ab[0], sizeof(u.off));
307 else if (!(offLast & UINT64_C(0xf000000000000000)))
308 {
309 /* get 8 random bytes and do simple squeeze. */
310 pThis->pfnGetBytes(pThis, &u.ab[0], sizeof(u.off));
311 u.off %= offLast + 1;
312 u.off += u64First;
313 }
314 else
315 {
316 /* get 9 random bytes and do shifted squeeze. (this ain't perfect) */
317 pThis->pfnGetBytes(pThis, &u.ab[0], sizeof(u.ab));
318 u.off %= (offLast >> 4) + 1;
319 u.off <<= 4;
320 u.off |= u.ab[8] & 0xf;
321 if (u.off > offLast)
322 u.off = offLast;
323 u.off += u64First;
324 }
325 return u.off;
326}
327
328
329DECLCALLBACK(uint64_t) rtRandAdvSynthesizeU64FromU32(PRTRANDINT pThis, uint64_t u64First, uint64_t u64Last)
330{
331 uint64_t off = u64Last - u64First;
332 if (off <= UINT32_MAX)
333 return pThis->pfnGetU32(pThis, 0, off) + u64First;
334
335 return ( pThis->pfnGetU32(pThis, 0, UINT32_MAX)
336 | ((uint64_t)pThis->pfnGetU32(pThis, 0, off >> 32) << 32))
337 + u64First;
338}
339
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