• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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-2021 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/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 
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/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 
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   MagickSizeType
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 
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 
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 
139 /*
140   Forward declarations.
141 */
142 static StringInfo
143   *GenerateEntropicChaos(RandomInfo *);
144 
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 */
AcquireRandomInfo(void)163 MagickExport RandomInfo *AcquireRandomInfo(void)
164 {
165   const StringInfo
166     *digest;
167 
168   RandomInfo
169     *random_info;
170 
171   StringInfo
172     *entropy,
173     *key,
174     *nonce;
175 
176   random_info=(RandomInfo *) AcquireCriticalMemory(sizeof(*random_info));
177   (void) memset(random_info,0,sizeof(*random_info));
178   random_info->signature_info=AcquireSignatureInfo();
179   random_info->nonce=AcquireStringInfo(2*GetSignatureDigestsize(
180     random_info->signature_info));
181   ResetStringInfo(random_info->nonce);
182   random_info->reservoir=AcquireStringInfo(GetSignatureDigestsize(
183     random_info->signature_info));
184   ResetStringInfo(random_info->reservoir);
185   random_info->normalize=(double) (1.0/(MagickULLConstant(~0) >> 11));
186   random_info->seed[0]=MagickULLConstant(0x76e15d3efefdcbbf);
187   random_info->seed[1]=MagickULLConstant(0xc5004e441c522fb3);
188   random_info->seed[2]=MagickULLConstant(0x77710069854ee241);
189   random_info->seed[3]=MagickULLConstant(0x39109bb02acbe635);
190   random_info->secret_key=secret_key;
191   random_info->protocol_major=RandomProtocolMajorVersion;
192   random_info->protocol_minor=RandomProtocolMinorVersion;
193   random_info->semaphore=AcquireSemaphoreInfo();
194   random_info->timestamp=(ssize_t) time(0);
195   random_info->signature=MagickCoreSignature;
196   /*
197     Seed random nonce.
198   */
199   nonce=GenerateEntropicChaos(random_info);
200   if (nonce == (StringInfo *) NULL)
201     ThrowFatalException(ResourceLimitFatalError,"MemoryAllocationFailed");
202   InitializeSignature(random_info->signature_info);
203   UpdateSignature(random_info->signature_info,nonce);
204   FinalizeSignature(random_info->signature_info);
205   SetStringInfoLength(nonce,(GetSignatureDigestsize(
206     random_info->signature_info)+1)/2);
207   SetStringInfo(nonce,GetSignatureDigest(random_info->signature_info));
208   SetStringInfo(random_info->nonce,nonce);
209   nonce=DestroyStringInfo(nonce);
210   /*
211     Seed random reservoir with entropic data.
212   */
213   entropy=GenerateEntropicChaos(random_info);
214   if (entropy == (StringInfo *) NULL)
215     ThrowFatalException(ResourceLimitFatalError,"MemoryAllocationFailed");
216   UpdateSignature(random_info->signature_info,entropy);
217   FinalizeSignature(random_info->signature_info);
218   SetStringInfo(random_info->reservoir,GetSignatureDigest(
219     random_info->signature_info));
220   entropy=DestroyStringInfo(entropy);
221   /*
222     Seed pseudo random number generator.
223   */
224   if (random_info->secret_key == ~0UL)
225     {
226       key=GetRandomKey(random_info,sizeof(random_info->seed));
227       (void) memcpy(random_info->seed,GetStringInfoDatum(key),
228         sizeof(random_info->seed));
229       key=DestroyStringInfo(key);
230     }
231   else
232     {
233       SignatureInfo
234         *signature_info;
235 
236       signature_info=AcquireSignatureInfo();
237       key=AcquireStringInfo(sizeof(random_info->secret_key));
238       SetStringInfoDatum(key,(unsigned char *) &random_info->secret_key);
239       UpdateSignature(signature_info,key);
240       key=DestroyStringInfo(key);
241       FinalizeSignature(signature_info);
242       digest=GetSignatureDigest(signature_info);
243       (void) memcpy(random_info->seed,GetStringInfoDatum(digest),
244         MagickMin((size_t) GetSignatureDigestsize(signature_info),
245         sizeof(random_info->seed)));
246       signature_info=DestroySignatureInfo(signature_info);
247     }
248   return(random_info);
249 }
250 
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 */
DestroyRandomInfo(RandomInfo * random_info)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 
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)
ReadRandom(int file,unsigned char * source,size_t length)320 static ssize_t ReadRandom(int file,unsigned char *source,size_t length)
321 {
322   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 
GenerateEntropicChaos(RandomInfo * random_info)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=(size_t) timer.tv_sec;
416         nanoseconds=(size_t) (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_WINDOWS_SUPPORT)
455   {
456     double
457       seconds;
458 
459     LARGE_INTEGER
460       nanoseconds;
461 
462     /*
463       Not crytographically strong but better than nothing.
464     */
465     seconds=NTElapsedTime()+NTUserTime();
466     SetStringInfoLength(chaos,sizeof(seconds));
467     SetStringInfoDatum(chaos,(unsigned char *) &seconds);
468     ConcatenateStringInfo(entropy,chaos);
469     if (QueryPerformanceCounter(&nanoseconds) != 0)
470       {
471         SetStringInfoLength(chaos,sizeof(nanoseconds));
472         SetStringInfoDatum(chaos,(unsigned char *) &nanoseconds);
473         ConcatenateStringInfo(entropy,chaos);
474       }
475     /*
476       Our best hope for true entropy.
477     */
478     SetStringInfoLength(chaos,MaxEntropyExtent);
479     (void) NTGatherRandomData(MaxEntropyExtent,GetStringInfoDatum(chaos));
480     ConcatenateStringInfo(entropy,chaos);
481   }
482 #else
483   {
484     char
485       *filename;
486 
487     int
488       file;
489 
490     ssize_t
491       count;
492 
493     StringInfo
494       *device;
495 
496     /*
497       Not crytographically strong but better than nothing.
498     */
499     if (environ != (char **) NULL)
500       {
501         ssize_t
502           i;
503 
504         /*
505           Squeeze some entropy from the sometimes unpredicatble environment.
506         */
507         for (i=0; environ[i] != (char *) NULL; i++)
508         {
509           SetStringInfoLength(chaos,strlen(environ[i]));
510           SetStringInfoDatum(chaos,(unsigned char *) environ[i]);
511           ConcatenateStringInfo(entropy,chaos);
512         }
513       }
514     filename=AcquireString("/dev/urandom");
515     device=StringToStringInfo(filename);
516     device=DestroyStringInfo(device);
517     file=open_utf8(filename,O_RDONLY | O_BINARY,0);
518     filename=DestroyString(filename);
519     if (file != -1)
520       {
521         SetStringInfoLength(chaos,MaxEntropyExtent);
522         count=ReadRandom(file,GetStringInfoDatum(chaos),MaxEntropyExtent);
523         (void) close(file);
524         SetStringInfoLength(chaos,(size_t) count);
525         ConcatenateStringInfo(entropy,chaos);
526       }
527     if (gather_true_random != MagickFalse)
528       {
529         /*
530           Our best hope for true entropy.
531         */
532         filename=AcquireString("/dev/random");
533         device=StringToStringInfo(filename);
534         device=DestroyStringInfo(device);
535         file=open_utf8(filename,O_RDONLY | O_BINARY,0);
536         filename=DestroyString(filename);
537         if (file == -1)
538           {
539             filename=AcquireString("/dev/srandom");
540             device=StringToStringInfo(filename);
541             device=DestroyStringInfo(device);
542             file=open_utf8(filename,O_RDONLY | O_BINARY,0);
543           }
544         if (file != -1)
545           {
546             SetStringInfoLength(chaos,MaxEntropyExtent);
547             count=ReadRandom(file,GetStringInfoDatum(chaos),MaxEntropyExtent);
548             (void) close(file);
549             SetStringInfoLength(chaos,(size_t) count);
550             ConcatenateStringInfo(entropy,chaos);
551           }
552       }
553   }
554 #endif
555   chaos=DestroyStringInfo(chaos);
556   UnlockSemaphoreInfo(random_info->semaphore);
557   return(entropy);
558 }
559 
560 /*
561 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
562 %                                                                             %
563 %                                                                             %
564 %                                                                             %
565 %   G e t P s e u d o R a n d o m V a l u e                                   %
566 %                                                                             %
567 %                                                                             %
568 %                                                                             %
569 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
570 %
571 %  GetPseudoRandomValue() is a Xoshiro generator that returns a non-negative
572 %  double-precision floating-point value uniformly distributed over the
573 %  interval [0.0, 1.0) with a 2 to the 256th-1 period.
574 %
575 %  The format of the GetPseudoRandomValue method is:
576 %
577 %      double GetPseudoRandomValue(RandomInfo *randon_info)
578 %
579 %  A description of each parameter follows:
580 %
581 %    o random_info: the random info.
582 %
583 */
GetPseudoRandomValue(RandomInfo * magick_restrict random_info)584 MagickExport double GetPseudoRandomValue(
585   RandomInfo *magick_restrict random_info)
586 {
587 #define RandomROTL(x,k) (((x) << (k)) | ((x) >> (64-(k))))
588 
589   const MagickSizeType
590     alpha = (random_info->seed[1] << 17),
591     value = (random_info->seed[0]+random_info->seed[3]);
592 
593   random_info->seed[2]^=random_info->seed[0];
594   random_info->seed[3]^=random_info->seed[1];
595   random_info->seed[1]^=random_info->seed[2];
596   random_info->seed[0]^=random_info->seed[3];
597   random_info->seed[2]^=alpha;
598   random_info->seed[3]=RandomROTL(random_info->seed[3],45);
599   return((double) ((value >> 11)*random_info->normalize));
600 }
601 
602 /*
603 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
604 %                                                                             %
605 %                                                                             %
606 %                                                                             %
607 +   G e t R a n d o m I n f o N o r m a l i z e                               %
608 %                                                                             %
609 %                                                                             %
610 %                                                                             %
611 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
612 %
613 %  GetRandomInfoNormalize() returns the random normalize value.
614 %
615 %  The format of the GetRandomInfoNormalize method is:
616 %
617 %      double GetRandomInfoNormalize(const RandomInfo *random_info)
618 %
619 %  A description of each parameter follows:
620 %
621 %    o random_info: the random info.
622 %
623 */
GetRandomInfoNormalize(const RandomInfo * random_info)624 MagickPrivate double GetRandomInfoNormalize(const RandomInfo *random_info)
625 {
626   assert(random_info != (const RandomInfo *) NULL);
627   return(random_info->normalize);
628 }
629 
630 /*
631 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
632 %                                                                             %
633 %                                                                             %
634 %                                                                             %
635 +   G e t R a n d o m I n f o S e e d                                         %
636 %                                                                             %
637 %                                                                             %
638 %                                                                             %
639 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
640 %
641 %  GetRandomInfoSeed() returns the random seed.
642 %
643 %  The format of the GetRandomInfoSeed method is:
644 %
645 %      unsigned long *GetRandomInfoSeed(RandomInfo *random_info)
646 %
647 %  A description of each parameter follows:
648 %
649 %    o random_info: the random info.
650 %
651 */
GetRandomInfoSeed(RandomInfo * random_info)652 MagickPrivate unsigned long *GetRandomInfoSeed(RandomInfo *random_info)
653 {
654   assert(random_info != (RandomInfo *) NULL);
655   return((unsigned long *) random_info->seed);
656 }
657 
658 /*
659 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
660 %                                                                             %
661 %                                                                             %
662 %                                                                             %
663 %   G e t R a n d o m K e y                                                   %
664 %                                                                             %
665 %                                                                             %
666 %                                                                             %
667 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
668 %
669 %  GetRandomKey() gets a random key from the reservoir.
670 %
671 %  The format of the GetRandomKey method is:
672 %
673 %      StringInfo *GetRandomKey(RandomInfo *random_info,const size_t length)
674 %
675 %  A description of each parameter follows:
676 %
677 %    o random_info: the random info.
678 %
679 %    o length: the key length.
680 %
681 */
GetRandomKey(RandomInfo * random_info,const size_t length)682 MagickExport StringInfo *GetRandomKey(RandomInfo *random_info,
683   const size_t length)
684 {
685   StringInfo
686     *key;
687 
688   assert(random_info != (RandomInfo *) NULL);
689   key=AcquireStringInfo(length);
690   SetRandomKey(random_info,length,GetStringInfoDatum(key));
691   return(key);
692 }
693 
694 /*
695 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
696 %                                                                             %
697 %                                                                             %
698 %                                                                             %
699 %   G e t R a n d o m S e c r e t K e y                                       %
700 %                                                                             %
701 %                                                                             %
702 %                                                                             %
703 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
704 %
705 %  GetRandomSecretKey() returns the random secet key.
706 %
707 %  The format of the GetRandomSecretKey method is:
708 %
709 %      unsigned long GetRandomSecretKey(const RandomInfo *random_info)
710 %
711 %  A description of each parameter follows:
712 %
713 %    o random_info: the random info.
714 */
GetRandomSecretKey(const RandomInfo * random_info)715 MagickExport unsigned long GetRandomSecretKey(const RandomInfo *random_info)
716 {
717   return(random_info->secret_key);
718 }
719 
720 /*
721 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
722 %                                                                             %
723 %                                                                             %
724 %                                                                             %
725 %   G e t R a n d o m V a l u e                                               %
726 %                                                                             %
727 %                                                                             %
728 %                                                                             %
729 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
730 %
731 %  GetRandomValue() return a non-negative double-precision floating-point
732 %  value uniformly distributed over the interval [0.0, 1.0) with a 2 to the
733 %  128th-1 period (not cryptographically strong).
734 %
735 %  The format of the GetRandomValue method is:
736 %
737 %      double GetRandomValue(void)
738 %
739 */
GetRandomValue(RandomInfo * random_info)740 MagickExport double GetRandomValue(RandomInfo *random_info)
741 {
742   unsigned long
743     key,
744     range;
745 
746   range=(~0UL);
747   do
748   {
749     SetRandomKey(random_info,sizeof(key),(unsigned char *) &key);
750   } while (key == range);
751   return((double) key/range);
752 }
753 
754 /*
755 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
756 %                                                                             %
757 %                                                                             %
758 %                                                                             %
759 +   R a n d o m C o m p o n e n t G e n e s i s                               %
760 %                                                                             %
761 %                                                                             %
762 %                                                                             %
763 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
764 %
765 %  RandomComponentGenesis() instantiates the random component.
766 %
767 %  The format of the RandomComponentGenesis method is:
768 %
769 %      MagickBooleanType RandomComponentGenesis(void)
770 %
771 */
RandomComponentGenesis(void)772 MagickPrivate MagickBooleanType RandomComponentGenesis(void)
773 {
774   if (random_semaphore == (SemaphoreInfo *) NULL)
775     random_semaphore=AcquireSemaphoreInfo();
776   return(MagickTrue);
777 }
778 
779 /*
780 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
781 %                                                                             %
782 %                                                                             %
783 %                                                                             %
784 +   R a n d o m C o m p o n e n t T e r m i n u s                             %
785 %                                                                             %
786 %                                                                             %
787 %                                                                             %
788 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
789 %
790 %  RandomComponentTerminus() destroys the random component.
791 %
792 %  The format of the RandomComponentTerminus method is:
793 %
794 %      RandomComponentTerminus(void)
795 %
796 */
RandomComponentTerminus(void)797 MagickPrivate void RandomComponentTerminus(void)
798 {
799   if (random_semaphore == (SemaphoreInfo *) NULL)
800     ActivateSemaphoreInfo(&random_semaphore);
801   RelinquishSemaphoreInfo(&random_semaphore);
802 }
803 
804 /*
805 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
806 %                                                                             %
807 %                                                                             %
808 %                                                                             %
809 %   S e t R a n d o m K e y                                                   %
810 %                                                                             %
811 %                                                                             %
812 %                                                                             %
813 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
814 %
815 %  SetRandomKey() sets a random key from the reservoir.
816 %
817 %  The format of the SetRandomKey method is:
818 %
819 %      void SetRandomKey(RandomInfo *random_info,const size_t length,
820 %        unsigned char *key)
821 %
822 %  A description of each parameter follows:
823 %
824 %    o random_info: the random info.
825 %
826 %    o length: the key length.
827 %
828 %    o key: the key.
829 %
830 */
831 
IncrementRandomNonce(StringInfo * nonce)832 static inline void IncrementRandomNonce(StringInfo *nonce)
833 {
834   ssize_t
835     i;
836 
837   unsigned char
838     *datum;
839 
840   datum=GetStringInfoDatum(nonce);
841   for (i=(ssize_t) (GetStringInfoLength(nonce)-1); i != 0; i--)
842   {
843     datum[i]++;
844     if (datum[i] != 0)
845       return;
846   }
847   ThrowFatalException(RandomFatalError,"SequenceWrapError");
848 }
849 
SetRandomKey(RandomInfo * random_info,const size_t length,unsigned char * key)850 MagickExport void SetRandomKey(RandomInfo *random_info,const size_t length,
851   unsigned char *key)
852 {
853   size_t
854     i;
855 
856   unsigned char
857     *p;
858 
859   SignatureInfo
860     *signature_info;
861 
862   unsigned char
863     *datum;
864 
865   assert(random_info != (RandomInfo *) NULL);
866   if (length == 0)
867     return;
868   LockSemaphoreInfo(random_info->semaphore);
869   signature_info=random_info->signature_info;
870   datum=GetStringInfoDatum(random_info->reservoir);
871   i=length;
872   for (p=key; (i != 0) && (random_info->i != 0); i--)
873   {
874     *p++=datum[random_info->i];
875     random_info->i++;
876     if (random_info->i == GetSignatureDigestsize(signature_info))
877       random_info->i=0;
878   }
879   while (i >= GetSignatureDigestsize(signature_info))
880   {
881     InitializeSignature(signature_info);
882     UpdateSignature(signature_info,random_info->nonce);
883     FinalizeSignature(signature_info);
884     IncrementRandomNonce(random_info->nonce);
885     (void) memcpy(p,GetStringInfoDatum(GetSignatureDigest(
886       signature_info)),GetSignatureDigestsize(signature_info));
887     p+=GetSignatureDigestsize(signature_info);
888     i-=GetSignatureDigestsize(signature_info);
889   }
890   if (i != 0)
891     {
892       InitializeSignature(signature_info);
893       UpdateSignature(signature_info,random_info->nonce);
894       FinalizeSignature(signature_info);
895       IncrementRandomNonce(random_info->nonce);
896       SetStringInfo(random_info->reservoir,GetSignatureDigest(signature_info));
897       random_info->i=i;
898       datum=GetStringInfoDatum(random_info->reservoir);
899       while (i-- != 0)
900         p[i]=datum[i];
901     }
902   UnlockSemaphoreInfo(random_info->semaphore);
903 }
904 
905 /*
906 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
907 %                                                                             %
908 %                                                                             %
909 %                                                                             %
910 %   S e t R a n d o m S e c r e t K e y                                       %
911 %                                                                             %
912 %                                                                             %
913 %                                                                             %
914 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
915 %
916 %  SetRandomSecretKey() sets the pseudo-random number generator secret key.
917 %
918 %  The format of the SetRandomSecretKey method is:
919 %
920 %      void SetRandomSecretKey(const unsigned long key)
921 %
922 %  A description of each parameter follows:
923 %
924 %    o key: the secret key.
925 %
926 */
SetRandomSecretKey(const unsigned long key)927 MagickExport void SetRandomSecretKey(const unsigned long key)
928 {
929   secret_key=key;
930 }
931 
932 /*
933 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
934 %                                                                             %
935 %                                                                             %
936 %                                                                             %
937 %   S e t R a n d o m T r u e R a n d o m                                     %
938 %                                                                             %
939 %                                                                             %
940 %                                                                             %
941 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
942 %
943 %  SetRandomTrueRandom() declares your intentions to use true random numbers.
944 %  True random numbers are encouraged but may not always be practical because
945 %  your application may block while entropy is gathered from your environment.
946 %
947 %  The format of the SetRandomTrueRandom method is:
948 %
949 %      void SetRandomTrueRandom(const MagickBooleanType true_random)
950 %
951 %  A description of each parameter follows:
952 %
953 %    o true_random: declare your intentions to use true-random number.
954 %
955 */
SetRandomTrueRandom(const MagickBooleanType true_random)956 MagickExport void SetRandomTrueRandom(const MagickBooleanType true_random)
957 {
958   gather_true_random=true_random;
959 }
960