1*cdf0e10cSrcweir /************************************************************************* 2*cdf0e10cSrcweir * 3*cdf0e10cSrcweir * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4*cdf0e10cSrcweir * 5*cdf0e10cSrcweir * Copyright 2000, 2010 Oracle and/or its affiliates. 6*cdf0e10cSrcweir * 7*cdf0e10cSrcweir * OpenOffice.org - a multi-platform office productivity suite 8*cdf0e10cSrcweir * 9*cdf0e10cSrcweir * This file is part of OpenOffice.org. 10*cdf0e10cSrcweir * 11*cdf0e10cSrcweir * OpenOffice.org is free software: you can redistribute it and/or modify 12*cdf0e10cSrcweir * it under the terms of the GNU Lesser General Public License version 3 13*cdf0e10cSrcweir * only, as published by the Free Software Foundation. 14*cdf0e10cSrcweir * 15*cdf0e10cSrcweir * OpenOffice.org is distributed in the hope that it will be useful, 16*cdf0e10cSrcweir * but WITHOUT ANY WARRANTY; without even the implied warranty of 17*cdf0e10cSrcweir * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 18*cdf0e10cSrcweir * GNU Lesser General Public License version 3 for more details 19*cdf0e10cSrcweir * (a copy is included in the LICENSE file that accompanied this code). 20*cdf0e10cSrcweir * 21*cdf0e10cSrcweir * You should have received a copy of the GNU Lesser General Public License 22*cdf0e10cSrcweir * version 3 along with OpenOffice.org. If not, see 23*cdf0e10cSrcweir * <http://www.openoffice.org/license.html> 24*cdf0e10cSrcweir * for a copy of the LGPLv3 License. 25*cdf0e10cSrcweir * 26*cdf0e10cSrcweir ************************************************************************/ 27*cdf0e10cSrcweir 28*cdf0e10cSrcweir #define _RTL_RANDOM_C_ "$Revision: 1.6 $" 29*cdf0e10cSrcweir 30*cdf0e10cSrcweir #include <sal/types.h> 31*cdf0e10cSrcweir #include <osl/thread.h> 32*cdf0e10cSrcweir #include <osl/time.h> 33*cdf0e10cSrcweir #include <rtl/alloc.h> 34*cdf0e10cSrcweir #include <rtl/digest.h> 35*cdf0e10cSrcweir #include <rtl/random.h> 36*cdf0e10cSrcweir #include <osl/time.h> 37*cdf0e10cSrcweir 38*cdf0e10cSrcweir /*======================================================================== 39*cdf0e10cSrcweir * 40*cdf0e10cSrcweir * rtlRandom internals. 41*cdf0e10cSrcweir * 42*cdf0e10cSrcweir *======================================================================*/ 43*cdf0e10cSrcweir #define RTL_RANDOM_RNG_1(a) ((a) * 16807L) 44*cdf0e10cSrcweir #define RTL_RANDOM_RNG_2(a) ((a) * 65539L) 45*cdf0e10cSrcweir 46*cdf0e10cSrcweir #define RTL_RANDOM_RNG(x, y, z) \ 47*cdf0e10cSrcweir { \ 48*cdf0e10cSrcweir (x) = 170 * ((x) % 178) - 63 * ((x) / 178); \ 49*cdf0e10cSrcweir if ((x) < 0) (x) += 30328L; \ 50*cdf0e10cSrcweir \ 51*cdf0e10cSrcweir (y) = 171 * ((y) % 177) - 2 * ((y) / 177); \ 52*cdf0e10cSrcweir if ((y) < 0) (y) += 30269L; \ 53*cdf0e10cSrcweir \ 54*cdf0e10cSrcweir (z) = 172 * ((z) % 176) - 35 * ((z) / 176); \ 55*cdf0e10cSrcweir if ((z) < 0) (z) += 30307L; \ 56*cdf0e10cSrcweir } 57*cdf0e10cSrcweir 58*cdf0e10cSrcweir /** RandomData_Impl. 59*cdf0e10cSrcweir */ 60*cdf0e10cSrcweir typedef struct random_data_impl_st 61*cdf0e10cSrcweir { 62*cdf0e10cSrcweir sal_Int16 m_nX; 63*cdf0e10cSrcweir sal_Int16 m_nY; 64*cdf0e10cSrcweir sal_Int16 m_nZ; 65*cdf0e10cSrcweir } RandomData_Impl; 66*cdf0e10cSrcweir 67*cdf0e10cSrcweir /** __rtl_random_data. 68*cdf0e10cSrcweir */ 69*cdf0e10cSrcweir static double __rtl_random_data (RandomData_Impl *pImpl); 70*cdf0e10cSrcweir 71*cdf0e10cSrcweir /** RandomPool_Impl. 72*cdf0e10cSrcweir */ 73*cdf0e10cSrcweir #define RTL_RANDOM_DIGEST rtl_Digest_AlgorithmMD5 74*cdf0e10cSrcweir #define RTL_RANDOM_SIZE_DIGEST RTL_DIGEST_LENGTH_MD5 75*cdf0e10cSrcweir #define RTL_RANDOM_SIZE_POOL 1023 76*cdf0e10cSrcweir 77*cdf0e10cSrcweir typedef struct random_pool_impl_st 78*cdf0e10cSrcweir { 79*cdf0e10cSrcweir rtlDigest m_hDigest; 80*cdf0e10cSrcweir sal_uInt8 m_pDigest[RTL_RANDOM_SIZE_DIGEST]; 81*cdf0e10cSrcweir sal_uInt8 m_pData[RTL_RANDOM_SIZE_POOL + 1]; 82*cdf0e10cSrcweir sal_uInt32 m_nData; 83*cdf0e10cSrcweir sal_uInt32 m_nIndex; 84*cdf0e10cSrcweir sal_uInt32 m_nCount; 85*cdf0e10cSrcweir } RandomPool_Impl; 86*cdf0e10cSrcweir 87*cdf0e10cSrcweir /** __rtl_random_initPool. 88*cdf0e10cSrcweir */ 89*cdf0e10cSrcweir static sal_Bool __rtl_random_initPool ( 90*cdf0e10cSrcweir RandomPool_Impl *pImpl); 91*cdf0e10cSrcweir 92*cdf0e10cSrcweir /** __rtl_random_seedPool. 93*cdf0e10cSrcweir */ 94*cdf0e10cSrcweir static void __rtl_random_seedPool ( 95*cdf0e10cSrcweir RandomPool_Impl *pImpl, const sal_uInt8 *pBuffer, sal_Size nBufLen); 96*cdf0e10cSrcweir 97*cdf0e10cSrcweir /** __rtl_random_readPool. 98*cdf0e10cSrcweir */ 99*cdf0e10cSrcweir static void __rtl_random_readPool ( 100*cdf0e10cSrcweir RandomPool_Impl *pImpl, sal_uInt8 *pBuffer, sal_Size nBufLen); 101*cdf0e10cSrcweir 102*cdf0e10cSrcweir /* 103*cdf0e10cSrcweir * __rtl_random_data. 104*cdf0e10cSrcweir */ 105*cdf0e10cSrcweir static double __rtl_random_data (RandomData_Impl *pImpl) 106*cdf0e10cSrcweir { 107*cdf0e10cSrcweir register double random; 108*cdf0e10cSrcweir 109*cdf0e10cSrcweir RTL_RANDOM_RNG (pImpl->m_nX, pImpl->m_nY, pImpl->m_nZ); 110*cdf0e10cSrcweir random = (((double)(pImpl->m_nX) / 30328.0) + 111*cdf0e10cSrcweir ((double)(pImpl->m_nY) / 30269.0) + 112*cdf0e10cSrcweir ((double)(pImpl->m_nZ) / 30307.0) ); 113*cdf0e10cSrcweir 114*cdf0e10cSrcweir random -= ((double)((sal_uInt32)(random))); 115*cdf0e10cSrcweir return (random); 116*cdf0e10cSrcweir } 117*cdf0e10cSrcweir 118*cdf0e10cSrcweir /* 119*cdf0e10cSrcweir * __rtl_random_initPool. 120*cdf0e10cSrcweir */ 121*cdf0e10cSrcweir static sal_Bool __rtl_random_initPool (RandomPool_Impl *pImpl) 122*cdf0e10cSrcweir { 123*cdf0e10cSrcweir pImpl->m_hDigest = rtl_digest_create (RTL_RANDOM_DIGEST); 124*cdf0e10cSrcweir if (pImpl->m_hDigest) 125*cdf0e10cSrcweir { 126*cdf0e10cSrcweir oslThreadIdentifier id; 127*cdf0e10cSrcweir TimeValue tv; 128*cdf0e10cSrcweir RandomData_Impl rd; 129*cdf0e10cSrcweir double seed; 130*cdf0e10cSrcweir 131*cdf0e10cSrcweir /* The use of uninitialized stack variables as a way to 132*cdf0e10cSrcweir * enhance the entropy of the random pool triggers 133*cdf0e10cSrcweir * memory checkers like purify and valgrind. 134*cdf0e10cSrcweir */ 135*cdf0e10cSrcweir 136*cdf0e10cSrcweir /* 137*cdf0e10cSrcweir __rtl_random_seedPool (pImpl, (sal_uInt8*)&id, sizeof(id)); 138*cdf0e10cSrcweir __rtl_random_seedPool (pImpl, (sal_uInt8*)&tv, sizeof(tv)); 139*cdf0e10cSrcweir __rtl_random_seedPool (pImpl, (sal_uInt8*)&rd, sizeof(rd)); 140*cdf0e10cSrcweir */ 141*cdf0e10cSrcweir 142*cdf0e10cSrcweir id = osl_getThreadIdentifier (NULL); 143*cdf0e10cSrcweir id = RTL_RANDOM_RNG_2(RTL_RANDOM_RNG_1(id)); 144*cdf0e10cSrcweir __rtl_random_seedPool (pImpl, (sal_uInt8*)&id, sizeof(id)); 145*cdf0e10cSrcweir 146*cdf0e10cSrcweir osl_getSystemTime (&tv); 147*cdf0e10cSrcweir tv.Seconds = RTL_RANDOM_RNG_2(tv.Seconds); 148*cdf0e10cSrcweir tv.Nanosec = RTL_RANDOM_RNG_2(tv.Nanosec); 149*cdf0e10cSrcweir __rtl_random_seedPool (pImpl, (sal_uInt8*)&tv, sizeof(tv)); 150*cdf0e10cSrcweir 151*cdf0e10cSrcweir rd.m_nX = (sal_Int16)(((id >> 1) << 1) + 1); 152*cdf0e10cSrcweir rd.m_nY = (sal_Int16)(((tv.Seconds >> 1) << 1) + 1); 153*cdf0e10cSrcweir rd.m_nZ = (sal_Int16)(((tv.Nanosec >> 1) << 1) + 1); 154*cdf0e10cSrcweir __rtl_random_seedPool (pImpl, (sal_uInt8*)&rd, sizeof(rd)); 155*cdf0e10cSrcweir 156*cdf0e10cSrcweir while (pImpl->m_nData < RTL_RANDOM_SIZE_POOL) 157*cdf0e10cSrcweir { 158*cdf0e10cSrcweir seed = __rtl_random_data (&rd); 159*cdf0e10cSrcweir __rtl_random_seedPool (pImpl, (sal_uInt8*)&seed, sizeof(seed)); 160*cdf0e10cSrcweir } 161*cdf0e10cSrcweir return sal_True; 162*cdf0e10cSrcweir } 163*cdf0e10cSrcweir return sal_False; 164*cdf0e10cSrcweir } 165*cdf0e10cSrcweir 166*cdf0e10cSrcweir /* 167*cdf0e10cSrcweir * __rtl_random_seedPool. 168*cdf0e10cSrcweir */ 169*cdf0e10cSrcweir static void __rtl_random_seedPool ( 170*cdf0e10cSrcweir RandomPool_Impl *pImpl, const sal_uInt8 *pBuffer, sal_Size nBufLen) 171*cdf0e10cSrcweir { 172*cdf0e10cSrcweir sal_Size i; 173*cdf0e10cSrcweir sal_sSize j, k; 174*cdf0e10cSrcweir 175*cdf0e10cSrcweir for (i = 0; i < nBufLen; i += RTL_RANDOM_SIZE_DIGEST) 176*cdf0e10cSrcweir { 177*cdf0e10cSrcweir j = nBufLen - i; 178*cdf0e10cSrcweir if (j > RTL_RANDOM_SIZE_DIGEST) 179*cdf0e10cSrcweir j = RTL_RANDOM_SIZE_DIGEST; 180*cdf0e10cSrcweir 181*cdf0e10cSrcweir rtl_digest_update ( 182*cdf0e10cSrcweir pImpl->m_hDigest, pImpl->m_pDigest, RTL_RANDOM_SIZE_DIGEST); 183*cdf0e10cSrcweir 184*cdf0e10cSrcweir k = (pImpl->m_nIndex + j) - RTL_RANDOM_SIZE_POOL; 185*cdf0e10cSrcweir if (k > 0) 186*cdf0e10cSrcweir { 187*cdf0e10cSrcweir rtl_digest_update ( 188*cdf0e10cSrcweir pImpl->m_hDigest, &(pImpl->m_pData[pImpl->m_nIndex]), j - k); 189*cdf0e10cSrcweir rtl_digest_update ( 190*cdf0e10cSrcweir pImpl->m_hDigest, &(pImpl->m_pData[0]), k); 191*cdf0e10cSrcweir } 192*cdf0e10cSrcweir else 193*cdf0e10cSrcweir { 194*cdf0e10cSrcweir rtl_digest_update ( 195*cdf0e10cSrcweir pImpl->m_hDigest, &(pImpl->m_pData[pImpl->m_nIndex]), j); 196*cdf0e10cSrcweir } 197*cdf0e10cSrcweir 198*cdf0e10cSrcweir rtl_digest_update (pImpl->m_hDigest, pBuffer, j); 199*cdf0e10cSrcweir pBuffer += j; 200*cdf0e10cSrcweir 201*cdf0e10cSrcweir rtl_digest_get ( 202*cdf0e10cSrcweir pImpl->m_hDigest, pImpl->m_pDigest, RTL_RANDOM_SIZE_DIGEST); 203*cdf0e10cSrcweir for (k = 0; k < j; k++) 204*cdf0e10cSrcweir { 205*cdf0e10cSrcweir pImpl->m_pData[pImpl->m_nIndex++] ^= pImpl->m_pDigest[k]; 206*cdf0e10cSrcweir if (pImpl->m_nIndex >= RTL_RANDOM_SIZE_POOL) 207*cdf0e10cSrcweir { 208*cdf0e10cSrcweir pImpl->m_nData = RTL_RANDOM_SIZE_POOL; 209*cdf0e10cSrcweir pImpl->m_nIndex = 0; 210*cdf0e10cSrcweir } 211*cdf0e10cSrcweir } 212*cdf0e10cSrcweir } 213*cdf0e10cSrcweir 214*cdf0e10cSrcweir if (pImpl->m_nIndex > pImpl->m_nData) 215*cdf0e10cSrcweir pImpl->m_nData = pImpl->m_nIndex; 216*cdf0e10cSrcweir } 217*cdf0e10cSrcweir 218*cdf0e10cSrcweir /* 219*cdf0e10cSrcweir * __rtl_random_readPool. 220*cdf0e10cSrcweir */ 221*cdf0e10cSrcweir static void __rtl_random_readPool ( 222*cdf0e10cSrcweir RandomPool_Impl *pImpl, sal_uInt8 *pBuffer, sal_Size nBufLen) 223*cdf0e10cSrcweir { 224*cdf0e10cSrcweir sal_Int32 j, k; 225*cdf0e10cSrcweir 226*cdf0e10cSrcweir while (nBufLen > 0) 227*cdf0e10cSrcweir { 228*cdf0e10cSrcweir j = nBufLen; 229*cdf0e10cSrcweir if (j > RTL_RANDOM_SIZE_DIGEST/2) 230*cdf0e10cSrcweir j = RTL_RANDOM_SIZE_DIGEST/2; 231*cdf0e10cSrcweir nBufLen -= j; 232*cdf0e10cSrcweir 233*cdf0e10cSrcweir rtl_digest_update ( 234*cdf0e10cSrcweir pImpl->m_hDigest, 235*cdf0e10cSrcweir &(pImpl->m_pDigest[RTL_RANDOM_SIZE_DIGEST/2]), 236*cdf0e10cSrcweir RTL_RANDOM_SIZE_DIGEST/2); 237*cdf0e10cSrcweir 238*cdf0e10cSrcweir k = (pImpl->m_nIndex + j) - pImpl->m_nData; 239*cdf0e10cSrcweir if (k > 0) 240*cdf0e10cSrcweir { 241*cdf0e10cSrcweir rtl_digest_update ( 242*cdf0e10cSrcweir pImpl->m_hDigest, &(pImpl->m_pData[pImpl->m_nIndex]), j - k); 243*cdf0e10cSrcweir rtl_digest_update ( 244*cdf0e10cSrcweir pImpl->m_hDigest, &(pImpl->m_pData[0]), k); 245*cdf0e10cSrcweir } 246*cdf0e10cSrcweir else 247*cdf0e10cSrcweir { 248*cdf0e10cSrcweir rtl_digest_update ( 249*cdf0e10cSrcweir pImpl->m_hDigest, &(pImpl->m_pData[pImpl->m_nIndex]), j); 250*cdf0e10cSrcweir } 251*cdf0e10cSrcweir 252*cdf0e10cSrcweir rtl_digest_get ( 253*cdf0e10cSrcweir pImpl->m_hDigest, pImpl->m_pDigest, RTL_RANDOM_SIZE_DIGEST); 254*cdf0e10cSrcweir for (k = 0; k < j; k++) 255*cdf0e10cSrcweir { 256*cdf0e10cSrcweir if (pImpl->m_nIndex >= pImpl->m_nData) pImpl->m_nIndex = 0; 257*cdf0e10cSrcweir pImpl->m_pData[pImpl->m_nIndex++] ^= pImpl->m_pDigest[k]; 258*cdf0e10cSrcweir *pBuffer++ = pImpl->m_pDigest[k + RTL_RANDOM_SIZE_DIGEST/2]; 259*cdf0e10cSrcweir } 260*cdf0e10cSrcweir } 261*cdf0e10cSrcweir 262*cdf0e10cSrcweir pImpl->m_nCount++; 263*cdf0e10cSrcweir rtl_digest_update ( 264*cdf0e10cSrcweir pImpl->m_hDigest, &(pImpl->m_nCount), sizeof(pImpl->m_nCount)); 265*cdf0e10cSrcweir rtl_digest_update ( 266*cdf0e10cSrcweir pImpl->m_hDigest, pImpl->m_pDigest, RTL_RANDOM_SIZE_DIGEST); 267*cdf0e10cSrcweir rtl_digest_get ( 268*cdf0e10cSrcweir pImpl->m_hDigest, pImpl->m_pDigest, RTL_RANDOM_SIZE_DIGEST); 269*cdf0e10cSrcweir } 270*cdf0e10cSrcweir 271*cdf0e10cSrcweir /*======================================================================== 272*cdf0e10cSrcweir * 273*cdf0e10cSrcweir * rtlRandom implementation. 274*cdf0e10cSrcweir * 275*cdf0e10cSrcweir *======================================================================*/ 276*cdf0e10cSrcweir /* 277*cdf0e10cSrcweir * rtl_random_createPool. 278*cdf0e10cSrcweir */ 279*cdf0e10cSrcweir rtlRandomPool SAL_CALL rtl_random_createPool (void) 280*cdf0e10cSrcweir { 281*cdf0e10cSrcweir RandomPool_Impl *pImpl = (RandomPool_Impl*)NULL; 282*cdf0e10cSrcweir pImpl = (RandomPool_Impl*)rtl_allocateZeroMemory (sizeof(RandomPool_Impl)); 283*cdf0e10cSrcweir if (pImpl) 284*cdf0e10cSrcweir { 285*cdf0e10cSrcweir if (!__rtl_random_initPool (pImpl)) 286*cdf0e10cSrcweir { 287*cdf0e10cSrcweir rtl_freeZeroMemory (pImpl, sizeof(RandomPool_Impl)); 288*cdf0e10cSrcweir pImpl = (RandomPool_Impl*)NULL; 289*cdf0e10cSrcweir } 290*cdf0e10cSrcweir } 291*cdf0e10cSrcweir return ((rtlRandomPool)pImpl); 292*cdf0e10cSrcweir } 293*cdf0e10cSrcweir 294*cdf0e10cSrcweir /* 295*cdf0e10cSrcweir * rtl_random_destroyPool. 296*cdf0e10cSrcweir */ 297*cdf0e10cSrcweir void SAL_CALL rtl_random_destroyPool (rtlRandomPool Pool) 298*cdf0e10cSrcweir { 299*cdf0e10cSrcweir RandomPool_Impl *pImpl = (RandomPool_Impl *)Pool; 300*cdf0e10cSrcweir if (pImpl) 301*cdf0e10cSrcweir { 302*cdf0e10cSrcweir rtl_digest_destroy (pImpl->m_hDigest); 303*cdf0e10cSrcweir rtl_freeZeroMemory (pImpl, sizeof (RandomPool_Impl)); 304*cdf0e10cSrcweir } 305*cdf0e10cSrcweir } 306*cdf0e10cSrcweir 307*cdf0e10cSrcweir /* 308*cdf0e10cSrcweir * rtl_random_addBytes. 309*cdf0e10cSrcweir */ 310*cdf0e10cSrcweir rtlRandomError SAL_CALL rtl_random_addBytes ( 311*cdf0e10cSrcweir rtlRandomPool Pool, const void *Buffer, sal_Size Bytes) 312*cdf0e10cSrcweir { 313*cdf0e10cSrcweir RandomPool_Impl *pImpl = (RandomPool_Impl *)Pool; 314*cdf0e10cSrcweir const sal_uInt8 *pBuffer = (const sal_uInt8 *)Buffer; 315*cdf0e10cSrcweir 316*cdf0e10cSrcweir if ((pImpl == NULL) || (pBuffer == NULL)) 317*cdf0e10cSrcweir return rtl_Random_E_Argument; 318*cdf0e10cSrcweir 319*cdf0e10cSrcweir __rtl_random_seedPool (pImpl, pBuffer, Bytes); 320*cdf0e10cSrcweir return rtl_Random_E_None; 321*cdf0e10cSrcweir } 322*cdf0e10cSrcweir 323*cdf0e10cSrcweir /* 324*cdf0e10cSrcweir * rtl_random_getBytes. 325*cdf0e10cSrcweir */ 326*cdf0e10cSrcweir rtlRandomError SAL_CALL rtl_random_getBytes ( 327*cdf0e10cSrcweir rtlRandomPool Pool, void *Buffer, sal_Size Bytes) 328*cdf0e10cSrcweir { 329*cdf0e10cSrcweir RandomPool_Impl *pImpl = (RandomPool_Impl *)Pool; 330*cdf0e10cSrcweir sal_uInt8 *pBuffer = (sal_uInt8 *)Buffer; 331*cdf0e10cSrcweir 332*cdf0e10cSrcweir if ((pImpl == NULL) || (pBuffer == NULL)) 333*cdf0e10cSrcweir return rtl_Random_E_Argument; 334*cdf0e10cSrcweir 335*cdf0e10cSrcweir __rtl_random_readPool (pImpl, pBuffer, Bytes); 336*cdf0e10cSrcweir return rtl_Random_E_None; 337*cdf0e10cSrcweir } 338*cdf0e10cSrcweir 339