VirtualBox

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

Last change on this file was 98103, checked in by vboxsync, 16 months ago

Copyright year updates by scm.

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

© 2023 Oracle
ContactPrivacy policyTerms of Use