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