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