VirtualBox

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

Last change on this file since 78052 was 76553, checked in by vboxsync, 6 years ago

scm --update-copyright-year

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