/src/imagemagick/MagickCore/random.c
Line | Count | Source |
1 | | /* |
2 | | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% |
3 | | % % |
4 | | % % |
5 | | % RRRR AAA N N DDDD OOO M M % |
6 | | % R R A A NN N D D O O MM MM % |
7 | | % RRRR AAAAA N N N D D O O M M M % |
8 | | % R R A A N NN D D O O M M % |
9 | | % R R A A N N DDDD OOO M M % |
10 | | % % |
11 | | % % |
12 | | % MagickCore Methods to Generate Random Numbers % |
13 | | % % |
14 | | % Software Design % |
15 | | % Cristy % |
16 | | % December 2001 % |
17 | | % % |
18 | | % % |
19 | | % Copyright @ 1999 ImageMagick Studio LLC, a non-profit organization % |
20 | | % dedicated to making software imaging solutions freely available. % |
21 | | % % |
22 | | % You may not use this file except in compliance with the License. You may % |
23 | | % obtain a copy of the License at % |
24 | | % % |
25 | | % https://imagemagick.org/license/ % |
26 | | % % |
27 | | % Unless required by applicable law or agreed to in writing, software % |
28 | | % distributed under the License is distributed on an "AS IS" BASIS, % |
29 | | % WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. % |
30 | | % See the License for the specific language governing permissions and % |
31 | | % limitations under the License. % |
32 | | % % |
33 | | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% |
34 | | % |
35 | | % The generation of random numbers is too important to be left to chance. |
36 | | % -- Tom Christiansen <tchrist@mox.perl.com> |
37 | | % |
38 | | % |
39 | | */ |
40 | | |
41 | | /* |
42 | | Include declarations. |
43 | | */ |
44 | | #if defined(__VMS) |
45 | | #include <time.h> |
46 | | #endif |
47 | | #if defined(__MINGW32__) |
48 | | #include <sys/time.h> |
49 | | #endif |
50 | | #include "MagickCore/studio.h" |
51 | | #include "MagickCore/exception.h" |
52 | | #include "MagickCore/exception-private.h" |
53 | | #include "MagickCore/image-private.h" |
54 | | #include "MagickCore/memory_.h" |
55 | | #include "MagickCore/memory-private.h" |
56 | | #include "MagickCore/random_.h" |
57 | | #include "MagickCore/random-private.h" |
58 | | #include "MagickCore/resource_.h" |
59 | | #include "MagickCore/semaphore.h" |
60 | | #include "MagickCore/signature-private.h" |
61 | | #include "MagickCore/string_.h" |
62 | | #include "MagickCore/thread_.h" |
63 | | #include "MagickCore/thread-private.h" |
64 | | #include "MagickCore/timer-private.h" |
65 | | #include "MagickCore/utility.h" |
66 | | #include "MagickCore/utility-private.h" |
67 | | #if defined(MAGICKCORE_HAVE_GETENTROPY) |
68 | | #include <sys/random.h> |
69 | | #endif |
70 | | /* |
71 | | Define declarations. |
72 | | */ |
73 | | #define PseudoRandomHash SHA256Hash |
74 | | #define RandomEntropyLevel 9 |
75 | | #define RandomFilename "reservoir.xdm" |
76 | | #define RandomFiletype "random" |
77 | 15.7k | #define RandomProtocolMajorVersion 1 |
78 | 15.7k | #define RandomProtocolMinorVersion 0 |
79 | | |
80 | | /* |
81 | | Typedef declarations. |
82 | | */ |
83 | | struct _RandomInfo |
84 | | { |
85 | | SignatureInfo |
86 | | *signature_info; |
87 | | |
88 | | StringInfo |
89 | | *nonce, |
90 | | *reservoir; |
91 | | |
92 | | size_t |
93 | | i; |
94 | | |
95 | | MagickSizeType |
96 | | seed[4]; |
97 | | |
98 | | double |
99 | | normalize; |
100 | | |
101 | | unsigned long |
102 | | secret_key; |
103 | | |
104 | | unsigned short |
105 | | protocol_major, |
106 | | protocol_minor; |
107 | | |
108 | | SemaphoreInfo |
109 | | *semaphore; |
110 | | |
111 | | time_t |
112 | | timestamp; |
113 | | |
114 | | size_t |
115 | | signature; |
116 | | }; |
117 | | |
118 | | /* |
119 | | External declarations. |
120 | | */ |
121 | | #if defined(__APPLE__) && !defined(TARGET_OS_IPHONE) |
122 | | #include <crt_externs.h> |
123 | | #define environ (*_NSGetEnviron()) |
124 | | #endif |
125 | | |
126 | | #if !defined(MAGICKCORE_WINDOWS_SUPPORT) |
127 | | extern char |
128 | | **environ; |
129 | | #endif |
130 | | |
131 | | /* |
132 | | Global declarations. |
133 | | */ |
134 | | static SemaphoreInfo |
135 | | *random_semaphore = (SemaphoreInfo *) NULL; |
136 | | |
137 | | static unsigned long |
138 | | secret_key = ~0UL; |
139 | | |
140 | | static MagickBooleanType |
141 | | gather_true_random = MagickFalse; |
142 | | |
143 | | /* |
144 | | Forward declarations. |
145 | | */ |
146 | | static StringInfo |
147 | | *GenerateEntropicChaos(RandomInfo *); |
148 | | |
149 | | /* |
150 | | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% |
151 | | % % |
152 | | % % |
153 | | % % |
154 | | % A c q u i r e R a n d o m I n f o % |
155 | | % % |
156 | | % % |
157 | | % % |
158 | | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% |
159 | | % |
160 | | % AcquireRandomInfo() allocates the RandomInfo structure. |
161 | | % |
162 | | % The format of the AcquireRandomInfo method is: |
163 | | % |
164 | | % RandomInfo *AcquireRandomInfo(void) |
165 | | % |
166 | | */ |
167 | | MagickExport RandomInfo *AcquireRandomInfo(void) |
168 | 15.7k | { |
169 | 15.7k | const StringInfo |
170 | 15.7k | *digest; |
171 | | |
172 | 15.7k | RandomInfo |
173 | 15.7k | *random_info; |
174 | | |
175 | 15.7k | StringInfo |
176 | 15.7k | *entropy, |
177 | 15.7k | *key, |
178 | 15.7k | *nonce; |
179 | | |
180 | 15.7k | random_info=(RandomInfo *) AcquireCriticalMemory(sizeof(*random_info)); |
181 | 15.7k | (void) memset(random_info,0,sizeof(*random_info)); |
182 | 15.7k | random_info->signature_info=AcquireSignatureInfo(); |
183 | 15.7k | random_info->nonce=AcquireStringInfo(2*GetSignatureDigestsize( |
184 | 15.7k | random_info->signature_info)); |
185 | 15.7k | ResetStringInfo(random_info->nonce); |
186 | 15.7k | random_info->reservoir=AcquireStringInfo(GetSignatureDigestsize( |
187 | 15.7k | random_info->signature_info)); |
188 | 15.7k | ResetStringInfo(random_info->reservoir); |
189 | 15.7k | random_info->normalize=(double) (1.0/(MagickULLConstant(~0) >> 11)); |
190 | 15.7k | random_info->seed[0]=MagickULLConstant(0x76e15d3efefdcbbf); |
191 | 15.7k | random_info->seed[1]=MagickULLConstant(0xc5004e441c522fb3); |
192 | 15.7k | random_info->seed[2]=MagickULLConstant(0x77710069854ee241); |
193 | 15.7k | random_info->seed[3]=MagickULLConstant(0x39109bb02acbe635); |
194 | 15.7k | random_info->secret_key=secret_key; |
195 | 15.7k | random_info->protocol_major=RandomProtocolMajorVersion; |
196 | 15.7k | random_info->protocol_minor=RandomProtocolMinorVersion; |
197 | 15.7k | random_info->semaphore=AcquireSemaphoreInfo(); |
198 | 15.7k | random_info->timestamp=GetMagickTime(); |
199 | 15.7k | random_info->signature=MagickCoreSignature; |
200 | | /* |
201 | | Seed random nonce. |
202 | | */ |
203 | 15.7k | nonce=GenerateEntropicChaos(random_info); |
204 | 15.7k | if (nonce == (StringInfo *) NULL) |
205 | 15.7k | ThrowFatalException(ResourceLimitFatalError,"MemoryAllocationFailed"); |
206 | 15.7k | InitializeSignature(random_info->signature_info); |
207 | 15.7k | UpdateSignature(random_info->signature_info,nonce); |
208 | 15.7k | FinalizeSignature(random_info->signature_info); |
209 | 15.7k | SetStringInfoLength(nonce,(GetSignatureDigestsize( |
210 | 15.7k | random_info->signature_info)+1)/2); |
211 | 15.7k | SetStringInfo(nonce,GetSignatureDigest(random_info->signature_info)); |
212 | 15.7k | SetStringInfo(random_info->nonce,nonce); |
213 | 15.7k | nonce=DestroyStringInfo(nonce); |
214 | | /* |
215 | | Seed random reservoir with entropic data. |
216 | | */ |
217 | 15.7k | entropy=GenerateEntropicChaos(random_info); |
218 | 15.7k | if (entropy == (StringInfo *) NULL) |
219 | 15.7k | ThrowFatalException(ResourceLimitFatalError,"MemoryAllocationFailed"); |
220 | 15.7k | UpdateSignature(random_info->signature_info,entropy); |
221 | 15.7k | FinalizeSignature(random_info->signature_info); |
222 | 15.7k | SetStringInfo(random_info->reservoir,GetSignatureDigest( |
223 | 15.7k | random_info->signature_info)); |
224 | 15.7k | entropy=DestroyStringInfo(entropy); |
225 | | /* |
226 | | Seed pseudo random number generator. |
227 | | */ |
228 | 15.7k | if (random_info->secret_key == ~0UL) |
229 | 15.7k | { |
230 | 15.7k | key=GetRandomKey(random_info,sizeof(random_info->seed)); |
231 | 15.7k | (void) memcpy(random_info->seed,GetStringInfoDatum(key), |
232 | 15.7k | sizeof(random_info->seed)); |
233 | 15.7k | key=DestroyStringInfo(key); |
234 | 15.7k | } |
235 | 0 | else |
236 | 0 | { |
237 | 0 | SignatureInfo |
238 | 0 | *signature_info; |
239 | |
|
240 | 0 | signature_info=AcquireSignatureInfo(); |
241 | 0 | key=AcquireStringInfo(sizeof(random_info->secret_key)); |
242 | 0 | SetStringInfoDatum(key,(unsigned char *) &random_info->secret_key); |
243 | 0 | UpdateSignature(signature_info,key); |
244 | 0 | key=DestroyStringInfo(key); |
245 | 0 | FinalizeSignature(signature_info); |
246 | 0 | digest=GetSignatureDigest(signature_info); |
247 | 0 | (void) memcpy(random_info->seed,GetStringInfoDatum(digest), |
248 | 0 | MagickMin((size_t) GetSignatureDigestsize(signature_info), |
249 | 0 | sizeof(random_info->seed))); |
250 | 0 | signature_info=DestroySignatureInfo(signature_info); |
251 | 0 | } |
252 | 15.7k | return(random_info); |
253 | 15.7k | } |
254 | | |
255 | | /* |
256 | | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% |
257 | | % % |
258 | | % % |
259 | | % % |
260 | | + D e s t r o y R a n d o m I n f o % |
261 | | % % |
262 | | % % |
263 | | % % |
264 | | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% |
265 | | % |
266 | | % DestroyRandomInfo() deallocates memory associated with the random |
267 | | % reservoir. |
268 | | % |
269 | | % The format of the DestroyRandomInfo method is: |
270 | | % |
271 | | % RandomInfo *DestroyRandomInfo(RandomInfo *random_info) |
272 | | % |
273 | | % A description of each parameter follows: |
274 | | % |
275 | | % o random_info: the random info. |
276 | | % |
277 | | */ |
278 | | MagickExport RandomInfo *DestroyRandomInfo(RandomInfo *random_info) |
279 | 15.6k | { |
280 | 15.6k | assert(random_info != (RandomInfo *) NULL); |
281 | 15.6k | assert(random_info->signature == MagickCoreSignature); |
282 | 15.6k | if (IsEventLogging() != MagickFalse) |
283 | 0 | (void) LogMagickEvent(TraceEvent,GetMagickModule(),"..."); |
284 | 15.6k | LockSemaphoreInfo(random_info->semaphore); |
285 | 15.6k | if (random_info->reservoir != (StringInfo *) NULL) |
286 | 15.6k | random_info->reservoir=DestroyStringInfo(random_info->reservoir); |
287 | 15.6k | if (random_info->nonce != (StringInfo *) NULL) |
288 | 15.6k | random_info->nonce=DestroyStringInfo(random_info->nonce); |
289 | 15.6k | if (random_info->signature_info != (SignatureInfo *) NULL) |
290 | 15.6k | random_info->signature_info=DestroySignatureInfo( |
291 | 15.6k | random_info->signature_info); |
292 | 15.6k | (void) memset(random_info->seed,0,sizeof(random_info->seed)); |
293 | 15.6k | random_info->signature=(~MagickCoreSignature); |
294 | 15.6k | UnlockSemaphoreInfo(random_info->semaphore); |
295 | 15.6k | RelinquishSemaphoreInfo(&random_info->semaphore); |
296 | 15.6k | random_info=(RandomInfo *) RelinquishMagickMemory(random_info); |
297 | 15.6k | return(random_info); |
298 | 15.6k | } |
299 | | |
300 | | /* |
301 | | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% |
302 | | % % |
303 | | % % |
304 | | % % |
305 | | + G e n e r a t e E n t r o p i c C h a o s % |
306 | | % % |
307 | | % % |
308 | | % % |
309 | | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% |
310 | | % |
311 | | % GenerateEntropicChaos() generate entropic chaos used to initialize the |
312 | | % random reservoir. |
313 | | % |
314 | | % The format of the GenerateEntropicChaos method is: |
315 | | % |
316 | | % StringInfo *GenerateEntropicChaos(RandomInfo *random_info) |
317 | | % |
318 | | % A description of each parameter follows: |
319 | | % |
320 | | % o random_info: the random info. |
321 | | % |
322 | | */ |
323 | | |
324 | | #if !defined(MAGICKCORE_WINDOWS_SUPPORT) |
325 | | static ssize_t ReadRandom(int file,unsigned char *source,size_t length) |
326 | 0 | { |
327 | 0 | unsigned char |
328 | 0 | *q; |
329 | 0 |
|
330 | 0 | ssize_t |
331 | 0 | offset, |
332 | 0 | count; |
333 | 0 |
|
334 | 0 | offset=0; |
335 | 0 | for (q=source; length != 0; length-=(size_t) count) |
336 | 0 | { |
337 | 0 | count=(ssize_t) read(file,q,length); |
338 | 0 | if (count <= 0) |
339 | 0 | { |
340 | 0 | count=0; |
341 | 0 | if (errno == EINTR) |
342 | 0 | continue; |
343 | 0 | return(-1); |
344 | 0 | } |
345 | 0 | q+=(ptrdiff_t) count; |
346 | 0 | offset+=count; |
347 | 0 | } |
348 | 0 | return(offset); |
349 | 0 | } |
350 | | #endif |
351 | | |
352 | | static StringInfo *GenerateEntropicChaos(RandomInfo *random_info) |
353 | 31.4k | { |
354 | 62.9k | #define MaxEntropyExtent 64 /* max permitted: 256 */ |
355 | | |
356 | 31.4k | MagickThreadType |
357 | 31.4k | tid; |
358 | | |
359 | 31.4k | StringInfo |
360 | 31.4k | *chaos, |
361 | 31.4k | *entropy; |
362 | | |
363 | 31.4k | ssize_t |
364 | 31.4k | pid; |
365 | | |
366 | 31.4k | time_t |
367 | 31.4k | nanoseconds, |
368 | 31.4k | seconds; |
369 | | |
370 | | /* |
371 | | Initialize random reservoir. |
372 | | */ |
373 | 31.4k | entropy=AcquireStringInfo(0); |
374 | 31.4k | LockSemaphoreInfo(random_info->semaphore); |
375 | 31.4k | #ifdef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION |
376 | | /* Deterministic entropy for fuzzing */ |
377 | 31.4k | { |
378 | 31.4k | unsigned char |
379 | 31.4k | *datum; |
380 | | |
381 | 31.4k | SetStringInfoLength(entropy,MaxEntropyExtent); |
382 | 31.4k | datum=GetStringInfoDatum(entropy); |
383 | 31.4k | (void) memset(datum,0x42,MaxEntropyExtent); |
384 | 31.4k | UnlockSemaphoreInfo(random_info->semaphore); |
385 | 31.4k | return(entropy); |
386 | 31.4k | } |
387 | 0 | #endif |
388 | 0 | #if defined(MAGICKCORE_HAVE_GETENTROPY) |
389 | 0 | { |
390 | 0 | int |
391 | 0 | status; |
392 | | |
393 | 0 | SetStringInfoLength(entropy,MaxEntropyExtent); |
394 | 0 | status=getentropy(GetStringInfoDatum(entropy),MaxEntropyExtent); |
395 | 0 | if (status == 0) |
396 | 0 | { |
397 | 0 | UnlockSemaphoreInfo(random_info->semaphore); |
398 | 0 | return(entropy); |
399 | 0 | } |
400 | 0 | } |
401 | 0 | #endif |
402 | 0 | chaos=AcquireStringInfo(sizeof(unsigned char *)); |
403 | 0 | SetStringInfoDatum(chaos,(unsigned char *) &entropy); |
404 | 0 | ConcatenateStringInfo(entropy,chaos); |
405 | 0 | SetStringInfoDatum(chaos,(unsigned char *) entropy); |
406 | 0 | ConcatenateStringInfo(entropy,chaos); |
407 | 0 | pid=(ssize_t) getpid(); |
408 | 0 | SetStringInfoLength(chaos,sizeof(pid)); |
409 | 0 | SetStringInfoDatum(chaos,(unsigned char *) &pid); |
410 | 0 | ConcatenateStringInfo(entropy,chaos); |
411 | 0 | tid=GetMagickThreadId(); |
412 | 0 | SetStringInfoLength(chaos,sizeof(tid)); |
413 | 0 | SetStringInfoDatum(chaos,(unsigned char *) &tid); |
414 | 0 | ConcatenateStringInfo(entropy,chaos); |
415 | 0 | #if defined(MAGICKCORE_HAVE_SYSCONF) && defined(_SC_PHYS_PAGES) |
416 | 0 | { |
417 | 0 | ssize_t |
418 | 0 | pages; |
419 | |
|
420 | 0 | pages=(ssize_t) sysconf(_SC_PHYS_PAGES); |
421 | 0 | SetStringInfoLength(chaos,sizeof(pages)); |
422 | 0 | SetStringInfoDatum(chaos,(unsigned char *) &pages); |
423 | 0 | ConcatenateStringInfo(entropy,chaos); |
424 | 0 | } |
425 | 0 | #endif |
426 | 0 | #if defined(MAGICKCORE_HAVE_GETRUSAGE) && defined(RUSAGE_SELF) |
427 | 0 | { |
428 | 0 | struct rusage |
429 | 0 | usage; |
430 | |
|
431 | 0 | if (getrusage(RUSAGE_SELF,&usage) == 0) |
432 | 0 | { |
433 | 0 | SetStringInfoLength(chaos,sizeof(usage)); |
434 | 0 | SetStringInfoDatum(chaos,(unsigned char *) &usage); |
435 | 0 | } |
436 | 0 | } |
437 | 0 | #endif |
438 | 0 | seconds=time((time_t *) 0); |
439 | 0 | nanoseconds=0; |
440 | 0 | #if defined(MAGICKCORE_HAVE_GETTIMEOFDAY) |
441 | 0 | { |
442 | 0 | struct timeval |
443 | 0 | timer; |
444 | |
|
445 | 0 | if (gettimeofday(&timer,(struct timezone *) NULL) == 0) |
446 | 0 | { |
447 | 0 | seconds=timer.tv_sec; |
448 | 0 | nanoseconds=1000*timer.tv_usec; |
449 | 0 | } |
450 | 0 | } |
451 | 0 | #endif |
452 | | #if defined(MAGICKCORE_HAVE_CLOCK_GETTIME) && defined(CLOCK_REALTIME_HR) |
453 | | { |
454 | | struct timespec |
455 | | timer; |
456 | | |
457 | | if (clock_gettime(CLOCK_REALTIME_HR,&timer) == 0) |
458 | | { |
459 | | seconds=timer.tv_sec; |
460 | | nanoseconds=timer.tv_nsec; |
461 | | } |
462 | | } |
463 | | #endif |
464 | 0 | SetStringInfoLength(chaos,sizeof(seconds)); |
465 | 0 | SetStringInfoDatum(chaos,(unsigned char *) &seconds); |
466 | 0 | ConcatenateStringInfo(entropy,chaos); |
467 | 0 | SetStringInfoLength(chaos,sizeof(nanoseconds)); |
468 | 0 | SetStringInfoDatum(chaos,(unsigned char *) &nanoseconds); |
469 | 0 | ConcatenateStringInfo(entropy,chaos); |
470 | 0 | nanoseconds=0; |
471 | 0 | #if defined(MAGICKCORE_HAVE_CLOCK) |
472 | 0 | nanoseconds=clock(); |
473 | 0 | #endif |
474 | 0 | #if defined(MAGICKCORE_HAVE_TIMES) |
475 | 0 | { |
476 | 0 | struct tms |
477 | 0 | timer; |
478 | |
|
479 | 0 | (void) times(&timer); |
480 | 0 | nanoseconds=timer.tms_utime+timer.tms_stime; |
481 | 0 | } |
482 | 0 | #endif |
483 | 0 | SetStringInfoLength(chaos,sizeof(nanoseconds)); |
484 | 0 | SetStringInfoDatum(chaos,(unsigned char *) &nanoseconds); |
485 | 0 | ConcatenateStringInfo(entropy,chaos); |
486 | | #if defined(MAGICKCORE_WINDOWS_SUPPORT) |
487 | | { |
488 | | double |
489 | | nt_seconds; |
490 | | |
491 | | LARGE_INTEGER |
492 | | nt_nanoseconds; |
493 | | |
494 | | /* |
495 | | Not cryptographically strong but better than nothing. |
496 | | */ |
497 | | nt_seconds=NTElapsedTime()+NTElapsedTime(); |
498 | | SetStringInfoLength(chaos,sizeof(nt_seconds)); |
499 | | SetStringInfoDatum(chaos,(unsigned char *) &nt_seconds); |
500 | | ConcatenateStringInfo(entropy,chaos); |
501 | | if (QueryPerformanceCounter(&nt_nanoseconds) != 0) |
502 | | { |
503 | | SetStringInfoLength(chaos,sizeof(nt_nanoseconds)); |
504 | | SetStringInfoDatum(chaos,(unsigned char *) &nt_nanoseconds); |
505 | | ConcatenateStringInfo(entropy,chaos); |
506 | | } |
507 | | /* |
508 | | Our best hope for true entropy. |
509 | | */ |
510 | | SetStringInfoLength(chaos,MaxEntropyExtent); |
511 | | (void) NTGatherRandomData(MaxEntropyExtent,GetStringInfoDatum(chaos)); |
512 | | ConcatenateStringInfo(entropy,chaos); |
513 | | } |
514 | | #else |
515 | 0 | { |
516 | 0 | char |
517 | 0 | *filename; |
518 | |
|
519 | 0 | int |
520 | 0 | file; |
521 | |
|
522 | 0 | ssize_t |
523 | 0 | count; |
524 | |
|
525 | 0 | StringInfo |
526 | 0 | *device; |
527 | | |
528 | | /* |
529 | | Not cryptographically strong but better than nothing. |
530 | | */ |
531 | 0 | if (environ != (char **) NULL) |
532 | 0 | { |
533 | 0 | ssize_t |
534 | 0 | i; |
535 | | |
536 | | /* |
537 | | Squeeze some entropy from the sometimes unpredictable environment. |
538 | | */ |
539 | 0 | for (i=0; environ[i] != (char *) NULL; i++) |
540 | 0 | { |
541 | 0 | SetStringInfoLength(chaos,strlen(environ[i])); |
542 | 0 | SetStringInfoDatum(chaos,(unsigned char *) environ[i]); |
543 | 0 | ConcatenateStringInfo(entropy,chaos); |
544 | 0 | } |
545 | 0 | } |
546 | 0 | filename=AcquireString("/dev/urandom"); |
547 | 0 | device=StringToStringInfo(filename); |
548 | 0 | device=DestroyStringInfo(device); |
549 | 0 | file=open_utf8(filename,O_RDONLY | O_BINARY,0); |
550 | 0 | filename=DestroyString(filename); |
551 | 0 | if (file != -1) |
552 | 0 | { |
553 | 0 | SetStringInfoLength(chaos,MaxEntropyExtent); |
554 | 0 | count=ReadRandom(file,GetStringInfoDatum(chaos),MaxEntropyExtent); |
555 | 0 | (void) close_utf8(file); |
556 | 0 | SetStringInfoLength(chaos,(size_t) count); |
557 | 0 | ConcatenateStringInfo(entropy,chaos); |
558 | 0 | } |
559 | 0 | if (gather_true_random != MagickFalse) |
560 | 0 | { |
561 | | /* |
562 | | Our best hope for true entropy. |
563 | | */ |
564 | 0 | filename=AcquireString("/dev/random"); |
565 | 0 | device=StringToStringInfo(filename); |
566 | 0 | device=DestroyStringInfo(device); |
567 | 0 | file=open_utf8(filename,O_RDONLY | O_BINARY,0); |
568 | 0 | filename=DestroyString(filename); |
569 | 0 | if (file == -1) |
570 | 0 | { |
571 | 0 | filename=AcquireString("/dev/srandom"); |
572 | 0 | device=StringToStringInfo(filename); |
573 | 0 | device=DestroyStringInfo(device); |
574 | 0 | file=open_utf8(filename,O_RDONLY | O_BINARY,0); |
575 | 0 | } |
576 | 0 | if (file != -1) |
577 | 0 | { |
578 | 0 | SetStringInfoLength(chaos,MaxEntropyExtent); |
579 | 0 | count=ReadRandom(file,GetStringInfoDatum(chaos),MaxEntropyExtent); |
580 | 0 | (void) close_utf8(file); |
581 | 0 | SetStringInfoLength(chaos,(size_t) count); |
582 | 0 | ConcatenateStringInfo(entropy,chaos); |
583 | 0 | } |
584 | 0 | } |
585 | 0 | } |
586 | 0 | #endif |
587 | 0 | chaos=DestroyStringInfo(chaos); |
588 | 0 | UnlockSemaphoreInfo(random_info->semaphore); |
589 | 0 | return(entropy); |
590 | 0 | } |
591 | | |
592 | | /* |
593 | | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% |
594 | | % % |
595 | | % % |
596 | | % % |
597 | | % G e t P s e u d o R a n d o m V a l u e % |
598 | | % % |
599 | | % % |
600 | | % % |
601 | | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% |
602 | | % |
603 | | % GetPseudoRandomValue() is a Xoshiro generator that returns a non-negative |
604 | | % double-precision floating-point value uniformly distributed over the |
605 | | % interval [0.0, 1.0) with a 2 to the 256th-1 period. |
606 | | % |
607 | | % The format of the GetPseudoRandomValue method is: |
608 | | % |
609 | | % double GetPseudoRandomValue(RandomInfo *randon_info) |
610 | | % |
611 | | % A description of each parameter follows: |
612 | | % |
613 | | % o random_info: the random info. |
614 | | % |
615 | | */ |
616 | | MagickExport double GetPseudoRandomValue( |
617 | | RandomInfo *magick_restrict random_info) |
618 | 19.9M | { |
619 | 19.9M | #define RandomROTL(x,k) (((x) << (k)) | ((x) >> (64-(k)))) |
620 | | |
621 | 19.9M | const MagickSizeType |
622 | 19.9M | alpha = (random_info->seed[1] << 17), |
623 | 19.9M | value = (random_info->seed[0]+random_info->seed[3]); |
624 | | |
625 | 19.9M | random_info->seed[2]^=random_info->seed[0]; |
626 | 19.9M | random_info->seed[3]^=random_info->seed[1]; |
627 | 19.9M | random_info->seed[1]^=random_info->seed[2]; |
628 | 19.9M | random_info->seed[0]^=random_info->seed[3]; |
629 | 19.9M | random_info->seed[2]^=alpha; |
630 | 19.9M | random_info->seed[3]=RandomROTL(random_info->seed[3],45); |
631 | 19.9M | return((double) ((value >> 11)*random_info->normalize)); |
632 | 19.9M | } |
633 | | |
634 | | /* |
635 | | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% |
636 | | % % |
637 | | % % |
638 | | % % |
639 | | + G e t R a n d o m I n f o N o r m a l i z e % |
640 | | % % |
641 | | % % |
642 | | % % |
643 | | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% |
644 | | % |
645 | | % GetRandomInfoNormalize() returns the random normalize value. |
646 | | % |
647 | | % The format of the GetRandomInfoNormalize method is: |
648 | | % |
649 | | % double GetRandomInfoNormalize(const RandomInfo *random_info) |
650 | | % |
651 | | % A description of each parameter follows: |
652 | | % |
653 | | % o random_info: the random info. |
654 | | % |
655 | | */ |
656 | | MagickPrivate double GetRandomInfoNormalize(const RandomInfo *random_info) |
657 | 0 | { |
658 | 0 | assert(random_info != (const RandomInfo *) NULL); |
659 | 0 | return(random_info->normalize); |
660 | 0 | } |
661 | | |
662 | | /* |
663 | | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% |
664 | | % % |
665 | | % % |
666 | | % % |
667 | | + G e t R a n d o m I n f o S e e d % |
668 | | % % |
669 | | % % |
670 | | % % |
671 | | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% |
672 | | % |
673 | | % GetRandomInfoSeed() returns the random seed. |
674 | | % |
675 | | % The format of the GetRandomInfoSeed method is: |
676 | | % |
677 | | % unsigned long *GetRandomInfoSeed(RandomInfo *random_info) |
678 | | % |
679 | | % A description of each parameter follows: |
680 | | % |
681 | | % o random_info: the random info. |
682 | | % |
683 | | */ |
684 | | MagickPrivate unsigned long *GetRandomInfoSeed(RandomInfo *random_info) |
685 | 0 | { |
686 | 0 | assert(random_info != (RandomInfo *) NULL); |
687 | 0 | return((unsigned long *) random_info->seed); |
688 | 0 | } |
689 | | |
690 | | /* |
691 | | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% |
692 | | % % |
693 | | % % |
694 | | % % |
695 | | % G e t R a n d o m K e y % |
696 | | % % |
697 | | % % |
698 | | % % |
699 | | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% |
700 | | % |
701 | | % GetRandomKey() gets a random key from the reservoir. |
702 | | % |
703 | | % The format of the GetRandomKey method is: |
704 | | % |
705 | | % StringInfo *GetRandomKey(RandomInfo *random_info,const size_t length) |
706 | | % |
707 | | % A description of each parameter follows: |
708 | | % |
709 | | % o random_info: the random info. |
710 | | % |
711 | | % o length: the key length. |
712 | | % |
713 | | */ |
714 | | MagickExport StringInfo *GetRandomKey(RandomInfo *random_info, |
715 | | const size_t length) |
716 | 373k | { |
717 | 373k | StringInfo |
718 | 373k | *key; |
719 | | |
720 | 373k | assert(random_info != (RandomInfo *) NULL); |
721 | 373k | key=AcquireStringInfo(length); |
722 | 373k | SetRandomKey(random_info,length,GetStringInfoDatum(key)); |
723 | 373k | return(key); |
724 | 373k | } |
725 | | |
726 | | /* |
727 | | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% |
728 | | % % |
729 | | % % |
730 | | % % |
731 | | % G e t R a n d o m S e c r e t K e y % |
732 | | % % |
733 | | % % |
734 | | % % |
735 | | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% |
736 | | % |
737 | | % GetRandomSecretKey() returns the random secret key. |
738 | | % |
739 | | % The format of the GetRandomSecretKey method is: |
740 | | % |
741 | | % unsigned long GetRandomSecretKey(const RandomInfo *random_info) |
742 | | % |
743 | | % A description of each parameter follows: |
744 | | % |
745 | | % o random_info: the random info. |
746 | | */ |
747 | | MagickExport unsigned long GetRandomSecretKey(const RandomInfo *random_info) |
748 | 0 | { |
749 | 0 | return(random_info->secret_key); |
750 | 0 | } |
751 | | |
752 | | /* |
753 | | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% |
754 | | % % |
755 | | % % |
756 | | % % |
757 | | % G e t R a n d o m V a l u e % |
758 | | % % |
759 | | % % |
760 | | % % |
761 | | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% |
762 | | % |
763 | | % GetRandomValue() return a non-negative double-precision floating-point |
764 | | % value uniformly distributed over the interval [0.0, 1.0) with a 2 to the |
765 | | % 128th-1 period (not cryptographically strong). |
766 | | % |
767 | | % The format of the GetRandomValue method is: |
768 | | % |
769 | | % double GetRandomValue(void) |
770 | | % |
771 | | */ |
772 | | MagickExport double GetRandomValue(RandomInfo *random_info) |
773 | 0 | { |
774 | 0 | unsigned long |
775 | 0 | key, |
776 | 0 | range; |
777 | |
|
778 | 0 | range=(~0UL); |
779 | 0 | do |
780 | 0 | { |
781 | 0 | SetRandomKey(random_info,sizeof(key),(unsigned char *) &key); |
782 | 0 | } while (key == range); |
783 | 0 | return((double) key/range); |
784 | 0 | } |
785 | | |
786 | | /* |
787 | | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% |
788 | | % % |
789 | | % % |
790 | | % % |
791 | | + R a n d o m C o m p o n e n t G e n e s i s % |
792 | | % % |
793 | | % % |
794 | | % % |
795 | | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% |
796 | | % |
797 | | % RandomComponentGenesis() instantiates the random component. |
798 | | % |
799 | | % The format of the RandomComponentGenesis method is: |
800 | | % |
801 | | % MagickBooleanType RandomComponentGenesis(void) |
802 | | % |
803 | | */ |
804 | | MagickPrivate MagickBooleanType RandomComponentGenesis(void) |
805 | 295 | { |
806 | 295 | if (random_semaphore == (SemaphoreInfo *) NULL) |
807 | 295 | random_semaphore=AcquireSemaphoreInfo(); |
808 | 295 | return(MagickTrue); |
809 | 295 | } |
810 | | |
811 | | /* |
812 | | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% |
813 | | % % |
814 | | % % |
815 | | % % |
816 | | + R a n d o m C o m p o n e n t T e r m i n u s % |
817 | | % % |
818 | | % % |
819 | | % % |
820 | | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% |
821 | | % |
822 | | % RandomComponentTerminus() destroys the random component. |
823 | | % |
824 | | % The format of the RandomComponentTerminus method is: |
825 | | % |
826 | | % RandomComponentTerminus(void) |
827 | | % |
828 | | */ |
829 | | MagickPrivate void RandomComponentTerminus(void) |
830 | 0 | { |
831 | 0 | if (random_semaphore == (SemaphoreInfo *) NULL) |
832 | 0 | ActivateSemaphoreInfo(&random_semaphore); |
833 | 0 | RelinquishSemaphoreInfo(&random_semaphore); |
834 | 0 | } |
835 | | |
836 | | /* |
837 | | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% |
838 | | % % |
839 | | % % |
840 | | % % |
841 | | % S e t R a n d o m K e y % |
842 | | % % |
843 | | % % |
844 | | % % |
845 | | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% |
846 | | % |
847 | | % SetRandomKey() sets a random key from the reservoir. |
848 | | % |
849 | | % The format of the SetRandomKey method is: |
850 | | % |
851 | | % void SetRandomKey(RandomInfo *random_info,const size_t length, |
852 | | % unsigned char *key) |
853 | | % |
854 | | % A description of each parameter follows: |
855 | | % |
856 | | % o random_info: the random info. |
857 | | % |
858 | | % o length: the key length. |
859 | | % |
860 | | % o key: the key. |
861 | | % |
862 | | */ |
863 | | |
864 | | static inline void IncrementRandomNonce(StringInfo *nonce) |
865 | 0 | { |
866 | 0 | ssize_t |
867 | 0 | i; |
868 | 0 |
|
869 | 0 | unsigned char |
870 | 0 | *datum; |
871 | 0 |
|
872 | 0 | datum=GetStringInfoDatum(nonce); |
873 | 0 | for (i=(ssize_t) (GetStringInfoLength(nonce)-1); i != 0; i--) |
874 | 0 | { |
875 | 0 | datum[i]++; |
876 | 0 | if (datum[i] != 0) |
877 | 0 | return; |
878 | 0 | } |
879 | 0 | ThrowFatalException(RandomFatalError,"SequenceWrapError"); |
880 | 0 | } |
881 | | |
882 | | MagickExport void SetRandomKey(RandomInfo *random_info,const size_t length, |
883 | | unsigned char *key) |
884 | 373k | { |
885 | 373k | size_t |
886 | 373k | i; |
887 | | |
888 | 373k | unsigned char |
889 | 373k | *p; |
890 | | |
891 | 373k | SignatureInfo |
892 | 373k | *signature_info; |
893 | | |
894 | 373k | unsigned char |
895 | 373k | *datum; |
896 | | |
897 | 373k | assert(random_info != (RandomInfo *) NULL); |
898 | 373k | if (length == 0) |
899 | 0 | return; |
900 | 373k | #ifdef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION |
901 | | /* Deterministic random key for fuzzing */ |
902 | 373k | (void) memset(key,0x42,length); |
903 | 373k | return; |
904 | 0 | #endif |
905 | 0 | LockSemaphoreInfo(random_info->semaphore); |
906 | 0 | signature_info=random_info->signature_info; |
907 | 0 | datum=GetStringInfoDatum(random_info->reservoir); |
908 | 0 | i=length; |
909 | 0 | for (p=key; (i != 0) && (random_info->i != 0); i--) |
910 | 0 | { |
911 | 0 | *p++=datum[random_info->i]; |
912 | 0 | random_info->i++; |
913 | 0 | if (random_info->i == GetSignatureDigestsize(signature_info)) |
914 | 0 | random_info->i=0; |
915 | 0 | } |
916 | 0 | while (i >= GetSignatureDigestsize(signature_info)) |
917 | 0 | { |
918 | 0 | InitializeSignature(signature_info); |
919 | 0 | UpdateSignature(signature_info,random_info->nonce); |
920 | 0 | FinalizeSignature(signature_info); |
921 | 0 | IncrementRandomNonce(random_info->nonce); |
922 | 0 | (void) memcpy(p,GetStringInfoDatum(GetSignatureDigest( |
923 | 0 | signature_info)),GetSignatureDigestsize(signature_info)); |
924 | 0 | p+=(ptrdiff_t) GetSignatureDigestsize(signature_info); |
925 | 0 | i-=GetSignatureDigestsize(signature_info); |
926 | 0 | } |
927 | 0 | if (i != 0) |
928 | 0 | { |
929 | 0 | InitializeSignature(signature_info); |
930 | 0 | UpdateSignature(signature_info,random_info->nonce); |
931 | 0 | FinalizeSignature(signature_info); |
932 | 0 | IncrementRandomNonce(random_info->nonce); |
933 | 0 | SetStringInfo(random_info->reservoir,GetSignatureDigest(signature_info)); |
934 | 0 | random_info->i=i; |
935 | 0 | datum=GetStringInfoDatum(random_info->reservoir); |
936 | 0 | while (i-- != 0) |
937 | 0 | p[i]=datum[i]; |
938 | 0 | } |
939 | 0 | UnlockSemaphoreInfo(random_info->semaphore); |
940 | 0 | } |
941 | | |
942 | | /* |
943 | | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% |
944 | | % % |
945 | | % % |
946 | | % % |
947 | | % S e t R a n d o m S e c r e t K e y % |
948 | | % % |
949 | | % % |
950 | | % % |
951 | | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% |
952 | | % |
953 | | % SetRandomSecretKey() sets the pseudo-random number generator secret key. |
954 | | % |
955 | | % The format of the SetRandomSecretKey method is: |
956 | | % |
957 | | % void SetRandomSecretKey(const unsigned long key) |
958 | | % |
959 | | % A description of each parameter follows: |
960 | | % |
961 | | % o key: the secret key. |
962 | | % |
963 | | */ |
964 | | MagickExport void SetRandomSecretKey(const unsigned long key) |
965 | 0 | { |
966 | 0 | secret_key=key; |
967 | 0 | } |
968 | | |
969 | | /* |
970 | | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% |
971 | | % % |
972 | | % % |
973 | | % % |
974 | | % S e t R a n d o m T r u e R a n d o m % |
975 | | % % |
976 | | % % |
977 | | % % |
978 | | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% |
979 | | % |
980 | | % SetRandomTrueRandom() declares your intentions to use true random numbers. |
981 | | % True random numbers are encouraged but may not always be practical because |
982 | | % your application may block while entropy is gathered from your environment. |
983 | | % |
984 | | % The format of the SetRandomTrueRandom method is: |
985 | | % |
986 | | % void SetRandomTrueRandom(const MagickBooleanType true_random) |
987 | | % |
988 | | % A description of each parameter follows: |
989 | | % |
990 | | % o true_random: declare your intentions to use true-random number. |
991 | | % |
992 | | */ |
993 | | MagickExport void SetRandomTrueRandom(const MagickBooleanType true_random) |
994 | 0 | { |
995 | 0 | gather_true_random=true_random; |
996 | 0 | } |