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