rand.cpp revision 166d15723bdbf3eeec7d9d420de92c65cf9daf9f
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync/* $Id$ */
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync/** @file
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync * IPRT - Random Number
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync */
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync/*
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync * Copyright (C) 2006-2007 Sun Microsystems, Inc.
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync *
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync * This file is part of VirtualBox Open Source Edition (OSE), as
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync * available from http://www.virtualbox.org. This file is free software;
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync * you can redistribute it and/or modify it under the terms of the GNU
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync * General Public License (GPL) as published by the Free Software
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync * Foundation, in version 2 as it comes in the "COPYING" file of the
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync *
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync * The contents of this file may alternatively be used under the terms
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync * of the Common Development and Distribution License Version 1.0
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync * (CDDL) only, as it comes in the "COPYING.CDDL" file of the
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync * VirtualBox OSE distribution, in which case the provisions of the
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync * CDDL are applicable instead of those of the GPL.
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync *
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync * You may elect to license modified versions of this file under the
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync * terms and conditions of either the GPL or the CDDL or both.
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync *
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync * Clara, CA 95054 USA or visit http://www.sun.com if you need
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync * additional information or have any questions.
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync */
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync/*******************************************************************************
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync* Header Files *
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync*******************************************************************************/
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync#include <iprt/rand.h>
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync#include <iprt/time.h>
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync#include <iprt/asm.h>
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync#include <iprt/err.h>
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync#include <iprt/assert.h>
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync#include <iprt/thread.h>
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync#include "internal/rand.h"
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync/*******************************************************************************
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync* Global Variables *
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync*******************************************************************************/
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync/** Lazy init. */
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsyncstatic volatile bool g_fInitialized = false;
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync/** The context variable for the fallback path. */
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsyncstatic uint32_t g_u32Ctx;
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync/*******************************************************************************
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync* Internal Functions *
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync*******************************************************************************/
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsyncstatic uint32_t rtRandGenBytesFallbackU31(uint32_t *pCtx);
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync/**
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync * Lazy initialization of the native and fallback random byte sources.
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync *
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync */
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsyncstatic void rtRandLazyInit(void)
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync{
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync /*
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync * Seed the fallback random code.
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync */
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync g_u32Ctx = (uint32_t)(ASMReadTSC() >> 8);
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync /*
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync * Call host specific init.
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync */
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync rtRandLazyInitNative();
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync g_fInitialized = true;
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync}
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync/**
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync * Internal wrapper for the native and generic random byte methods.
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync *
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync * @param pv Where to store the random bytes.
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync * @param cb Number of bytes to generate.
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync */
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsyncstatic void rtRandGenBytes(void *pv, size_t cb)
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync{
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync Assert(cb);
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync if (RT_UNLIKELY(!g_fInitialized))
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync rtRandLazyInit();
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync int rc = rtRandGenBytesNative(pv, cb);
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync if (RT_FAILURE(rc))
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync rtRandGenBytesFallback(pv, cb);
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync}
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync/**
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync * Fills a buffer with random bytes.
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync *
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync * @param pv Where to store the random bytes.
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync * @param cb Number of bytes to generate.
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync */
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsyncRTDECL(void) RTRandBytes(void *pv, size_t cb) RT_NO_THROW
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync{
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync if (cb)
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync rtRandGenBytes(pv, cb);
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync}
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync/**
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync * Generate a 32-bit unsigned random number in the set [u32First..u32Last].
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync *
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync * @returns The random number.
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync * @param u32First First number in the set.
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync * @param u32Last Last number in the set.
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync */
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsyncRTDECL(uint32_t) RTRandU32Ex(uint32_t u32First, uint32_t u32Last) RT_NO_THROW
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync{
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync union
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync {
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync uint32_t off;
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync uint8_t ab[5];
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync } u;
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync const uint32_t offLast = u32Last - u32First;
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync if (offLast == UINT32_MAX)
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync /* get 4 random bytes and return them raw. */
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync rtRandGenBytes(&u.ab, sizeof(u.off));
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync else if (!(offLast & UINT32_C(0xf0000000)))
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync {
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync /* get 4 random bytes and do simple squeeze. */
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync rtRandGenBytes(&u.ab, sizeof(u.off));
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync u.off %= offLast + 1;
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync u.off += u32First;
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync }
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync else
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync {
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync /* get 5 random bytes and do shifted squeeze. (this ain't perfect) */
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync rtRandGenBytes(&u.ab, sizeof(u.ab));
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync u.off %= (offLast >> 4) + 1;
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync u.off <<= 4;
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync u.off |= u.ab[4] & 0xf;
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync if (u.off > offLast)
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync u.off = offLast;
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync u.off += u32First;
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync }
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync return u.off;
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync}
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync/**
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync * Generate a 32-bit unsigned random number.
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync *
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync * @returns The random number.
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync */
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsyncRTDECL(uint32_t) RTRandU32(void) RT_NO_THROW
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync{
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync return RTRandU32Ex(0, UINT32_MAX);
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync}
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync/**
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync * Generate a 32-bit signed random number in the set [i32First..i32Last].
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync *
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync * @returns The random number.
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync * @param i32First First number in the set.
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync * @param i32Last Last number in the set.
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync */
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsyncRTDECL(int32_t) RTRandS32Ex(int32_t i32First, int32_t i32Last) RT_NO_THROW
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync{
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync if (i32First == INT32_MIN && i32Last == INT32_MAX)
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync return (int32_t)RTRandU32Ex(0, UINT32_MAX);
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync return RTRandU32Ex(0, i32Last - i32First) + i32First;
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync}
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync/**
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync * Generate a 32-bit signed random number.
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync *
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync * @returns The random number.
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync */
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsyncRTDECL(int32_t) RTRandS32(void) RT_NO_THROW
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync{
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync return (int32_t)RTRandU32Ex(0, UINT32_MAX);
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync}
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync/**
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync * Generate a 64-bit unsigned random number in the set [u64First..u64Last].
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync *
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync * @returns The random number.
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync * @param u64First First number in the set.
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync * @param u64Last Last number in the set.
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync */
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsyncRTDECL(uint64_t) RTRandU64Ex(uint64_t u64First, uint64_t u64Last) RT_NO_THROW
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync{
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync union
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync {
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync uint64_t off;
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync uint32_t off32;
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync uint8_t ab[9];
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync } u;
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync const uint64_t offLast = u64Last - u64First;
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync if (offLast == UINT64_MAX)
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync /* get 8 random bytes and return them raw. */
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync rtRandGenBytes(&u.ab, sizeof(u.off));
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync else if (!(offLast & UINT64_C(0xf000000000000000)))
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync {
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync /* get 8 random bytes and do simple squeeze. */
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync rtRandGenBytes(&u.ab, sizeof(u.off));
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync u.off %= offLast + 1;
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync u.off += u64First;
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync }
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync else
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync {
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync /* get 9 random bytes and do shifted squeeze. (this ain't perfect) */
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync rtRandGenBytes(&u.ab, sizeof(u.ab));
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync u.off %= (offLast >> 4) + 1;
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync u.off <<= 4;
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync u.off |= u.ab[8] & 0xf;
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync if (u.off > offLast)
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync u.off = offLast;
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync u.off += u64First;
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync }
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync return u.off;
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync}
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync
50f998bb47f333d10515d4c12ad01a4e92a0747bvboxsync/**
50f998bb47f333d10515d4c12ad01a4e92a0747bvboxsync * Generate a 64-bit unsigned random number.
50f998bb47f333d10515d4c12ad01a4e92a0747bvboxsync *
50f998bb47f333d10515d4c12ad01a4e92a0747bvboxsync * @returns The random number.
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync */
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsyncRTDECL(uint64_t) RTRandU64(void) RT_NO_THROW
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync{
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync return RTRandU64Ex(0, UINT64_MAX);
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync}
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync/**
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync * Generate a 64-bit signed random number in the set [i64First..i64Last].
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync *
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync * @returns The random number.
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync * @param i64First First number in the set.
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync * @param i64Last Last number in the set.
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync */
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsyncRTDECL(int64_t) RTRandS64Ex(int64_t i64First, int64_t i64Last) RT_NO_THROW
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync{
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync if (i64First == INT64_MIN && i64Last == INT64_MAX)
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync return (int64_t)RTRandU64Ex(0, UINT64_MAX);
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync return (int64_t)RTRandU64Ex(0, i64Last - i64First) + i64First;
81cfcb51c89626fd5d331d92dcec81c94a5e9d2fvboxsync}
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync/**
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync * Generate a 64-bit signed random number.
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync *
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync * @returns The random number.
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync */
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsyncRTDECL(int64_t) RTRandS64(void) RT_NO_THROW
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync{
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync return (int64_t)RTRandU64Ex(0, UINT64_MAX);
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync}
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync/**
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync * Fallback random byte source.
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync *
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync * @param pv Where to store the random bytes.
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync * @param cb Number of bytes to generate.
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync */
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsyncvoid rtRandGenBytesFallback(void *pv, size_t cb) RT_NO_THROW
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync{
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync uint64_t u64Last = 0;
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync uint8_t *pb = (uint8_t *)pv;
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync for (unsigned i = 0;; i++)
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync {
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync uint32_t u32 = rtRandGenBytesFallbackU31(&g_u32Ctx);
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync *pb++ = (uint8_t)u32;
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync if (!--cb)
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync break;
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync u32 >>= 8;
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync *pb++ = (uint8_t)u32;
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync if (!--cb)
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync break;
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync u32 >>= 8;
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync *pb++ = (uint8_t)u32;
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync if (!--cb)
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync break;
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync /*
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync * Is this really a good idea? Looks like we cannot
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync * quite trust the lower bits here for instance...
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync */
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync if (!(i % 3))
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync {
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync uint64_t u64 = ASMReadTSC();
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync uint64_t u64Delta = u64 - u64Last;
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync if (u64Delta > 0xff)
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync {
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync u32 >>= 8;
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync *pb++ = ((uint8_t)u64 >> 5) | (u32 << 3);
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync if (!--cb)
e2bd93b4f9c38c9b01eb960ba7bc1fc9c4d38ce8vboxsync break;
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync u64Last = u64;
e2bd93b4f9c38c9b01eb960ba7bc1fc9c4d38ce8vboxsync }
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync }
e2bd93b4f9c38c9b01eb960ba7bc1fc9c4d38ce8vboxsync }
f091ce66ee934d599f16056078a9a76d7286b959vboxsync}
f091ce66ee934d599f16056078a9a76d7286b959vboxsync
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync/*-
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync * Copyright (c) 1990, 1993
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync * The Regents of the University of California. All rights reserved.
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync *
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync * Redistribution and use in source and binary forms, with or without
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync * modification, are permitted provided that the following conditions
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync * are met:
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync * 1. Redistributions of source code must retain the above copyright
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync * notice, this list of conditions and the following disclaimer.
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync * 2. Redistributions in binary form must reproduce the above copyright
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync * notice, this list of conditions and the following disclaimer in the
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync * documentation and/or other materials provided with the distribution.
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync * 4. Neither the name of the University nor the names of its contributors
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync * may be used to endorse or promote products derived from this software
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync * without specific prior written permission.
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync *
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
021c939a9e3f688c0c3bbd759354be906bb2dcabvboxsync * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
021c939a9e3f688c0c3bbd759354be906bb2dcabvboxsync * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
021c939a9e3f688c0c3bbd759354be906bb2dcabvboxsync * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
021c939a9e3f688c0c3bbd759354be906bb2dcabvboxsync * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
021c939a9e3f688c0c3bbd759354be906bb2dcabvboxsync * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
021c939a9e3f688c0c3bbd759354be906bb2dcabvboxsync * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
021c939a9e3f688c0c3bbd759354be906bb2dcabvboxsync * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
021c939a9e3f688c0c3bbd759354be906bb2dcabvboxsync * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
021c939a9e3f688c0c3bbd759354be906bb2dcabvboxsync * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
021c939a9e3f688c0c3bbd759354be906bb2dcabvboxsync * SUCH DAMAGE.
021c939a9e3f688c0c3bbd759354be906bb2dcabvboxsync */
021c939a9e3f688c0c3bbd759354be906bb2dcabvboxsync
021c939a9e3f688c0c3bbd759354be906bb2dcabvboxsync/* The core of:
021c939a9e3f688c0c3bbd759354be906bb2dcabvboxsync__FBSDID("$FreeBSD: /repoman/r/ncvs/src/lib/libc/stdlib/rand.c,v 1.16 2007/01/09 00:28:10 imp Exp $");
021c939a9e3f688c0c3bbd759354be906bb2dcabvboxsync*/
021c939a9e3f688c0c3bbd759354be906bb2dcabvboxsync
021c939a9e3f688c0c3bbd759354be906bb2dcabvboxsync/**
021c939a9e3f688c0c3bbd759354be906bb2dcabvboxsync * Generates an unsigned 31 bit pseudo random number.
021c939a9e3f688c0c3bbd759354be906bb2dcabvboxsync *
021c939a9e3f688c0c3bbd759354be906bb2dcabvboxsync * @returns pseudo random number.
021c939a9e3f688c0c3bbd759354be906bb2dcabvboxsync * @param pCtx The context.
021c939a9e3f688c0c3bbd759354be906bb2dcabvboxsync */
021c939a9e3f688c0c3bbd759354be906bb2dcabvboxsyncstatic uint32_t rtRandGenBytesFallbackU31(uint32_t *pCtx)
021c939a9e3f688c0c3bbd759354be906bb2dcabvboxsync{
021c939a9e3f688c0c3bbd759354be906bb2dcabvboxsync /*
021c939a9e3f688c0c3bbd759354be906bb2dcabvboxsync * Compute x = (7^5 * x) mod (2^31 - 1)
021c939a9e3f688c0c3bbd759354be906bb2dcabvboxsync * without overflowing 31 bits:
021c939a9e3f688c0c3bbd759354be906bb2dcabvboxsync * (2^31 - 1) = 127773 * (7^5) + 2836
021c939a9e3f688c0c3bbd759354be906bb2dcabvboxsync *
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync * From "Random number generators: good ones are hard to find", Park and
d1d4bf58f99da14d0aaa7bcc728a359c8a7eb7bdvboxsync * Miller, Communications of the ACM, vol. 31, no. 10, October 1988, p. 1195.
d1d4bf58f99da14d0aaa7bcc728a359c8a7eb7bdvboxsync */
d1d4bf58f99da14d0aaa7bcc728a359c8a7eb7bdvboxsync uint32_t Ctx = *pCtx;
d1d4bf58f99da14d0aaa7bcc728a359c8a7eb7bdvboxsync if (!Ctx) /* must not be zero. */
d1d4bf58f99da14d0aaa7bcc728a359c8a7eb7bdvboxsync Ctx = 0x20070212;
d1d4bf58f99da14d0aaa7bcc728a359c8a7eb7bdvboxsync uint32_t Hi = Ctx / 127773;
d1d4bf58f99da14d0aaa7bcc728a359c8a7eb7bdvboxsync uint32_t Lo = Ctx % 127773;
d1d4bf58f99da14d0aaa7bcc728a359c8a7eb7bdvboxsync int32_t x = 16807 * Lo - 2836 * Hi;
d1d4bf58f99da14d0aaa7bcc728a359c8a7eb7bdvboxsync if (x < 0)
021c939a9e3f688c0c3bbd759354be906bb2dcabvboxsync x += INT32_MAX;
021c939a9e3f688c0c3bbd759354be906bb2dcabvboxsync *pCtx = x;
021c939a9e3f688c0c3bbd759354be906bb2dcabvboxsync return x % INT32_MAX;
021c939a9e3f688c0c3bbd759354be906bb2dcabvboxsync}
021c939a9e3f688c0c3bbd759354be906bb2dcabvboxsync
021c939a9e3f688c0c3bbd759354be906bb2dcabvboxsync