47#if defined(__MINGW32__)
50#include "magick/studio.h"
51#include "magick/exception.h"
52#include "magick/exception-private.h"
53#include "magick/image-private.h"
54#include "magick/memory_.h"
55#include "magick/memory-private.h"
56#include "magick/random_.h"
57#include "magick/resource_.h"
58#include "magick/semaphore.h"
59#include "magick/signature-private.h"
60#include "magick/string_.h"
61#include "magick/thread_.h"
62#include "magick/thread-private.h"
63#include "magick/timer-private.h"
64#include "magick/utility-private.h"
65#if defined(MAGICKCORE_HAVE_GETENTROPY)
66#include <sys/random.h>
71#define PseudoRandomHash SHA256Hash
72#define RandomEntropyLevel 9
73#define RandomFilename "reservoir.xdm"
74#define RandomFiletype "random"
75#define RandomProtocolMajorVersion 1
76#define RandomProtocolMinorVersion 0
119#if defined(__APPLE__) && !defined(TARGET_OS_IPHONE)
120#include <crt_externs.h>
121#define environ (*_NSGetEnviron())
124#if !defined(MAGICKCORE_WINDOWS_SUPPORT)
138static MagickBooleanType
139 gather_true_random = MagickFalse;
165MagickExport
RandomInfo *AcquireRandomInfo(
void)
178 random_info=(
RandomInfo *) AcquireCriticalMemory(
sizeof(*random_info));
179 (void) memset(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=(double) (1.0/(MagickULLConstant(~0) >> 11));
188 random_info->seed[0]=MagickULLConstant(0x76e15d3efefdcbbf);
189 random_info->seed[1]=MagickULLConstant(0xc5004e441c522fb3);
190 random_info->seed[2]=MagickULLConstant(0x77710069854ee241);
191 random_info->seed[3]=MagickULLConstant(0x39109bb02acbe635);
192 random_info->secret_key=secret_key;
193 random_info->protocol_major=RandomProtocolMajorVersion;
194 random_info->protocol_minor=RandomProtocolMinorVersion;
195 random_info->semaphore=AllocateSemaphoreInfo();
196 random_info->timestamp=GetMagickTime();
197 random_info->signature=MagickCoreSignature;
201 nonce=GenerateEntropicChaos(random_info);
203 ThrowFatalException(ResourceLimitFatalError,
"MemoryAllocationFailed");
204 InitializeSignature(random_info->signature_info);
205 UpdateSignature(random_info->signature_info,nonce);
206 FinalizeSignature(random_info->signature_info);
207 SetStringInfoLength(nonce,(GetSignatureDigestsize(
208 random_info->signature_info)+1)/2);
209 SetStringInfo(nonce,GetSignatureDigest(random_info->signature_info));
210 SetStringInfo(random_info->nonce,nonce);
211 nonce=DestroyStringInfo(nonce);
215 entropy=GenerateEntropicChaos(random_info);
217 ThrowFatalException(ResourceLimitFatalError,
"MemoryAllocationFailed");
218 UpdateSignature(random_info->signature_info,entropy);
219 FinalizeSignature(random_info->signature_info);
220 SetStringInfo(random_info->reservoir,GetSignatureDigest(
221 random_info->signature_info));
222 entropy=DestroyStringInfo(entropy);
226 if (random_info->secret_key == ~0UL)
228 key=GetRandomKey(random_info,
sizeof(random_info->seed));
229 (void) memcpy(random_info->seed,GetStringInfoDatum(key),
230 sizeof(random_info->seed));
231 key=DestroyStringInfo(key);
238 signature_info=AcquireSignatureInfo();
239 key=AcquireStringInfo(
sizeof(random_info->secret_key));
240 SetStringInfoDatum(key,(
unsigned char *) &random_info->secret_key);
241 UpdateSignature(signature_info,key);
242 key=DestroyStringInfo(key);
243 FinalizeSignature(signature_info);
244 digest=GetSignatureDigest(signature_info);
245 (void) memcpy(random_info->seed,GetStringInfoDatum(digest),
246 MagickMin((
size_t) GetSignatureDigestsize(signature_info),
247 sizeof(random_info->seed)));
248 signature_info=DestroySignatureInfo(signature_info);
279 assert(random_info->signature == MagickCoreSignature);
280 if (IsEventLogging() != MagickFalse)
281 (void) LogMagickEvent(TraceEvent,GetMagickModule(),
"...");
282 LockSemaphoreInfo(random_info->semaphore);
283 if (random_info->reservoir != (
StringInfo *) NULL)
284 random_info->reservoir=DestroyStringInfo(random_info->reservoir);
285 if (random_info->nonce != (
StringInfo *) NULL)
286 random_info->nonce=DestroyStringInfo(random_info->nonce);
288 random_info->signature_info=DestroySignatureInfo(
289 random_info->signature_info);
290 (void) memset(random_info->seed,0,
sizeof(random_info->seed));
291 random_info->signature=(~MagickCoreSignature);
292 UnlockSemaphoreInfo(random_info->semaphore);
293 DestroySemaphoreInfo(&random_info->semaphore);
294 random_info=(
RandomInfo *) RelinquishMagickMemory(random_info);
322#if !defined(MAGICKCORE_WINDOWS_SUPPORT)
323static ssize_t ReadRandom(
int file,
unsigned char *source,
size_t length)
333 for (q=source; length != 0; length-=count)
335 count=(ssize_t) read(file,q,length);
352#define MaxEntropyExtent 64
371 entropy=AcquireStringInfo(0);
372 LockSemaphoreInfo(random_info->semaphore);
373#if defined(MAGICKCORE_HAVE_GETENTROPY)
378 SetStringInfoLength(entropy,MaxEntropyExtent);
379 status=getentropy(GetStringInfoDatum(entropy),MaxEntropyExtent);
382 UnlockSemaphoreInfo(random_info->semaphore);
387 chaos=AcquireStringInfo(
sizeof(
unsigned char *));
388 SetStringInfoDatum(chaos,(
unsigned char *) &entropy);
389 ConcatenateStringInfo(entropy,chaos);
390 SetStringInfoDatum(chaos,(
unsigned char *) entropy);
391 ConcatenateStringInfo(entropy,chaos);
392 pid=(ssize_t) getpid();
393 SetStringInfoLength(chaos,
sizeof(pid));
394 SetStringInfoDatum(chaos,(
unsigned char *) &pid);
395 ConcatenateStringInfo(entropy,chaos);
396 tid=GetMagickThreadId();
397 SetStringInfoLength(chaos,
sizeof(tid));
398 SetStringInfoDatum(chaos,(
unsigned char *) &tid);
399 ConcatenateStringInfo(entropy,chaos);
400#if defined(MAGICKCORE_HAVE_SYSCONF) && defined(_SC_PHYS_PAGES)
405 pages=(ssize_t) sysconf(_SC_PHYS_PAGES);
406 SetStringInfoLength(chaos,
sizeof(pages));
407 SetStringInfoDatum(chaos,(
unsigned char *) &pages);
408 ConcatenateStringInfo(entropy,chaos);
411#if defined(MAGICKCORE_HAVE_GETRUSAGE) && defined(RUSAGE_SELF)
416 if (getrusage(RUSAGE_SELF,&usage) == 0)
418 SetStringInfoLength(chaos,
sizeof(usage));
419 SetStringInfoDatum(chaos,(
unsigned char *) &usage);
423 seconds=time((time_t *) 0);
425#if defined(MAGICKCORE_HAVE_GETTIMEOFDAY)
430 if (gettimeofday(&timer,(
struct timezone *) NULL) == 0)
432 seconds=(size_t) timer.tv_sec;
433 nanoseconds=(size_t) (1000UL*timer.tv_usec);
437#if defined(MAGICKCORE_HAVE_CLOCK_GETTIME) && defined(CLOCK_REALTIME_HR)
442 if (clock_gettime(CLOCK_REALTIME_HR,&timer) == 0)
444 seconds=timer.tv_sec;
445 nanoseconds=timer.tv_nsec;
449 SetStringInfoLength(chaos,
sizeof(seconds));
450 SetStringInfoDatum(chaos,(
unsigned char *) &seconds);
451 ConcatenateStringInfo(entropy,chaos);
452 SetStringInfoLength(chaos,
sizeof(nanoseconds));
453 SetStringInfoDatum(chaos,(
unsigned char *) &nanoseconds);
454 ConcatenateStringInfo(entropy,chaos);
456#if defined(MAGICKCORE_HAVE_CLOCK)
459#if defined(MAGICKCORE_HAVE_TIMES)
464 (void) times(&timer);
465 nanoseconds=timer.tms_utime+timer.tms_stime;
468 SetStringInfoLength(chaos,
sizeof(nanoseconds));
469 SetStringInfoDatum(chaos,(
unsigned char *) &nanoseconds);
470 ConcatenateStringInfo(entropy,chaos);
471#if defined(MAGICKCORE_WINDOWS_SUPPORT)
482 seconds=NTElapsedTime()+NTUserTime();
483 SetStringInfoLength(chaos,
sizeof(seconds));
484 SetStringInfoDatum(chaos,(
unsigned char *) &seconds);
485 ConcatenateStringInfo(entropy,chaos);
486 if (QueryPerformanceCounter(&nanoseconds) != 0)
488 SetStringInfoLength(chaos,
sizeof(nanoseconds));
489 SetStringInfoDatum(chaos,(
unsigned char *) &nanoseconds);
490 ConcatenateStringInfo(entropy,chaos);
495 SetStringInfoLength(chaos,MaxEntropyExtent);
496 (void) NTGatherRandomData(MaxEntropyExtent,GetStringInfoDatum(chaos));
497 ConcatenateStringInfo(entropy,chaos);
516 if (environ != (
char **) NULL)
524 for (i=0; environ[i] != (
char *) NULL; i++)
526 SetStringInfoLength(chaos,strlen(environ[i]));
527 SetStringInfoDatum(chaos,(
unsigned char *) environ[i]);
528 ConcatenateStringInfo(entropy,chaos);
531 filename=AcquireString(
"/dev/urandom");
532 device=StringToStringInfo(filename);
533 device=DestroyStringInfo(device);
534 file=open_utf8(filename,O_RDONLY | O_BINARY,0);
535 filename=DestroyString(filename);
538 SetStringInfoLength(chaos,MaxEntropyExtent);
539 count=ReadRandom(file,GetStringInfoDatum(chaos),MaxEntropyExtent);
541 SetStringInfoLength(chaos,(
size_t) count);
542 ConcatenateStringInfo(entropy,chaos);
544 if (gather_true_random != MagickFalse)
549 filename=AcquireString(
"/dev/random");
550 device=StringToStringInfo(filename);
551 device=DestroyStringInfo(device);
552 file=open_utf8(filename,O_RDONLY | O_BINARY,0);
553 filename=DestroyString(filename);
556 filename=AcquireString(
"/dev/srandom");
557 device=StringToStringInfo(filename);
558 device=DestroyStringInfo(device);
559 file=open_utf8(filename,O_RDONLY | O_BINARY,0);
563 SetStringInfoLength(chaos,MaxEntropyExtent);
564 count=ReadRandom(file,GetStringInfoDatum(chaos),MaxEntropyExtent);
566 SetStringInfoLength(chaos,(
size_t) count);
567 ConcatenateStringInfo(entropy,chaos);
572 chaos=DestroyStringInfo(chaos);
573 UnlockSemaphoreInfo(random_info->semaphore);
601MagickExport
double GetPseudoRandomValue(
604#define RandomROTL(x,k) (((x) << (k)) | ((x) >> (64-(k))))
607 alpha = (random_info->seed[1] << 17),
608 value = (random_info->seed[0]+random_info->seed[3]);
610 random_info->seed[2]^=random_info->seed[0];
611 random_info->seed[3]^=random_info->seed[1];
612 random_info->seed[1]^=random_info->seed[2];
613 random_info->seed[0]^=random_info->seed[3];
614 random_info->seed[2]^=alpha;
615 random_info->seed[3]=RandomROTL(random_info->seed[3],45);
616 return((
double) ((value >> 11)*random_info->normalize));
641MagickPrivate
double GetRandomInfoNormalize(
const RandomInfo *random_info)
643 assert(random_info != (
const RandomInfo *) NULL);
644 return(random_info->normalize);
669MagickPrivate
unsigned long *GetRandomInfoSeed(
RandomInfo *random_info)
672 return((
unsigned long *) random_info->seed);
706 key=AcquireStringInfo(length);
707 SetRandomKey(random_info,length,GetStringInfoDatum(key));
732MagickExport
unsigned long GetRandomSecretKey(
const RandomInfo *random_info)
734 return(random_info->secret_key);
757MagickExport
double GetRandomValue(
RandomInfo *random_info)
766 SetRandomKey(random_info,
sizeof(key),(
unsigned char *) &key);
767 }
while (key == range);
768 return((
double) key/range);
789MagickExport MagickBooleanType RandomComponentGenesis(
void)
792 random_semaphore=AllocateSemaphoreInfo();
814MagickExport
void RandomComponentTerminus(
void)
817 ActivateSemaphoreInfo(&random_semaphore);
818 DestroySemaphoreInfo(&random_semaphore);
849static inline void IncrementRandomNonce(
StringInfo *nonce)
857 datum=GetStringInfoDatum(nonce);
858 for (i=(ssize_t) (GetStringInfoLength(nonce)-1); i != 0; i--)
864 ThrowFatalException(RandomFatalError,
"SequenceWrapError");
867MagickExport
void SetRandomKey(
RandomInfo *random_info,
const size_t length,
885 LockSemaphoreInfo(random_info->semaphore);
886 signature_info=random_info->signature_info;
887 datum=GetStringInfoDatum(random_info->reservoir);
889 for (p=key; (i != 0) && (random_info->i != 0); i--)
891 *p++=datum[random_info->i];
893 if (random_info->i == GetSignatureDigestsize(signature_info))
896 while (i >= GetSignatureDigestsize(signature_info))
898 InitializeSignature(signature_info);
899 UpdateSignature(signature_info,random_info->nonce);
900 FinalizeSignature(signature_info);
901 IncrementRandomNonce(random_info->nonce);
902 (void) memcpy(p,GetStringInfoDatum(GetSignatureDigest(
903 signature_info)),GetSignatureDigestsize(signature_info));
904 p+=GetSignatureDigestsize(signature_info);
905 i-=GetSignatureDigestsize(signature_info);
909 InitializeSignature(signature_info);
910 UpdateSignature(signature_info,random_info->nonce);
911 FinalizeSignature(signature_info);
912 IncrementRandomNonce(random_info->nonce);
913 SetStringInfo(random_info->reservoir,GetSignatureDigest(signature_info));
915 datum=GetStringInfoDatum(random_info->reservoir);
919 UnlockSemaphoreInfo(random_info->semaphore);
945MagickExport
void SeedPseudoRandomGenerator(
const unsigned long seed)
947 SetRandomSecretKey(seed);
950MagickExport
void SetRandomSecretKey(
const unsigned long key)
979MagickExport
void SetRandomTrueRandom(
const MagickBooleanType true_random)
981 gather_true_random=true_random;