xref: /aoo41x/main/sal/rtl/source/random.c (revision cdf0e10c)
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