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