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

Generated on 19 Nov 2009 for MagickCore by  doxygen 1.6.1