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#ifdef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION
381 SetStringInfoLength(entropy,MaxEntropyExtent);
382 datum=GetStringInfoDatum(entropy);
383 (void) memset(datum,0x42,MaxEntropyExtent);
384 UnlockSemaphoreInfo(random_info->semaphore);
388#if defined(MAGICKCORE_HAVE_GETENTROPY)
393 SetStringInfoLength(entropy,MaxEntropyExtent);
394 status=getentropy(GetStringInfoDatum(entropy),MaxEntropyExtent);
397 UnlockSemaphoreInfo(random_info->semaphore);
402 chaos=AcquireStringInfo(
sizeof(
unsigned char *));
403 SetStringInfoDatum(chaos,(
unsigned char *) &entropy);
404 ConcatenateStringInfo(entropy,chaos);
405 SetStringInfoDatum(chaos,(
unsigned char *) entropy);
406 ConcatenateStringInfo(entropy,chaos);
407 pid=(ssize_t) getpid();
408 SetStringInfoLength(chaos,
sizeof(pid));
409 SetStringInfoDatum(chaos,(
unsigned char *) &pid);
410 ConcatenateStringInfo(entropy,chaos);
411 tid=GetMagickThreadId();
412 SetStringInfoLength(chaos,
sizeof(tid));
413 SetStringInfoDatum(chaos,(
unsigned char *) &tid);
414 ConcatenateStringInfo(entropy,chaos);
415#if defined(MAGICKCORE_HAVE_SYSCONF) && defined(_SC_PHYS_PAGES)
420 pages=(ssize_t) sysconf(_SC_PHYS_PAGES);
421 SetStringInfoLength(chaos,
sizeof(pages));
422 SetStringInfoDatum(chaos,(
unsigned char *) &pages);
423 ConcatenateStringInfo(entropy,chaos);
426#if defined(MAGICKCORE_HAVE_GETRUSAGE) && defined(RUSAGE_SELF)
431 if (getrusage(RUSAGE_SELF,&usage) == 0)
433 SetStringInfoLength(chaos,
sizeof(usage));
434 SetStringInfoDatum(chaos,(
unsigned char *) &usage);
438 seconds=time((time_t *) 0);
440#if defined(MAGICKCORE_HAVE_GETTIMEOFDAY)
445 if (gettimeofday(&timer,(
struct timezone *) NULL) == 0)
447 seconds=timer.tv_sec;
448 nanoseconds=1000*timer.tv_usec;
452#if defined(MAGICKCORE_HAVE_CLOCK_GETTIME) && defined(CLOCK_REALTIME_HR)
457 if (clock_gettime(CLOCK_REALTIME_HR,&timer) == 0)
459 seconds=timer.tv_sec;
460 nanoseconds=timer.tv_nsec;
464 SetStringInfoLength(chaos,
sizeof(seconds));
465 SetStringInfoDatum(chaos,(
unsigned char *) &seconds);
466 ConcatenateStringInfo(entropy,chaos);
467 SetStringInfoLength(chaos,
sizeof(nanoseconds));
468 SetStringInfoDatum(chaos,(
unsigned char *) &nanoseconds);
469 ConcatenateStringInfo(entropy,chaos);
471#if defined(MAGICKCORE_HAVE_CLOCK)
474#if defined(MAGICKCORE_HAVE_TIMES)
479 (void) times(&timer);
480 nanoseconds=timer.tms_utime+timer.tms_stime;
483 SetStringInfoLength(chaos,
sizeof(nanoseconds));
484 SetStringInfoDatum(chaos,(
unsigned char *) &nanoseconds);
485 ConcatenateStringInfo(entropy,chaos);
486#if defined(MAGICKCORE_WINDOWS_SUPPORT)
497 nt_seconds=NTElapsedTime()+NTElapsedTime();
498 SetStringInfoLength(chaos,
sizeof(nt_seconds));
499 SetStringInfoDatum(chaos,(
unsigned char *) &nt_seconds);
500 ConcatenateStringInfo(entropy,chaos);
501 if (QueryPerformanceCounter(&nt_nanoseconds) != 0)
503 SetStringInfoLength(chaos,
sizeof(nt_nanoseconds));
504 SetStringInfoDatum(chaos,(
unsigned char *) &nt_nanoseconds);
505 ConcatenateStringInfo(entropy,chaos);
510 SetStringInfoLength(chaos,MaxEntropyExtent);
511 (void) NTGatherRandomData(MaxEntropyExtent,GetStringInfoDatum(chaos));
512 ConcatenateStringInfo(entropy,chaos);
531 if (environ != (
char **) NULL)
539 for (i=0; environ[i] != (
char *) NULL; i++)
541 SetStringInfoLength(chaos,strlen(environ[i]));
542 SetStringInfoDatum(chaos,(
unsigned char *) environ[i]);
543 ConcatenateStringInfo(entropy,chaos);
546 filename=AcquireString(
"/dev/urandom");
547 device=StringToStringInfo(filename);
548 device=DestroyStringInfo(device);
549 file=open_utf8(filename,O_RDONLY | O_BINARY,0);
550 filename=DestroyString(filename);
553 SetStringInfoLength(chaos,MaxEntropyExtent);
554 count=ReadRandom(file,GetStringInfoDatum(chaos),MaxEntropyExtent);
555 (void) close_utf8(file);
556 SetStringInfoLength(chaos,(
size_t) count);
557 ConcatenateStringInfo(entropy,chaos);
559 if (gather_true_random != MagickFalse)
564 filename=AcquireString(
"/dev/random");
565 device=StringToStringInfo(filename);
566 device=DestroyStringInfo(device);
567 file=open_utf8(filename,O_RDONLY | O_BINARY,0);
568 filename=DestroyString(filename);
571 filename=AcquireString(
"/dev/srandom");
572 device=StringToStringInfo(filename);
573 device=DestroyStringInfo(device);
574 file=open_utf8(filename,O_RDONLY | O_BINARY,0);
578 SetStringInfoLength(chaos,MaxEntropyExtent);
579 count=ReadRandom(file,GetStringInfoDatum(chaos),MaxEntropyExtent);
580 (void) close_utf8(file);
581 SetStringInfoLength(chaos,(
size_t) count);
582 ConcatenateStringInfo(entropy,chaos);
587 chaos=DestroyStringInfo(chaos);
588 UnlockSemaphoreInfo(random_info->semaphore);
616MagickExport
double GetPseudoRandomValue(
617 RandomInfo *magick_restrict random_info)
619#define RandomROTL(x,k) (((x) << (k)) | ((x) >> (64-(k))))
622 alpha = (random_info->seed[1] << 17),
623 value = (random_info->seed[0]+random_info->seed[3]);
625 random_info->seed[2]^=random_info->seed[0];
626 random_info->seed[3]^=random_info->seed[1];
627 random_info->seed[1]^=random_info->seed[2];
628 random_info->seed[0]^=random_info->seed[3];
629 random_info->seed[2]^=alpha;
630 random_info->seed[3]=RandomROTL(random_info->seed[3],45);
631 return((
double) ((value >> 11)*random_info->normalize));
656MagickPrivate
double GetRandomInfoNormalize(
const RandomInfo *random_info)
658 assert(random_info != (
const RandomInfo *) NULL);
659 return(random_info->normalize);
684MagickPrivate
unsigned long *GetRandomInfoSeed(RandomInfo *random_info)
686 assert(random_info != (RandomInfo *) NULL);
687 return((
unsigned long *) random_info->seed);
714MagickExport StringInfo *GetRandomKey(RandomInfo *random_info,
720 assert(random_info != (RandomInfo *) NULL);
721 key=AcquireStringInfo(length);
722 SetRandomKey(random_info,length,GetStringInfoDatum(key));
747MagickExport
unsigned long GetRandomSecretKey(
const RandomInfo *random_info)
749 return(random_info->secret_key);
772MagickExport
double GetRandomValue(RandomInfo *random_info)
781 SetRandomKey(random_info,
sizeof(key),(
unsigned char *) &key);
782 }
while (key == range);
783 return((
double) key/range);
804MagickPrivate MagickBooleanType RandomComponentGenesis(
void)
807 random_semaphore=AcquireSemaphoreInfo();
829MagickPrivate
void RandomComponentTerminus(
void)
832 ActivateSemaphoreInfo(&random_semaphore);
833 RelinquishSemaphoreInfo(&random_semaphore);
864static inline void IncrementRandomNonce(StringInfo *nonce)
872 datum=GetStringInfoDatum(nonce);
873 for (i=(ssize_t) (GetStringInfoLength(nonce)-1); i != 0; i--)
879 ThrowFatalException(RandomFatalError,
"SequenceWrapError");
882MagickExport
void SetRandomKey(RandomInfo *random_info,
const size_t length,
897 assert(random_info != (RandomInfo *) NULL);
900#ifdef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION
902 (void) memset(key,0x42,length);
905 LockSemaphoreInfo(random_info->semaphore);
906 signature_info=random_info->signature_info;
907 datum=GetStringInfoDatum(random_info->reservoir);
909 for (p=key; (i != 0) && (random_info->i != 0); i--)
911 *p++=datum[random_info->i];
913 if (random_info->i == GetSignatureDigestsize(signature_info))
916 while (i >= GetSignatureDigestsize(signature_info))
918 InitializeSignature(signature_info);
919 UpdateSignature(signature_info,random_info->nonce);
920 FinalizeSignature(signature_info);
921 IncrementRandomNonce(random_info->nonce);
922 (void) memcpy(p,GetStringInfoDatum(GetSignatureDigest(
923 signature_info)),GetSignatureDigestsize(signature_info));
924 p+=(ptrdiff_t) GetSignatureDigestsize(signature_info);
925 i-=GetSignatureDigestsize(signature_info);
929 InitializeSignature(signature_info);
930 UpdateSignature(signature_info,random_info->nonce);
931 FinalizeSignature(signature_info);
932 IncrementRandomNonce(random_info->nonce);
933 SetStringInfo(random_info->reservoir,GetSignatureDigest(signature_info));
935 datum=GetStringInfoDatum(random_info->reservoir);
939 UnlockSemaphoreInfo(random_info->semaphore);
964MagickExport
void SetRandomSecretKey(
const unsigned long key)
993MagickExport
void SetRandomTrueRandom(
const MagickBooleanType true_random)
995 gather_true_random=true_random;