MagickCore  7.1.1-43
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/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/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 #if defined(MAGICKCORE_HAVE_GETENTROPY)
376  {
377  int
378  status;
379 
380  SetStringInfoLength(entropy,MaxEntropyExtent);
381  status=getentropy(GetStringInfoDatum(entropy),MaxEntropyExtent);
382  if (status == 0)
383  {
384  UnlockSemaphoreInfo(random_info->semaphore);
385  return(entropy);
386  }
387  }
388 #endif
389  chaos=AcquireStringInfo(sizeof(unsigned char *));
390  SetStringInfoDatum(chaos,(unsigned char *) &entropy);
391  ConcatenateStringInfo(entropy,chaos);
392  SetStringInfoDatum(chaos,(unsigned char *) entropy);
393  ConcatenateStringInfo(entropy,chaos);
394  pid=(ssize_t) getpid();
395  SetStringInfoLength(chaos,sizeof(pid));
396  SetStringInfoDatum(chaos,(unsigned char *) &pid);
397  ConcatenateStringInfo(entropy,chaos);
398  tid=GetMagickThreadId();
399  SetStringInfoLength(chaos,sizeof(tid));
400  SetStringInfoDatum(chaos,(unsigned char *) &tid);
401  ConcatenateStringInfo(entropy,chaos);
402 #if defined(MAGICKCORE_HAVE_SYSCONF) && defined(_SC_PHYS_PAGES)
403  {
404  ssize_t
405  pages;
406 
407  pages=(ssize_t) sysconf(_SC_PHYS_PAGES);
408  SetStringInfoLength(chaos,sizeof(pages));
409  SetStringInfoDatum(chaos,(unsigned char *) &pages);
410  ConcatenateStringInfo(entropy,chaos);
411  }
412 #endif
413 #if defined(MAGICKCORE_HAVE_GETRUSAGE) && defined(RUSAGE_SELF)
414  {
415  struct rusage
416  usage;
417 
418  if (getrusage(RUSAGE_SELF,&usage) == 0)
419  {
420  SetStringInfoLength(chaos,sizeof(usage));
421  SetStringInfoDatum(chaos,(unsigned char *) &usage);
422  }
423  }
424 #endif
425  seconds=time((time_t *) 0);
426  nanoseconds=0;
427 #if defined(MAGICKCORE_HAVE_GETTIMEOFDAY)
428  {
429  struct timeval
430  timer;
431 
432  if (gettimeofday(&timer,(struct timezone *) NULL) == 0)
433  {
434  seconds=timer.tv_sec;
435  nanoseconds=1000*timer.tv_usec;
436  }
437  }
438 #endif
439 #if defined(MAGICKCORE_HAVE_CLOCK_GETTIME) && defined(CLOCK_REALTIME_HR)
440  {
441  struct timespec
442  timer;
443 
444  if (clock_gettime(CLOCK_REALTIME_HR,&timer) == 0)
445  {
446  seconds=timer.tv_sec;
447  nanoseconds=timer.tv_nsec;
448  }
449  }
450 #endif
451  SetStringInfoLength(chaos,sizeof(seconds));
452  SetStringInfoDatum(chaos,(unsigned char *) &seconds);
453  ConcatenateStringInfo(entropy,chaos);
454  SetStringInfoLength(chaos,sizeof(nanoseconds));
455  SetStringInfoDatum(chaos,(unsigned char *) &nanoseconds);
456  ConcatenateStringInfo(entropy,chaos);
457  nanoseconds=0;
458 #if defined(MAGICKCORE_HAVE_CLOCK)
459  nanoseconds=clock();
460 #endif
461 #if defined(MAGICKCORE_HAVE_TIMES)
462  {
463  struct tms
464  timer;
465 
466  (void) times(&timer);
467  nanoseconds=timer.tms_utime+timer.tms_stime;
468  }
469 #endif
470  SetStringInfoLength(chaos,sizeof(nanoseconds));
471  SetStringInfoDatum(chaos,(unsigned char *) &nanoseconds);
472  ConcatenateStringInfo(entropy,chaos);
473 #if defined(MAGICKCORE_WINDOWS_SUPPORT)
474  {
475  double
476  nt_seconds;
477 
478  LARGE_INTEGER
479  nt_nanoseconds;
480 
481  /*
482  Not cryptographically strong but better than nothing.
483  */
484  nt_seconds=NTElapsedTime()+NTElapsedTime();
485  SetStringInfoLength(chaos,sizeof(nt_seconds));
486  SetStringInfoDatum(chaos,(unsigned char *) &nt_seconds);
487  ConcatenateStringInfo(entropy,chaos);
488  if (QueryPerformanceCounter(&nt_nanoseconds) != 0)
489  {
490  SetStringInfoLength(chaos,sizeof(nt_nanoseconds));
491  SetStringInfoDatum(chaos,(unsigned char *) &nt_nanoseconds);
492  ConcatenateStringInfo(entropy,chaos);
493  }
494  /*
495  Our best hope for true entropy.
496  */
497  SetStringInfoLength(chaos,MaxEntropyExtent);
498  (void) NTGatherRandomData(MaxEntropyExtent,GetStringInfoDatum(chaos));
499  ConcatenateStringInfo(entropy,chaos);
500  }
501 #else
502  {
503  char
504  *filename;
505 
506  int
507  file;
508 
509  ssize_t
510  count;
511 
512  StringInfo
513  *device;
514 
515  /*
516  Not cryptographically strong but better than nothing.
517  */
518  if (environ != (char **) NULL)
519  {
520  ssize_t
521  i;
522 
523  /*
524  Squeeze some entropy from the sometimes unpredictable environment.
525  */
526  for (i=0; environ[i] != (char *) NULL; i++)
527  {
528  SetStringInfoLength(chaos,strlen(environ[i]));
529  SetStringInfoDatum(chaos,(unsigned char *) environ[i]);
530  ConcatenateStringInfo(entropy,chaos);
531  }
532  }
533  filename=AcquireString("/dev/urandom");
534  device=StringToStringInfo(filename);
535  device=DestroyStringInfo(device);
536  file=open_utf8(filename,O_RDONLY | O_BINARY,0);
537  filename=DestroyString(filename);
538  if (file != -1)
539  {
540  SetStringInfoLength(chaos,MaxEntropyExtent);
541  count=ReadRandom(file,GetStringInfoDatum(chaos),MaxEntropyExtent);
542  (void) close(file);
543  SetStringInfoLength(chaos,(size_t) count);
544  ConcatenateStringInfo(entropy,chaos);
545  }
546  if (gather_true_random != MagickFalse)
547  {
548  /*
549  Our best hope for true entropy.
550  */
551  filename=AcquireString("/dev/random");
552  device=StringToStringInfo(filename);
553  device=DestroyStringInfo(device);
554  file=open_utf8(filename,O_RDONLY | O_BINARY,0);
555  filename=DestroyString(filename);
556  if (file == -1)
557  {
558  filename=AcquireString("/dev/srandom");
559  device=StringToStringInfo(filename);
560  device=DestroyStringInfo(device);
561  file=open_utf8(filename,O_RDONLY | O_BINARY,0);
562  }
563  if (file != -1)
564  {
565  SetStringInfoLength(chaos,MaxEntropyExtent);
566  count=ReadRandom(file,GetStringInfoDatum(chaos),MaxEntropyExtent);
567  (void) close(file);
568  SetStringInfoLength(chaos,(size_t) count);
569  ConcatenateStringInfo(entropy,chaos);
570  }
571  }
572  }
573 #endif
574  chaos=DestroyStringInfo(chaos);
575  UnlockSemaphoreInfo(random_info->semaphore);
576  return(entropy);
577 }
578 
579 /*
580 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
581 % %
582 % %
583 % %
584 % G e t P s e u d o R a n d o m V a l u e %
585 % %
586 % %
587 % %
588 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
589 %
590 % GetPseudoRandomValue() is a Xoshiro generator that returns a non-negative
591 % double-precision floating-point value uniformly distributed over the
592 % interval [0.0, 1.0) with a 2 to the 256th-1 period.
593 %
594 % The format of the GetPseudoRandomValue method is:
595 %
596 % double GetPseudoRandomValue(RandomInfo *randon_info)
597 %
598 % A description of each parameter follows:
599 %
600 % o random_info: the random info.
601 %
602 */
603 MagickExport double GetPseudoRandomValue(
604  RandomInfo *magick_restrict random_info)
605 {
606 #define RandomROTL(x,k) (((x) << (k)) | ((x) >> (64-(k))))
607 
608  const MagickSizeType
609  alpha = (random_info->seed[1] << 17),
610  value = (random_info->seed[0]+random_info->seed[3]);
611 
612  random_info->seed[2]^=random_info->seed[0];
613  random_info->seed[3]^=random_info->seed[1];
614  random_info->seed[1]^=random_info->seed[2];
615  random_info->seed[0]^=random_info->seed[3];
616  random_info->seed[2]^=alpha;
617  random_info->seed[3]=RandomROTL(random_info->seed[3],45);
618  return((double) ((value >> 11)*random_info->normalize));
619 }
620 
621 /*
622 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
623 % %
624 % %
625 % %
626 + G e t R a n d o m I n f o N o r m a l i z e %
627 % %
628 % %
629 % %
630 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
631 %
632 % GetRandomInfoNormalize() returns the random normalize value.
633 %
634 % The format of the GetRandomInfoNormalize method is:
635 %
636 % double GetRandomInfoNormalize(const RandomInfo *random_info)
637 %
638 % A description of each parameter follows:
639 %
640 % o random_info: the random info.
641 %
642 */
643 MagickPrivate double GetRandomInfoNormalize(const RandomInfo *random_info)
644 {
645  assert(random_info != (const RandomInfo *) NULL);
646  return(random_info->normalize);
647 }
648 
649 /*
650 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
651 % %
652 % %
653 % %
654 + G e t R a n d o m I n f o S e e d %
655 % %
656 % %
657 % %
658 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
659 %
660 % GetRandomInfoSeed() returns the random seed.
661 %
662 % The format of the GetRandomInfoSeed method is:
663 %
664 % unsigned long *GetRandomInfoSeed(RandomInfo *random_info)
665 %
666 % A description of each parameter follows:
667 %
668 % o random_info: the random info.
669 %
670 */
671 MagickPrivate unsigned long *GetRandomInfoSeed(RandomInfo *random_info)
672 {
673  assert(random_info != (RandomInfo *) NULL);
674  return((unsigned long *) random_info->seed);
675 }
676 
677 /*
678 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
679 % %
680 % %
681 % %
682 % G e t R a n d o m K e y %
683 % %
684 % %
685 % %
686 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
687 %
688 % GetRandomKey() gets a random key from the reservoir.
689 %
690 % The format of the GetRandomKey method is:
691 %
692 % StringInfo *GetRandomKey(RandomInfo *random_info,const size_t length)
693 %
694 % A description of each parameter follows:
695 %
696 % o random_info: the random info.
697 %
698 % o length: the key length.
699 %
700 */
701 MagickExport StringInfo *GetRandomKey(RandomInfo *random_info,
702  const size_t length)
703 {
704  StringInfo
705  *key;
706 
707  assert(random_info != (RandomInfo *) NULL);
708  key=AcquireStringInfo(length);
709  SetRandomKey(random_info,length,GetStringInfoDatum(key));
710  return(key);
711 }
712 
713 /*
714 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
715 % %
716 % %
717 % %
718 % G e t R a n d o m S e c r e t K e y %
719 % %
720 % %
721 % %
722 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
723 %
724 % GetRandomSecretKey() returns the random secret key.
725 %
726 % The format of the GetRandomSecretKey method is:
727 %
728 % unsigned long GetRandomSecretKey(const RandomInfo *random_info)
729 %
730 % A description of each parameter follows:
731 %
732 % o random_info: the random info.
733 */
734 MagickExport unsigned long GetRandomSecretKey(const RandomInfo *random_info)
735 {
736  return(random_info->secret_key);
737 }
738 
739 /*
740 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
741 % %
742 % %
743 % %
744 % G e t R a n d o m V a l u e %
745 % %
746 % %
747 % %
748 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
749 %
750 % GetRandomValue() return a non-negative double-precision floating-point
751 % value uniformly distributed over the interval [0.0, 1.0) with a 2 to the
752 % 128th-1 period (not cryptographically strong).
753 %
754 % The format of the GetRandomValue method is:
755 %
756 % double GetRandomValue(void)
757 %
758 */
759 MagickExport double GetRandomValue(RandomInfo *random_info)
760 {
761  unsigned long
762  key,
763  range;
764 
765  range=(~0UL);
766  do
767  {
768  SetRandomKey(random_info,sizeof(key),(unsigned char *) &key);
769  } while (key == range);
770  return((double) key/range);
771 }
772 
773 /*
774 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
775 % %
776 % %
777 % %
778 + R a n d o m C o m p o n e n t G e n e s i s %
779 % %
780 % %
781 % %
782 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
783 %
784 % RandomComponentGenesis() instantiates the random component.
785 %
786 % The format of the RandomComponentGenesis method is:
787 %
788 % MagickBooleanType RandomComponentGenesis(void)
789 %
790 */
791 MagickPrivate MagickBooleanType RandomComponentGenesis(void)
792 {
793  if (random_semaphore == (SemaphoreInfo *) NULL)
794  random_semaphore=AcquireSemaphoreInfo();
795  return(MagickTrue);
796 }
797 
798 /*
799 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
800 % %
801 % %
802 % %
803 + R a n d o m C o m p o n e n t T e r m i n u s %
804 % %
805 % %
806 % %
807 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
808 %
809 % RandomComponentTerminus() destroys the random component.
810 %
811 % The format of the RandomComponentTerminus method is:
812 %
813 % RandomComponentTerminus(void)
814 %
815 */
816 MagickPrivate void RandomComponentTerminus(void)
817 {
818  if (random_semaphore == (SemaphoreInfo *) NULL)
819  ActivateSemaphoreInfo(&random_semaphore);
820  RelinquishSemaphoreInfo(&random_semaphore);
821 }
822 
823 /*
824 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
825 % %
826 % %
827 % %
828 % S e t R a n d o m K e y %
829 % %
830 % %
831 % %
832 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
833 %
834 % SetRandomKey() sets a random key from the reservoir.
835 %
836 % The format of the SetRandomKey method is:
837 %
838 % void SetRandomKey(RandomInfo *random_info,const size_t length,
839 % unsigned char *key)
840 %
841 % A description of each parameter follows:
842 %
843 % o random_info: the random info.
844 %
845 % o length: the key length.
846 %
847 % o key: the key.
848 %
849 */
850 
851 static inline void IncrementRandomNonce(StringInfo *nonce)
852 {
853  ssize_t
854  i;
855 
856  unsigned char
857  *datum;
858 
859  datum=GetStringInfoDatum(nonce);
860  for (i=(ssize_t) (GetStringInfoLength(nonce)-1); i != 0; i--)
861  {
862  datum[i]++;
863  if (datum[i] != 0)
864  return;
865  }
866  ThrowFatalException(RandomFatalError,"SequenceWrapError");
867 }
868 
869 MagickExport void SetRandomKey(RandomInfo *random_info,const size_t length,
870  unsigned char *key)
871 {
872  size_t
873  i;
874 
875  unsigned char
876  *p;
877 
879  *signature_info;
880 
881  unsigned char
882  *datum;
883 
884  assert(random_info != (RandomInfo *) NULL);
885  if (length == 0)
886  return;
887  LockSemaphoreInfo(random_info->semaphore);
888  signature_info=random_info->signature_info;
889  datum=GetStringInfoDatum(random_info->reservoir);
890  i=length;
891  for (p=key; (i != 0) && (random_info->i != 0); i--)
892  {
893  *p++=datum[random_info->i];
894  random_info->i++;
895  if (random_info->i == GetSignatureDigestsize(signature_info))
896  random_info->i=0;
897  }
898  while (i >= GetSignatureDigestsize(signature_info))
899  {
900  InitializeSignature(signature_info);
901  UpdateSignature(signature_info,random_info->nonce);
902  FinalizeSignature(signature_info);
903  IncrementRandomNonce(random_info->nonce);
904  (void) memcpy(p,GetStringInfoDatum(GetSignatureDigest(
905  signature_info)),GetSignatureDigestsize(signature_info));
906  p+=(ptrdiff_t) GetSignatureDigestsize(signature_info);
907  i-=GetSignatureDigestsize(signature_info);
908  }
909  if (i != 0)
910  {
911  InitializeSignature(signature_info);
912  UpdateSignature(signature_info,random_info->nonce);
913  FinalizeSignature(signature_info);
914  IncrementRandomNonce(random_info->nonce);
915  SetStringInfo(random_info->reservoir,GetSignatureDigest(signature_info));
916  random_info->i=i;
917  datum=GetStringInfoDatum(random_info->reservoir);
918  while (i-- != 0)
919  p[i]=datum[i];
920  }
921  UnlockSemaphoreInfo(random_info->semaphore);
922 }
923 
924 /*
925 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
926 % %
927 % %
928 % %
929 % S e t R a n d o m S e c r e t K e y %
930 % %
931 % %
932 % %
933 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
934 %
935 % SetRandomSecretKey() sets the pseudo-random number generator secret key.
936 %
937 % The format of the SetRandomSecretKey method is:
938 %
939 % void SetRandomSecretKey(const unsigned long key)
940 %
941 % A description of each parameter follows:
942 %
943 % o key: the secret key.
944 %
945 */
946 MagickExport void SetRandomSecretKey(const unsigned long key)
947 {
948  secret_key=key;
949 }
950 
951 /*
952 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
953 % %
954 % %
955 % %
956 % S e t R a n d o m T r u e R a n d o m %
957 % %
958 % %
959 % %
960 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
961 %
962 % SetRandomTrueRandom() declares your intentions to use true random numbers.
963 % True random numbers are encouraged but may not always be practical because
964 % your application may block while entropy is gathered from your environment.
965 %
966 % The format of the SetRandomTrueRandom method is:
967 %
968 % void SetRandomTrueRandom(const MagickBooleanType true_random)
969 %
970 % A description of each parameter follows:
971 %
972 % o true_random: declare your intentions to use true-random number.
973 %
974 */
975 MagickExport void SetRandomTrueRandom(const MagickBooleanType true_random)
976 {
977  gather_true_random=true_random;
978 }
SemaphoreInfo
Definition: semaphore.c:60
_SignatureInfo
Definition: signature.c:66
_StringInfo
Definition: string_.h:27
_RandomInfo
Definition: random.c:83