47#if defined(__MINGW32__) 
   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/memory-private.h" 
   56#include "MagickCore/random_.h" 
   57#include "MagickCore/random-private.h" 
   58#include "MagickCore/resource_.h" 
   59#include "MagickCore/semaphore.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/timer-private.h" 
   65#include "MagickCore/utility.h" 
   66#include "MagickCore/utility-private.h" 
   67#if defined(MAGICKCORE_HAVE_GETENTROPY) 
   68#include <sys/random.h> 
   73#define PseudoRandomHash  SHA256Hash 
   74#define RandomEntropyLevel  9 
   75#define RandomFilename  "reservoir.xdm" 
   76#define RandomFiletype  "random" 
   77#define RandomProtocolMajorVersion  1 
   78#define RandomProtocolMinorVersion  0 
  121#if defined(__APPLE__) && !defined(TARGET_OS_IPHONE) 
  122#include <crt_externs.h> 
  123#define environ (*_NSGetEnviron()) 
  126#if !defined(MAGICKCORE_WINDOWS_SUPPORT) 
  140static MagickBooleanType
 
  141  gather_true_random = MagickFalse;
 
  147  *GenerateEntropicChaos(RandomInfo *);
 
  167MagickExport RandomInfo *AcquireRandomInfo(
void)
 
  180  random_info=(RandomInfo *) AcquireCriticalMemory(
sizeof(*random_info));
 
  181  (void) memset(random_info,0,
sizeof(*random_info));
 
  182  random_info->signature_info=AcquireSignatureInfo();
 
  183  random_info->nonce=AcquireStringInfo(2*GetSignatureDigestsize(
 
  184    random_info->signature_info));
 
  185  ResetStringInfo(random_info->nonce);
 
  186  random_info->reservoir=AcquireStringInfo(GetSignatureDigestsize(
 
  187    random_info->signature_info));
 
  188  ResetStringInfo(random_info->reservoir);
 
  189  random_info->normalize=(double) (1.0/(MagickULLConstant(~0) >> 11));
 
  190  random_info->seed[0]=MagickULLConstant(0x76e15d3efefdcbbf);
 
  191  random_info->seed[1]=MagickULLConstant(0xc5004e441c522fb3);
 
  192  random_info->seed[2]=MagickULLConstant(0x77710069854ee241);
 
  193  random_info->seed[3]=MagickULLConstant(0x39109bb02acbe635);
 
  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=GetMagickTime();
 
  199  random_info->signature=MagickCoreSignature;
 
  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);
 
  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);
 
  228  if (random_info->secret_key == ~0UL)
 
  230      key=GetRandomKey(random_info,
sizeof(random_info->seed));
 
  231      (void) memcpy(random_info->seed,GetStringInfoDatum(key),
 
  232        sizeof(random_info->seed));
 
  233      key=DestroyStringInfo(key);
 
  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) memcpy(random_info->seed,GetStringInfoDatum(digest),
 
  248        MagickMin((
size_t) GetSignatureDigestsize(signature_info),
 
  249        sizeof(random_info->seed)));
 
  250      signature_info=DestroySignatureInfo(signature_info);
 
  278MagickExport RandomInfo *DestroyRandomInfo(RandomInfo *random_info)
 
  280  assert(random_info != (RandomInfo *) NULL);
 
  281  assert(random_info->signature == MagickCoreSignature);
 
  282  if (IsEventLogging() != MagickFalse)
 
  283    (void) LogMagickEvent(TraceEvent,GetMagickModule(),
"...");
 
  284  LockSemaphoreInfo(random_info->semaphore);
 
  285  if (random_info->reservoir != (StringInfo *) NULL)
 
  286    random_info->reservoir=DestroyStringInfo(random_info->reservoir);
 
  287  if (random_info->nonce != (StringInfo *) NULL)
 
  288    random_info->nonce=DestroyStringInfo(random_info->nonce);
 
  289  if (random_info->signature_info != (SignatureInfo *) NULL)
 
  290    random_info->signature_info=DestroySignatureInfo(
 
  291      random_info->signature_info);
 
  292  (void) memset(random_info->seed,0,
sizeof(random_info->seed));
 
  293  random_info->signature=(~MagickCoreSignature);
 
  294  UnlockSemaphoreInfo(random_info->semaphore);
 
  295  RelinquishSemaphoreInfo(&random_info->semaphore);
 
  296  random_info=(RandomInfo *) RelinquishMagickMemory(random_info);
 
  324#if !defined(MAGICKCORE_WINDOWS_SUPPORT) 
  325static ssize_t ReadRandom(
int file,
unsigned char *source,
size_t length)
 
  335  for (q=source; length != 0; length-=(size_t) count)
 
  337    count=(ssize_t) read(file,q,length);
 
  345    q+=(ptrdiff_t) count;
 
  352static StringInfo *GenerateEntropicChaos(RandomInfo *random_info)
 
  354#define MaxEntropyExtent  64   
  373  entropy=AcquireStringInfo(0);
 
  374  LockSemaphoreInfo(random_info->semaphore);
 
  375#if defined(MAGICKCORE_HAVE_GETENTROPY) 
  380    SetStringInfoLength(entropy,MaxEntropyExtent);
 
  381    status=getentropy(GetStringInfoDatum(entropy),MaxEntropyExtent);
 
  384        UnlockSemaphoreInfo(random_info->semaphore);
 
  389  chaos=AcquireStringInfo(
sizeof(
unsigned char *));
 
  390  SetStringInfoDatum(chaos,(
unsigned char *) &entropy);
 
  391  ConcatenateStringInfo(entropy,chaos);
 
  392  SetStringInfoDatum(chaos,(
unsigned char *) entropy);
 
  393  ConcatenateStringInfo(entropy,chaos);
 
  394  pid=(ssize_t) getpid();
 
  395  SetStringInfoLength(chaos,
sizeof(pid));
 
  396  SetStringInfoDatum(chaos,(
unsigned char *) &pid);
 
  397  ConcatenateStringInfo(entropy,chaos);
 
  398  tid=GetMagickThreadId();
 
  399  SetStringInfoLength(chaos,
sizeof(tid));
 
  400  SetStringInfoDatum(chaos,(
unsigned char *) &tid);
 
  401  ConcatenateStringInfo(entropy,chaos);
 
  402#if defined(MAGICKCORE_HAVE_SYSCONF) && defined(_SC_PHYS_PAGES) 
  407    pages=(ssize_t) sysconf(_SC_PHYS_PAGES);
 
  408    SetStringInfoLength(chaos,
sizeof(pages));
 
  409    SetStringInfoDatum(chaos,(
unsigned char *) &pages);
 
  410    ConcatenateStringInfo(entropy,chaos);
 
  413#if defined(MAGICKCORE_HAVE_GETRUSAGE) && defined(RUSAGE_SELF) 
  418    if (getrusage(RUSAGE_SELF,&usage) == 0)
 
  420        SetStringInfoLength(chaos,
sizeof(usage));
 
  421        SetStringInfoDatum(chaos,(
unsigned char *) &usage);
 
  425  seconds=time((time_t *) 0);
 
  427#if defined(MAGICKCORE_HAVE_GETTIMEOFDAY) 
  432    if (gettimeofday(&timer,(
struct timezone *) NULL) == 0)
 
  434        seconds=timer.tv_sec;
 
  435        nanoseconds=1000*timer.tv_usec;
 
  439#if defined(MAGICKCORE_HAVE_CLOCK_GETTIME) && defined(CLOCK_REALTIME_HR) 
  444    if (clock_gettime(CLOCK_REALTIME_HR,&timer) == 0)
 
  446        seconds=timer.tv_sec;
 
  447        nanoseconds=timer.tv_nsec;
 
  451  SetStringInfoLength(chaos,
sizeof(seconds));
 
  452  SetStringInfoDatum(chaos,(
unsigned char *) &seconds);
 
  453  ConcatenateStringInfo(entropy,chaos);
 
  454  SetStringInfoLength(chaos,
sizeof(nanoseconds));
 
  455  SetStringInfoDatum(chaos,(
unsigned char *) &nanoseconds);
 
  456  ConcatenateStringInfo(entropy,chaos);
 
  458#if defined(MAGICKCORE_HAVE_CLOCK) 
  461#if defined(MAGICKCORE_HAVE_TIMES) 
  466    (void) times(&timer);
 
  467    nanoseconds=timer.tms_utime+timer.tms_stime;
 
  470  SetStringInfoLength(chaos,
sizeof(nanoseconds));
 
  471  SetStringInfoDatum(chaos,(
unsigned char *) &nanoseconds);
 
  472  ConcatenateStringInfo(entropy,chaos);
 
  473#if defined(MAGICKCORE_WINDOWS_SUPPORT) 
  484    nt_seconds=NTElapsedTime()+NTElapsedTime();
 
  485    SetStringInfoLength(chaos,
sizeof(nt_seconds));
 
  486    SetStringInfoDatum(chaos,(
unsigned char *) &nt_seconds);
 
  487    ConcatenateStringInfo(entropy,chaos);
 
  488    if (QueryPerformanceCounter(&nt_nanoseconds) != 0)
 
  490        SetStringInfoLength(chaos,
sizeof(nt_nanoseconds));
 
  491        SetStringInfoDatum(chaos,(
unsigned char *) &nt_nanoseconds);
 
  492        ConcatenateStringInfo(entropy,chaos);
 
  497    SetStringInfoLength(chaos,MaxEntropyExtent);
 
  498    (void) NTGatherRandomData(MaxEntropyExtent,GetStringInfoDatum(chaos));
 
  499    ConcatenateStringInfo(entropy,chaos);
 
  518    if (environ != (
char **) NULL)
 
  526        for (i=0; environ[i] != (
char *) NULL; i++)
 
  528          SetStringInfoLength(chaos,strlen(environ[i]));
 
  529          SetStringInfoDatum(chaos,(
unsigned char *) environ[i]);
 
  530          ConcatenateStringInfo(entropy,chaos);
 
  533    filename=AcquireString(
"/dev/urandom");
 
  534    device=StringToStringInfo(filename);
 
  535    device=DestroyStringInfo(device);
 
  536    file=open_utf8(filename,O_RDONLY | O_BINARY,0);
 
  537    filename=DestroyString(filename);
 
  540        SetStringInfoLength(chaos,MaxEntropyExtent);
 
  541        count=ReadRandom(file,GetStringInfoDatum(chaos),MaxEntropyExtent);
 
  542        (void) close_utf8(file);
 
  543        SetStringInfoLength(chaos,(
size_t) count);
 
  544        ConcatenateStringInfo(entropy,chaos);
 
  546    if (gather_true_random != MagickFalse)
 
  551        filename=AcquireString(
"/dev/random");
 
  552        device=StringToStringInfo(filename);
 
  553        device=DestroyStringInfo(device);
 
  554        file=open_utf8(filename,O_RDONLY | O_BINARY,0);
 
  555        filename=DestroyString(filename);
 
  558            filename=AcquireString(
"/dev/srandom");
 
  559            device=StringToStringInfo(filename);
 
  560            device=DestroyStringInfo(device);
 
  561            file=open_utf8(filename,O_RDONLY | O_BINARY,0);
 
  565            SetStringInfoLength(chaos,MaxEntropyExtent);
 
  566            count=ReadRandom(file,GetStringInfoDatum(chaos),MaxEntropyExtent);
 
  567            (void) close_utf8(file);
 
  568            SetStringInfoLength(chaos,(
size_t) count);
 
  569            ConcatenateStringInfo(entropy,chaos);
 
  574  chaos=DestroyStringInfo(chaos);
 
  575  UnlockSemaphoreInfo(random_info->semaphore);
 
  603MagickExport 
