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