MagickCore  6.7.5
random.c
Go to the documentation of this file.
00001 /*
00002 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
00003 %                                                                             %
00004 %                                                                             %
00005 %                 RRRR    AAA   N   N  DDDD    OOO   M   M                    %
00006 %                 R   R  A   A  NN  N  D   D  O   O  MM MM                    %
00007 %                 RRRR   AAAAA  N N N  D   D  O   O  M M M                    %
00008 %                 R R    A   A  N  NN  D   D  O   O  M   M                    %
00009 %                 R  R   A   A  N   N  DDDD    OOO   M   M                    %
00010 %                                                                             %
00011 %                                                                             %
00012 %               MagickCore Methods to Generate Random Numbers                 %
00013 %                                                                             %
00014 %                             Software Design                                 %
00015 %                               John Cristy                                   %
00016 %                              December 2001                                  %
00017 %                                                                             %
00018 %                                                                             %
00019 %  Copyright 1999-2012 ImageMagick Studio LLC, a non-profit organization      %
00020 %  dedicated to making software imaging solutions freely available.           %
00021 %                                                                             %
00022 %  You may not use this file except in compliance with the License.  You may  %
00023 %  obtain a copy of the License at                                            %
00024 %                                                                             %
00025 %    http://www.imagemagick.org/script/license.php                            %
00026 %                                                                             %
00027 %  Unless required by applicable law or agreed to in writing, software        %
00028 %  distributed under the License is distributed on an "AS IS" BASIS,          %
00029 %  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.   %
00030 %  See the License for the specific language governing permissions and        %
00031 %  limitations under the License.                                             %
00032 %                                                                             %
00033 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
00034 %
00035 %  The generation of random numbers is too important to be left to chance.
00036 %                               -- Tom Christiansen <tchrist@mox.perl.com>
00037 %
00038 %
00039 */
00040 
00041 /*
00042   Include declarations.
00043 */
00044 #if defined(__VMS)
00045 #include <time.h>
00046 #endif
00047 #if defined(__MINGW32__)
00048 #include <sys/time.h>
00049 #endif
00050 #include "MagickCore/studio.h"
00051 #include "MagickCore/exception.h"
00052 #include "MagickCore/exception-private.h"
00053 #include "MagickCore/memory_.h"
00054 #include "MagickCore/semaphore.h"
00055 #include "MagickCore/random_.h"
00056 #include "MagickCore/random-private.h"
00057 #include "MagickCore/resource_.h"
00058 #include "MagickCore/signature-private.h"
00059 #include "MagickCore/string_.h"
00060 #include "MagickCore/thread_.h"
00061 #include "MagickCore/thread-private.h"
00062 #include "MagickCore/utility.h"
00063 #include "MagickCore/utility-private.h"
00064 /*
00065   Define declarations.
00066 */
00067 #define PseudoRandomHash  SHA256Hash
00068 #define RandomEntropyLevel  9
00069 #define RandomFilename  "reservoir.xdm"
00070 #define RandomFiletype  "random"
00071 #define RandomProtocolMajorVersion  1
00072 #define RandomProtocolMinorVersion  0
00073 
00074 /*
00075   Typedef declarations.
00076 */
00077 struct _RandomInfo
00078 {
00079   SignatureInfo
00080     *signature_info;
00081 
00082   StringInfo
00083     *nonce,
00084     *reservoir;
00085 
00086   size_t
00087     i;
00088 
00089   unsigned long
00090     seed[4];
00091 
00092   double
00093     normalize;
00094 
00095   unsigned short
00096     protocol_major,
00097     protocol_minor;
00098 
00099   SemaphoreInfo
00100     *semaphore;
00101 
00102   ssize_t
00103     timestamp;
00104 
00105   size_t
00106     signature;
00107 };
00108 
00109 /*
00110   External declarations.
00111 */
00112 #if defined(__APPLE__) && !defined(TARGET_OS_IPHONE)
00113 #include <crt_externs.h>
00114 #define environ (*_NSGetEnviron())
00115 #endif
00116 
00117 extern char
00118   **environ;
00119 
00120 /*
00121   Global declarations.
00122 */
00123 static SemaphoreInfo
00124   *random_semaphore = (SemaphoreInfo *) NULL;
00125 
00126 static unsigned long
00127   random_seed = ~0UL;
00128 
00129 static MagickBooleanType
00130   gather_true_random = MagickFalse;
00131 
00132 /*
00133   Forward declarations.
00134 */
00135 static StringInfo
00136   *GenerateEntropicChaos(RandomInfo *);
00137 
00138 /*
00139 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
00140 %                                                                             %
00141 %                                                                             %
00142 %                                                                             %
00143 %   A c q u i r e R a n d o m I n f o                                         %
00144 %                                                                             %
00145 %                                                                             %
00146 %                                                                             %
00147 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
00148 %
00149 %  AcquireRandomInfo() allocates the RandomInfo structure.
00150 %
00151 %  The format of the AcquireRandomInfo method is:
00152 %
00153 %      RandomInfo *AcquireRandomInfo(void)
00154 %
00155 */
00156 
00157 static inline size_t MagickMin(const size_t x,const size_t y)
00158 {
00159   if (x < y)
00160     return(x);
00161   return(y);
00162 }
00163 
00164 MagickExport RandomInfo *AcquireRandomInfo(void)
00165 {
00166   const StringInfo
00167     *digest;
00168 
00169   RandomInfo
00170     *random_info;
00171 
00172   StringInfo
00173     *entropy,
00174     *key,
00175     *nonce;
00176 
00177   random_info=(RandomInfo *) AcquireMagickMemory(sizeof(*random_info));
00178   if (random_info == (RandomInfo *) NULL)
00179     ThrowFatalException(ResourceLimitFatalError,"MemoryAllocationFailed");
00180   (void) ResetMagickMemory(random_info,0,sizeof(*random_info));
00181   random_info->signature_info=AcquireSignatureInfo();
00182   random_info->nonce=AcquireStringInfo(2*GetSignatureDigestsize(
00183     random_info->signature_info));
00184   ResetStringInfo(random_info->nonce);
00185   random_info->reservoir=AcquireStringInfo(GetSignatureDigestsize(
00186     random_info->signature_info));
00187   ResetStringInfo(random_info->reservoir);
00188   random_info->normalize=1.0/(~0UL);
00189   random_info->semaphore=AllocateSemaphoreInfo();
00190   random_info->protocol_major=RandomProtocolMajorVersion;
00191   random_info->protocol_minor=RandomProtocolMinorVersion;
00192   random_info->timestamp=(ssize_t) time(0);
00193   random_info->signature=MagickSignature;
00194   /*
00195     Seed random nonce.
00196   */
00197   nonce=GenerateEntropicChaos(random_info);
00198   if (nonce == (StringInfo *) NULL)
00199     ThrowFatalException(ResourceLimitFatalError,"MemoryAllocationFailed");
00200   InitializeSignature(random_info->signature_info);
00201   UpdateSignature(random_info->signature_info,nonce);
00202   FinalizeSignature(random_info->signature_info);
00203   SetStringInfoLength(nonce,(GetSignatureDigestsize(
00204     random_info->signature_info)+1)/2);
00205   SetStringInfo(nonce,GetSignatureDigest(random_info->signature_info));
00206   SetStringInfo(random_info->nonce,nonce);
00207   nonce=DestroyStringInfo(nonce);
00208   /*
00209     Seed random reservoir with entropic data.
00210   */
00211   entropy=GenerateEntropicChaos(random_info);
00212   if (entropy == (StringInfo *) NULL)
00213     ThrowFatalException(ResourceLimitFatalError,"MemoryAllocationFailed");
00214   UpdateSignature(random_info->signature_info,entropy);
00215   FinalizeSignature(random_info->signature_info);
00216   SetStringInfo(random_info->reservoir,GetSignatureDigest(
00217     random_info->signature_info));
00218   entropy=DestroyStringInfo(entropy);
00219   /*
00220     Seed pseudo random number generator.
00221   */
00222   if (random_seed == ~0UL)
00223     {
00224       key=GetRandomKey(random_info,sizeof(random_seed));
00225       (void) CopyMagickMemory(random_info->seed,GetStringInfoDatum(key),
00226         GetStringInfoLength(key));
00227       key=DestroyStringInfo(key);
00228     }
00229   else
00230     {
00231       SignatureInfo
00232         *signature_info;
00233 
00234       signature_info=AcquireSignatureInfo();
00235       key=AcquireStringInfo(sizeof(random_seed));
00236       SetStringInfoDatum(key,(unsigned char *) &random_seed);
00237       UpdateSignature(signature_info,key);
00238       key=DestroyStringInfo(key);
00239       FinalizeSignature(signature_info);
00240       digest=GetSignatureDigest(signature_info);
00241       (void) CopyMagickMemory(random_info->seed,GetStringInfoDatum(digest),
00242         MagickMin(GetSignatureDigestsize(signature_info),
00243         sizeof(*random_info->seed)));
00244       signature_info=DestroySignatureInfo(signature_info);
00245     }
00246   random_info->seed[1]=0x50a7f451UL;
00247   random_info->seed[2]=0x5365417eUL;
00248   random_info->seed[3]=0xc3a4171aUL;
00249   return(random_info);
00250 }
00251 
00252 /*
00253 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
00254 %                                                                             %
00255 %                                                                             %
00256 %                                                                             %
00257 +   D e s t r o y R a n d o m I n f o                                         %
00258 %                                                                             %
00259 %                                                                             %
00260 %                                                                             %
00261 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
00262 %
00263 %  DestroyRandomInfo() deallocates memory associated with the random
00264 %  reservoir.
00265 %
00266 %  The format of the DestroyRandomInfo method is:
00267 %
00268 %      RandomInfo *DestroyRandomInfo(RandomInfo *random_info)
00269 %
00270 %  A description of each parameter follows:
00271 %
00272 %    o random_info: the random info.
00273 %
00274 */
00275 MagickExport RandomInfo *DestroyRandomInfo(RandomInfo *random_info)
00276 {
00277   (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
00278   assert(random_info != (RandomInfo *) NULL);
00279   assert(random_info->signature == MagickSignature);
00280   LockSemaphoreInfo(random_info->semaphore);
00281   if (random_info->reservoir != (StringInfo *) NULL)
00282     random_info->reservoir=DestroyStringInfo(random_info->reservoir);
00283   if (random_info->nonce != (StringInfo *) NULL)
00284     random_info->nonce=DestroyStringInfo(random_info->nonce);
00285   if (random_info->signature_info != (SignatureInfo *) NULL)
00286     random_info->signature_info=DestroySignatureInfo(
00287       random_info->signature_info);
00288   (void) ResetMagickMemory(random_info->seed,0,sizeof(*random_info->seed));
00289   random_info->signature=(~MagickSignature);
00290   UnlockSemaphoreInfo(random_info->semaphore);
00291   DestroySemaphoreInfo(&random_info->semaphore);
00292   random_info=(RandomInfo *) RelinquishMagickMemory(random_info);
00293   return(random_info);
00294 }
00295 
00296 /*
00297 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
00298 %                                                                             %
00299 %                                                                             %
00300 %                                                                             %
00301 +   G e n e r a t e E n t r o p i c C h a o s                                 %
00302 %                                                                             %
00303 %                                                                             %
00304 %                                                                             %
00305 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
00306 %
00307 %  GenerateEntropicChaos() generate entropic chaos used to initialize the
00308 %  random reservoir.
00309 %
00310 %  The format of the GenerateEntropicChaos method is:
00311 %
00312 %      StringInfo *GenerateEntropicChaos(RandomInfo *random_info)
00313 %
00314 %  A description of each parameter follows:
00315 %
00316 %    o random_info: the random info.
00317 %
00318 */
00319 
00320 #if !defined(MAGICKCORE_WINDOWS_SUPPORT)
00321 static ssize_t ReadRandom(int file,unsigned char *source,size_t length)
00322 {
00323   register unsigned char
00324     *q;
00325 
00326   ssize_t
00327     offset,
00328     count;
00329 
00330   offset=0;
00331   for (q=source; length != 0; length-=count)
00332   {
00333     count=(ssize_t) read(file,q,length);
00334     if (count <= 0)
00335       {
00336         count=0;
00337         if (errno == EINTR)
00338           continue;
00339         return(-1);
00340       }
00341     q+=count;
00342     offset+=count;
00343   }
00344   return(offset);
00345 }
00346 #endif
00347 
00348 static StringInfo *GenerateEntropicChaos(RandomInfo *random_info)
00349 {
00350 #define MaxEntropyExtent  64
00351 
00352   MagickThreadType
00353     tid;
00354 
00355   StringInfo
00356     *chaos,
00357     *entropy;
00358 
00359   size_t
00360     nanoseconds,
00361     seconds;
00362 
00363   ssize_t
00364     pid;
00365 
00366   /*
00367     Initialize random reservoir.
00368   */
00369   entropy=AcquireStringInfo(0);
00370   LockSemaphoreInfo(random_info->semaphore);
00371   chaos=AcquireStringInfo(sizeof(unsigned char *));
00372   SetStringInfoDatum(chaos,(unsigned char *) &entropy);
00373   ConcatenateStringInfo(entropy,chaos);
00374   SetStringInfoDatum(chaos,(unsigned char *) entropy);
00375   ConcatenateStringInfo(entropy,chaos);
00376   pid=(ssize_t) getpid();
00377   SetStringInfoLength(chaos,sizeof(pid));
00378   SetStringInfoDatum(chaos,(unsigned char *) &pid);
00379   ConcatenateStringInfo(entropy,chaos);
00380   tid=GetMagickThreadId();
00381   SetStringInfoLength(chaos,sizeof(tid));
00382   SetStringInfoDatum(chaos,(unsigned char *) &tid);
00383   ConcatenateStringInfo(entropy,chaos);
00384 #if defined(MAGICKCORE_HAVE_GETRUSAGE) && defined(RUSAGE_SELF)
00385   {
00386     struct rusage
00387       usage;
00388 
00389     if (getrusage(RUSAGE_SELF,&usage) == 0)
00390       {
00391         SetStringInfoLength(chaos,sizeof(usage));
00392         SetStringInfoDatum(chaos,(unsigned char *) &usage);
00393       }
00394   }
00395 #endif
00396   seconds=time((time_t *) 0);
00397   nanoseconds=0;
00398 #if defined(MAGICKCORE_HAVE_GETTIMEOFDAY)
00399   {
00400     struct timeval
00401       timer;
00402 
00403     if (gettimeofday(&timer,(struct timezone *) NULL) == 0)
00404       {
00405         seconds=timer.tv_sec;
00406         nanoseconds=1000UL*timer.tv_usec;
00407       }
00408   }
00409 #endif
00410 #if defined(MAGICKCORE_HAVE_CLOCK_GETTIME) && defined(CLOCK_REALTIME_HR)
00411   {
00412     struct timespec
00413       timer;
00414 
00415     if (clock_gettime(CLOCK_REALTIME_HR,&timer) == 0)
00416       {
00417         seconds=timer.tv_sec;
00418         nanoseconds=timer.tv_nsec;
00419       }
00420   }
00421 #endif
00422   SetStringInfoLength(chaos,sizeof(seconds));
00423   SetStringInfoDatum(chaos,(unsigned char *) &seconds);
00424   ConcatenateStringInfo(entropy,chaos);
00425   SetStringInfoLength(chaos,sizeof(nanoseconds));
00426   SetStringInfoDatum(chaos,(unsigned char *) &nanoseconds);
00427   ConcatenateStringInfo(entropy,chaos);
00428   nanoseconds=0;
00429 #if defined(MAGICKCORE_HAVE_CLOCK)
00430   nanoseconds=clock();
00431 #endif
00432 #if defined(MAGICKCORE_HAVE_TIMES)
00433   {
00434     struct tms
00435       timer;
00436 
00437     (void) times(&timer);
00438     nanoseconds=timer.tms_utime+timer.tms_stime;
00439   }
00440 #endif
00441   SetStringInfoLength(chaos,sizeof(nanoseconds));
00442   SetStringInfoDatum(chaos,(unsigned char *) &nanoseconds);
00443   ConcatenateStringInfo(entropy,chaos);
00444 #if defined(MAGICKCORE_HAVE_MKSTEMP)
00445   {
00446     char
00447       *filename;
00448 
00449     int
00450       file;
00451 
00452     filename=ConstantString("magickXXXXXX");
00453     file=mkstemp(filename);
00454 #if defined(__OS2__)
00455     setmode(file,O_BINARY);
00456 #endif
00457     if (file != -1)
00458       (void) close(file);
00459     (void) remove_utf8(filename);
00460     SetStringInfoLength(chaos,strlen(filename));
00461     SetStringInfoDatum(chaos,(unsigned char *) filename);
00462     ConcatenateStringInfo(entropy,chaos);
00463     filename=DestroyString(filename);
00464   }
00465 #endif
00466 #if defined(MAGICKCORE_WINDOWS_SUPPORT)
00467   {
00468     double
00469       seconds;
00470 
00471     LARGE_INTEGER
00472       nanoseconds;
00473 
00474     MagickBooleanType
00475       status;
00476 
00477     /*
00478       Not crytographically strong but better than nothing.
00479     */
00480     seconds=NTElapsedTime()+NTUserTime();
00481     SetStringInfoLength(chaos,sizeof(seconds));
00482     SetStringInfoDatum(chaos,(unsigned char *) &seconds);
00483     ConcatenateStringInfo(entropy,chaos);
00484     if (QueryPerformanceCounter(&nanoseconds) != 0)
00485       {
00486         SetStringInfoLength(chaos,sizeof(nanoseconds));
00487         SetStringInfoDatum(chaos,(unsigned char *) &nanoseconds);
00488         ConcatenateStringInfo(entropy,chaos);
00489       }
00490     /*
00491       Our best hope for true entropy.
00492     */
00493     SetStringInfoLength(chaos,MaxEntropyExtent);
00494     status=NTGatherRandomData(MaxEntropyExtent,GetStringInfoDatum(chaos));
00495     ConcatenateStringInfo(entropy,chaos);
00496   }
00497 #else
00498   {
00499     char
00500       *filename;
00501 
00502     int
00503       file;
00504 
00505     ssize_t
00506       count;
00507 
00508     StringInfo
00509       *device;
00510 
00511     /*
00512       Not crytographically strong but better than nothing.
00513     */
00514     if (environ != (char **) NULL)
00515       {
00516         register ssize_t
00517           i;
00518 
00519         /*
00520           Squeeze some entropy from the sometimes unpredicatble environment.
00521         */
00522         for (i=0; environ[i] != (char *) NULL; i++)
00523         {
00524           SetStringInfoLength(chaos,strlen(environ[i]));
00525           SetStringInfoDatum(chaos,(unsigned char *) environ[i]);
00526           ConcatenateStringInfo(entropy,chaos);
00527         }
00528       }
00529     filename=AcquireString("/dev/urandom");
00530     device=StringToStringInfo(filename);
00531     device=DestroyStringInfo(device);
00532     file=open_utf8(filename,O_RDONLY | O_BINARY,0);
00533     filename=DestroyString(filename);
00534     if (file != -1)
00535       {
00536         SetStringInfoLength(chaos,MaxEntropyExtent);
00537         count=ReadRandom(file,GetStringInfoDatum(chaos),MaxEntropyExtent);
00538         (void) close(file);
00539         SetStringInfoLength(chaos,(size_t) count);
00540         ConcatenateStringInfo(entropy,chaos);
00541       }
00542     if (gather_true_random != MagickFalse)
00543       {
00544         /*
00545           Our best hope for true entropy.
00546         */
00547         filename=AcquireString("/dev/random");
00548         device=StringToStringInfo(filename);
00549         device=DestroyStringInfo(device);
00550         file=open_utf8(filename,O_RDONLY | O_BINARY,0);
00551         filename=DestroyString(filename);
00552         if (file == -1)
00553           {
00554             filename=AcquireString("/dev/srandom");
00555             device=StringToStringInfo(filename);
00556             device=DestroyStringInfo(device);
00557             file=open_utf8(filename,O_RDONLY | O_BINARY,0);
00558           }
00559         if (file != -1)
00560           {
00561             SetStringInfoLength(chaos,MaxEntropyExtent);
00562             count=ReadRandom(file,GetStringInfoDatum(chaos),MaxEntropyExtent);
00563             (void) close(file);
00564             SetStringInfoLength(chaos,(size_t) count);
00565             ConcatenateStringInfo(entropy,chaos);
00566           }
00567       }
00568   }
00569 #endif
00570   chaos=DestroyStringInfo(chaos);
00571   UnlockSemaphoreInfo(random_info->semaphore);
00572   return(entropy);
00573 }
00574 
00575 /*
00576 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
00577 %                                                                             %
00578 %                                                                             %
00579 %                                                                             %
00580 %   G e t P s e u d o R a n d o m V a l u e                                   %
00581 %                                                                             %
00582 %                                                                             %
00583 %                                                                             %
00584 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
00585 %
00586 %  GetPseudoRandomValue() return a non-negative double-precision floating-point
00587 %  value uniformly distributed over the interval [0.0, 1.0) with a 2 to the
00588 %  128th-1 period.
00589 %
00590 %  The format of the GetPseudoRandomValue method is:
00591 %
00592 %      double GetPseudoRandomValue(RandomInfo *randon_info)
00593 %
00594 %  A description of each parameter follows:
00595 %
00596 %    o random_info: the random info.
00597 %
00598 */
00599 MagickExport double GetPseudoRandomValue(RandomInfo *random_info)
00600 {
00601   register unsigned long
00602     *seed;
00603 
00604   unsigned long
00605     alpha;
00606 
00607   seed=random_info->seed;
00608   do
00609   {
00610     alpha=(unsigned long) (seed[1] ^ (seed[1] << 11));
00611     seed[1]=seed[2];
00612     seed[2]=seed[3];
00613     seed[3]=seed[0];
00614     seed[0]=(seed[0] ^ (seed[0] >> 19)) ^ (alpha ^ (alpha >> 8));
00615   } while (seed[0] == ~0UL);
00616   return(random_info->normalize*seed[0]);
00617 }
00618 
00619 /*
00620 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
00621 %                                                                             %
00622 %                                                                             %
00623 %                                                                             %
00624 %   G e t R a n d o m K e y                                                   %
00625 %                                                                             %
00626 %                                                                             %
00627 %                                                                             %
00628 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
00629 %
00630 %  GetRandomKey() gets a random key from the reservoir.
00631 %
00632 %  The format of the GetRandomKey method is:
00633 %
00634 %      StringInfo *GetRandomKey(RandomInfo *random_info,const size_t length)
00635 %
00636 %  A description of each parameter follows:
00637 %
00638 %    o random_info: the random info.
00639 %
00640 %    o length: the key length.
00641 %
00642 */
00643 MagickExport StringInfo *GetRandomKey(RandomInfo *random_info,
00644   const size_t length)
00645 {
00646   StringInfo
00647     *key;
00648 
00649   assert(random_info != (RandomInfo *) NULL);
00650   key=AcquireStringInfo(length);
00651   SetRandomKey(random_info,length,GetStringInfoDatum(key));
00652   return(key);
00653 }
00654 
00655 /*
00656 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
00657 %                                                                             %
00658 %                                                                             %
00659 %                                                                             %
00660 %   G e t R a n d o m V a l u e                                               %
00661 %                                                                             %
00662 %                                                                             %
00663 %                                                                             %
00664 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
00665 %
00666 %  GetRandomValue() return a non-negative double-precision floating-point
00667 %  value uniformly distributed over the interval [0.0, 1.0) with a 2 to the
00668 %  128th-1 period (not cryptographically strong).
00669 %
00670 %  The format of the GetRandomValue method is:
00671 %
00672 %      double GetRandomValue(void)
00673 %
00674 */
00675 MagickExport double GetRandomValue(RandomInfo *random_info)
00676 {
00677   unsigned long
00678     key,
00679     range;
00680 
00681   range=(~0UL);
00682   do
00683   {
00684     SetRandomKey(random_info,sizeof(key),(unsigned char *) &key);
00685   } while (key == range);
00686   return((double) key/range);
00687 }
00688 
00689 /*
00690 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
00691 %                                                                             %
00692 %                                                                             %
00693 %                                                                             %
00694 +   R a n d o m C o m p o n e n t G e n e s i s                               %
00695 %                                                                             %
00696 %                                                                             %
00697 %                                                                             %
00698 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
00699 %
00700 %  RandomComponentGenesis() instantiates the random component.
00701 %
00702 %  The format of the RandomComponentGenesis method is:
00703 %
00704 %      MagickBooleanType RandomComponentGenesis(void)
00705 %
00706 */
00707 MagickPrivate MagickBooleanType RandomComponentGenesis(void)
00708 {
00709   AcquireSemaphoreInfo(&random_semaphore);
00710   return(MagickTrue);
00711 }
00712 
00713 /*
00714 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
00715 %                                                                             %
00716 %                                                                             %
00717 %                                                                             %
00718 +   R a n d o m C o m p o n e n t T e r m i n u s                             %
00719 %                                                                             %
00720 %                                                                             %
00721 %                                                                             %
00722 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
00723 %
00724 %  RandomComponentTerminus() destroys the random component.
00725 %
00726 %  The format of the RandomComponentTerminus method is:
00727 %
00728 %      RandomComponentTerminus(void)
00729 %
00730 */
00731 MagickPrivate void RandomComponentTerminus(void)
00732 {
00733   if (random_semaphore == (SemaphoreInfo *) NULL)
00734     AcquireSemaphoreInfo(&random_semaphore);
00735   DestroySemaphoreInfo(&random_semaphore);
00736 }
00737 
00738 /*
00739 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
00740 %                                                                             %
00741 %                                                                             %
00742 %                                                                             %
00743 %   S e e d P s e u d o R a n d o m G e n e r a t o r                         %
00744 %                                                                             %
00745 %                                                                             %
00746 %                                                                             %
00747 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
00748 %
00749 %  SeedPseudoRandomGenerator() initializes the pseudo-random number generator
00750 %  with a random seed.
00751 %
00752 %  The format of the SeedPseudoRandomGenerator method is:
00753 %
00754 %      void SeedPseudoRandomGenerator(const unsigned long seed)
00755 %
00756 %  A description of each parameter follows:
00757 %
00758 %    o seed: the seed.
00759 %
00760 */
00761 MagickExport void SeedPseudoRandomGenerator(const unsigned long seed)
00762 {
00763   random_seed=seed;
00764 }
00765 
00766 /*
00767 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
00768 %                                                                             %
00769 %                                                                             %
00770 %                                                                             %
00771 %   S e t R a n d o m K e y                                                   %
00772 %                                                                             %
00773 %                                                                             %
00774 %                                                                             %
00775 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
00776 %
00777 %  SetRandomKey() sets a random key from the reservoir.
00778 %
00779 %  The format of the SetRandomKey method is:
00780 %
00781 %      void SetRandomKey(RandomInfo *random_info,const size_t length,
00782 %        unsigned char *key)
00783 %
00784 %  A description of each parameter follows:
00785 %
00786 %    o random_info: the random info.
00787 %
00788 %    o length: the key length.
00789 %
00790 %    o key: the key.
00791 %
00792 */
00793 
00794 static inline void IncrementRandomNonce(StringInfo *nonce)
00795 {
00796   register ssize_t
00797     i;
00798 
00799   unsigned char
00800     *datum;
00801 
00802   datum=GetStringInfoDatum(nonce);
00803   for (i=(ssize_t) (GetStringInfoLength(nonce)-1); i != 0; i--)
00804   {
00805     datum[i]++;
00806     if (datum[i] != 0)
00807       return;
00808   }
00809   ThrowFatalException(RandomFatalError,"SequenceWrapError");
00810 }
00811 
00812 MagickExport void SetRandomKey(RandomInfo *random_info,const size_t length,
00813   unsigned char *key)
00814 {
00815   register size_t
00816     i;
00817 
00818   register unsigned char
00819     *p;
00820 
00821   SignatureInfo
00822     *signature_info;
00823 
00824   unsigned char
00825     *datum;
00826 
00827   assert(random_info != (RandomInfo *) NULL);
00828   if (length == 0)
00829     return;
00830   LockSemaphoreInfo(random_info->semaphore);
00831   signature_info=random_info->signature_info;
00832   datum=GetStringInfoDatum(random_info->reservoir);
00833   i=length;
00834   for (p=key; (i != 0) && (random_info->i != 0); i--)
00835   {
00836     *p++=datum[random_info->i];
00837     random_info->i++;
00838     if (random_info->i == GetSignatureDigestsize(signature_info))
00839       random_info->i=0;
00840   }
00841   while (i >= GetSignatureDigestsize(signature_info))
00842   {
00843     InitializeSignature(signature_info);
00844     UpdateSignature(signature_info,random_info->nonce);
00845     FinalizeSignature(signature_info);
00846     IncrementRandomNonce(random_info->nonce);
00847     (void) CopyMagickMemory(p,GetStringInfoDatum(GetSignatureDigest(
00848       signature_info)),GetSignatureDigestsize(signature_info));
00849     p+=GetSignatureDigestsize(signature_info);
00850     i-=GetSignatureDigestsize(signature_info);
00851   }
00852   if (i != 0)
00853     {
00854       InitializeSignature(signature_info);
00855       UpdateSignature(signature_info,random_info->nonce);
00856       FinalizeSignature(signature_info);
00857       IncrementRandomNonce(random_info->nonce);
00858       SetStringInfo(random_info->reservoir,GetSignatureDigest(signature_info));
00859       random_info->i=i;
00860       datum=GetStringInfoDatum(random_info->reservoir);
00861       while (i-- != 0)
00862         p[i]=datum[i];
00863     }
00864   UnlockSemaphoreInfo(random_info->semaphore);
00865 }
00866 
00867 /*
00868 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
00869 %                                                                             %
00870 %                                                                             %
00871 %                                                                             %
00872 %   S e t R a n d o m T r u e R a n d o m                                     %
00873 %                                                                             %
00874 %                                                                             %
00875 %                                                                             %
00876 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
00877 %
00878 %  SetRandomTrueRandom() declares your intentions to use true random numbers.
00879 %  True random numbers are encouraged but may not always be practical because
00880 %  your application may block while entropy is gathered from your environment.
00881 %
00882 %  The format of the SetRandomTrueRandom method is:
00883 %
00884 %      void SetRandomTrueRandom(const MagickBooleanType true_random)
00885 %
00886 %  A description of each parameter follows:
00887 %
00888 %    o true_random: declare your intentions to use true-random number.
00889 %
00890 */
00891 MagickExport void SetRandomTrueRandom(const MagickBooleanType true_random)
00892 {
00893   gather_true_random=true_random;
00894 }