double GetPseudoRandomValue(
 
  604  RandomInfo *magick_restrict random_info)
 
  606#define RandomROTL(x,k) (((x) << (k)) | ((x) >> (64-(k)))) 
  609    alpha = (random_info->seed[1] << 17),
 
  610    value = (random_info->seed[0]+random_info->seed[3]);
 
  612  random_info->seed[2]^=random_info->seed[0];
 
  613  random_info->seed[3]^=random_info->seed[1];
 
  614  random_info->seed[1]^=random_info->seed[2];
 
  615  random_info->seed[0]^=random_info->seed[3];
 
  616  random_info->seed[2]^=alpha;
 
  617  random_info->seed[3]=RandomROTL(random_info->seed[3],45);
 
  618  return((
double) ((value >> 11)*random_info->normalize));
 
  643MagickPrivate 
double GetRandomInfoNormalize(
const RandomInfo *random_info)
 
  645  assert(random_info != (
const RandomInfo *) NULL);
 
  646  return(random_info->normalize);
 
  671MagickPrivate 
unsigned long *GetRandomInfoSeed(RandomInfo *random_info)
 
  673  assert(random_info != (RandomInfo *) NULL);
 
  674  return((
unsigned long *) random_info->seed);
 
  701MagickExport StringInfo *GetRandomKey(RandomInfo *random_info,
 
  707  assert(random_info != (RandomInfo *) NULL);
 
  708  key=AcquireStringInfo(length);
 
  709  SetRandomKey(random_info,length,GetStringInfoDatum(key));
 
  734MagickExport 
unsigned long GetRandomSecretKey(
const RandomInfo *random_info)
 
  736  return(random_info->secret_key);
 
  759MagickExport 
double GetRandomValue(RandomInfo *random_info)
 
  768    SetRandomKey(random_info,
sizeof(key),(
unsigned char *) &key);
 
  769  } 
