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