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