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