while (key == range);
 
  770  return((
double) key/range);
 
  791MagickPrivate MagickBooleanType RandomComponentGenesis(
void)
 
  794    random_semaphore=AcquireSemaphoreInfo();
 
  816MagickPrivate 
void RandomComponentTerminus(
void)
 
  819    ActivateSemaphoreInfo(&random_semaphore);
 
  820  RelinquishSemaphoreInfo(&random_semaphore);
 
  851static inline void IncrementRandomNonce(StringInfo *nonce)
 
  859  datum=GetStringInfoDatum(nonce);
 
  860  for (i=(ssize_t) (GetStringInfoLength(nonce)-1); i != 0; i--)
 
  866  ThrowFatalException(RandomFatalError,
"SequenceWrapError");
 
  869MagickExport 
void SetRandomKey(RandomInfo *random_info,
const size_t length,
 
  884  assert(random_info != (RandomInfo *) NULL);
 
  887  LockSemaphoreInfo(random_info->semaphore);
 
  888  signature_info=random_info->signature_info;
 
  889  datum=GetStringInfoDatum(random_info->reservoir);
 
  891  for (p=key; (i != 0) && (random_info->i != 0); i--)
 
  893    *p++=datum[random_info->i];
 
  895    if (random_info->i == GetSignatureDigestsize(signature_info))
 
  898  while (i >= GetSignatureDigestsize(signature_info))
 
  900    InitializeSignature(signature_info);
 
  901    UpdateSignature(signature_info,random_info->nonce);
 
  902    FinalizeSignature(signature_info);
 
  903    IncrementRandomNonce(random_info->nonce);
 
  904    (void) memcpy(p,GetStringInfoDatum(GetSignatureDigest(
 
  905      signature_info)),GetSignatureDigestsize(signature_info));
 
  906    p+=(ptrdiff_t) GetSignatureDigestsize(signature_info);
 
  907    i-=GetSignatureDigestsize(signature_info);
 
  911      InitializeSignature(signature_info);
 
  912      UpdateSignature(signature_info,random_info->nonce);
 
  913      FinalizeSignature(signature_info);
 
  914      IncrementRandomNonce(random_info->nonce);
 
  915      SetStringInfo(random_info->reservoir,GetSignatureDigest(signature_info));
 
  917      datum=GetStringInfoDatum(random_info->reservoir);
 
  921  UnlockSemaphoreInfo(random_info->semaphore);
 
  946MagickExport 
void SetRandomSecretKey(
const unsigned long key)
 
  975MagickExport 
void SetRandomTrueRandom(
const MagickBooleanType true_random)
 
  977  gather_true_random=true_random;