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