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