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