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