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/utility.h"
65 #include "MagickCore/utility-private.h"
66 #if defined(MAGICKCORE_HAVE_GETENTROPY)
67 #include <sys/random.h>
72 #define PseudoRandomHash SHA256Hash
73 #define RandomEntropyLevel 9
74 #define RandomFilename "reservoir.xdm"
75 #define RandomFiletype "random"
76 #define RandomProtocolMajorVersion 1
77 #define RandomProtocolMinorVersion 0
120 #if defined(__APPLE__) && !defined(TARGET_OS_IPHONE)
121 #include <crt_externs.h>
122 #define environ (*_NSGetEnviron())
125 #if !defined(MAGICKCORE_WINDOWS_SUPPORT)
139 static MagickBooleanType
140 gather_true_random = MagickFalse;
166 MagickExport
RandomInfo *AcquireRandomInfo(
void)
179 random_info=(
RandomInfo *) AcquireCriticalMemory(
sizeof(*random_info));
180 (void) memset(random_info,0,
sizeof(*random_info));
181 random_info->signature_info=AcquireSignatureInfo();
182 random_info->nonce=AcquireStringInfo(2*GetSignatureDigestsize(
183 random_info->signature_info));
184 ResetStringInfo(random_info->nonce);
185 random_info->reservoir=AcquireStringInfo(GetSignatureDigestsize(
186 random_info->signature_info));
187 ResetStringInfo(random_info->reservoir);
188 random_info->normalize=(double) (1.0/(MagickULLConstant(~0) >> 11));
189 random_info->seed[0]=MagickULLConstant(0x76e15d3efefdcbbf);
190 random_info->seed[1]=MagickULLConstant(0xc5004e441c522fb3);
191 random_info->seed[2]=MagickULLConstant(0x77710069854ee241);
192 random_info->seed[3]=MagickULLConstant(0x39109bb02acbe635);
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;
202 nonce=GenerateEntropicChaos(random_info);
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);
216 entropy=GenerateEntropicChaos(random_info);
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);
227 if (random_info->secret_key == ~0UL)
229 key=GetRandomKey(random_info,
sizeof(random_info->seed));
230 (void) memcpy(random_info->seed,GetStringInfoDatum(key),
231 sizeof(random_info->seed));
232 key=DestroyStringInfo(key);
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((
size_t) GetSignatureDigestsize(signature_info),
248 sizeof(random_info->seed)));
249 signature_info=DestroySignatureInfo(signature_info);
280 assert(random_info->signature == MagickCoreSignature);
281 if (IsEventLogging() != MagickFalse)
282 (void) LogMagickEvent(TraceEvent,GetMagickModule(),
"...");
283 LockSemaphoreInfo(random_info->semaphore);
284 if (random_info->reservoir != (
StringInfo *) NULL)
285 random_info->reservoir=DestroyStringInfo(random_info->reservoir);
286 if (random_info->nonce != (
StringInfo *) NULL)
287 random_info->nonce=DestroyStringInfo(random_info->nonce);
289 random_info->signature_info=DestroySignatureInfo(
290 random_info->signature_info);
291 (void) memset(random_info->seed,0,
sizeof(random_info->seed));
292 random_info->signature=(~MagickCoreSignature);
293 UnlockSemaphoreInfo(random_info->semaphore);
294 RelinquishSemaphoreInfo(&random_info->semaphore);
295 random_info=(
RandomInfo *) RelinquishMagickMemory(random_info);
323 #if !defined(MAGICKCORE_WINDOWS_SUPPORT)
324 static ssize_t ReadRandom(
int file,
unsigned char *source,
size_t length)
334 for (q=source; length != 0; length-=count)
336 count=(ssize_t) read(file,q,length);
353 #define MaxEntropyExtent 64
372 entropy=AcquireStringInfo(0);
373 LockSemaphoreInfo(random_info->semaphore);
374 #if defined(MAGICKCORE_HAVE_GETENTROPY)
379 SetStringInfoLength(entropy,MaxEntropyExtent);
380 status=getentropy(GetStringInfoDatum(entropy),MaxEntropyExtent);
383 UnlockSemaphoreInfo(random_info->semaphore);
388 chaos=AcquireStringInfo(
sizeof(
unsigned char *));
389 SetStringInfoDatum(chaos,(
unsigned char *) &entropy);
390 ConcatenateStringInfo(entropy,chaos);
391 SetStringInfoDatum(chaos,(
unsigned char *) entropy);
392 ConcatenateStringInfo(entropy,chaos);
393 pid=(ssize_t) getpid();
394 SetStringInfoLength(chaos,
sizeof(pid));
395 SetStringInfoDatum(chaos,(
unsigned char *) &pid);
396 ConcatenateStringInfo(entropy,chaos);
397 tid=GetMagickThreadId();
398 SetStringInfoLength(chaos,
sizeof(tid));
399 SetStringInfoDatum(chaos,(
unsigned char *) &tid);
400 ConcatenateStringInfo(entropy,chaos);
401 #if defined(MAGICKCORE_HAVE_SYSCONF) && defined(_SC_PHYS_PAGES)
406 pages=(ssize_t) sysconf(_SC_PHYS_PAGES);
407 SetStringInfoLength(chaos,
sizeof(pages));
408 SetStringInfoDatum(chaos,(
unsigned char *) &pages);
409 ConcatenateStringInfo(entropy,chaos);
412 #if defined(MAGICKCORE_HAVE_GETRUSAGE) && defined(RUSAGE_SELF)
417 if (getrusage(RUSAGE_SELF,&usage) == 0)
419 SetStringInfoLength(chaos,
sizeof(usage));
420 SetStringInfoDatum(chaos,(
unsigned char *) &usage);
424 seconds=time((time_t *) 0);
426 #if defined(MAGICKCORE_HAVE_GETTIMEOFDAY)
431 if (gettimeofday(&timer,(
struct timezone *) NULL) == 0)
433 seconds=(size_t) timer.tv_sec;
434 nanoseconds=(
size_t) (1000UL*timer.tv_usec);
438 #if defined(MAGICKCORE_HAVE_CLOCK_GETTIME) && defined(CLOCK_REALTIME_HR)
443 if (clock_gettime(CLOCK_REALTIME_HR,&timer) == 0)
445 seconds=timer.tv_sec;
446 nanoseconds=timer.tv_nsec;
450 SetStringInfoLength(chaos,
sizeof(seconds));
451 SetStringInfoDatum(chaos,(
unsigned char *) &seconds);
452 ConcatenateStringInfo(entropy,chaos);
453 SetStringInfoLength(chaos,
sizeof(nanoseconds));
454 SetStringInfoDatum(chaos,(
unsigned char *) &nanoseconds);
455 ConcatenateStringInfo(entropy,chaos);
457 #if defined(MAGICKCORE_HAVE_CLOCK)
460 #if defined(MAGICKCORE_HAVE_TIMES)
465 (void) times(&timer);
466 nanoseconds=timer.tms_utime+timer.tms_stime;
469 SetStringInfoLength(chaos,
sizeof(nanoseconds));
470 SetStringInfoDatum(chaos,(
unsigned char *) &nanoseconds);
471 ConcatenateStringInfo(entropy,chaos);
472 #if defined(MAGICKCORE_WINDOWS_SUPPORT)
483 nt_seconds=NTElapsedTime()+NTUserTime();
484 SetStringInfoLength(chaos,
sizeof(nt_seconds));
485 SetStringInfoDatum(chaos,(
unsigned char *) &nt_seconds);
486 ConcatenateStringInfo(entropy,chaos);
487 if (QueryPerformanceCounter(&nt_nanoseconds) != 0)
489 SetStringInfoLength(chaos,
sizeof(nt_nanoseconds));
490 SetStringInfoDatum(chaos,(
unsigned char *) &nt_nanoseconds);
491 ConcatenateStringInfo(entropy,chaos);
496 SetStringInfoLength(chaos,MaxEntropyExtent);
497 (void) NTGatherRandomData(MaxEntropyExtent,GetStringInfoDatum(chaos));
498 ConcatenateStringInfo(entropy,chaos);
517 if (environ != (
char **) NULL)
525 for (i=0; environ[i] != (
char *) NULL; i++)
527 SetStringInfoLength(chaos,strlen(environ[i]));
528 SetStringInfoDatum(chaos,(
unsigned char *) environ[i]);
529 ConcatenateStringInfo(entropy,chaos);
532 filename=AcquireString(
"/dev/urandom");
533 device=StringToStringInfo(filename);
534 device=DestroyStringInfo(device);
535 file=open_utf8(filename,O_RDONLY | O_BINARY,0);
536 filename=DestroyString(filename);
539 SetStringInfoLength(chaos,MaxEntropyExtent);
540 count=ReadRandom(file,GetStringInfoDatum(chaos),MaxEntropyExtent);
542 SetStringInfoLength(chaos,(
size_t) count);
543 ConcatenateStringInfo(entropy,chaos);
545 if (gather_true_random != MagickFalse)
550 filename=AcquireString(
"/dev/random");
551 device=StringToStringInfo(filename);
552 device=DestroyStringInfo(device);
553 file=open_utf8(filename,O_RDONLY | O_BINARY,0);
554 filename=DestroyString(filename);
557 filename=AcquireString(
"/dev/srandom");
558 device=StringToStringInfo(filename);
559 device=DestroyStringInfo(device);
560 file=open_utf8(filename,O_RDONLY | O_BINARY,0);
564 SetStringInfoLength(chaos,MaxEntropyExtent);
565 count=ReadRandom(file,GetStringInfoDatum(chaos),MaxEntropyExtent);
567 SetStringInfoLength(chaos,(
size_t) count);
568 ConcatenateStringInfo(entropy,chaos);
573 chaos=DestroyStringInfo(chaos);
574 UnlockSemaphoreInfo(random_info->semaphore);
602 MagickExport
double GetPseudoRandomValue(
605 #define RandomROTL(x,k) (((x) << (k)) | ((x) >> (64-(k))))
608 alpha = (random_info->seed[1] << 17),
609 value = (random_info->seed[0]+random_info->seed[3]);
611 random_info->seed[2]^=random_info->seed[0];
612 random_info->seed[3]^=random_info->seed[1];
613 random_info->seed[1]^=random_info->seed[2];
614 random_info->seed[0]^=random_info->seed[3];
615 random_info->seed[2]^=alpha;
616 random_info->seed[3]=RandomROTL(random_info->seed[3],45);
617 return((
double) ((value >> 11)*random_info->normalize));
642 MagickPrivate
double GetRandomInfoNormalize(
const RandomInfo *random_info)
644 assert(random_info != (
const RandomInfo *) NULL);
645 return(random_info->normalize);
670 MagickPrivate
unsigned long *GetRandomInfoSeed(
RandomInfo *random_info)
673 return((
unsigned long *) random_info->seed);
707 key=AcquireStringInfo(length);
708 SetRandomKey(random_info,length,GetStringInfoDatum(key));
733 MagickExport
unsigned long GetRandomSecretKey(
const RandomInfo *random_info)
735 return(random_info->secret_key);
758 MagickExport
double GetRandomValue(
RandomInfo *random_info)
767 SetRandomKey(random_info,
sizeof(key),(
unsigned char *) &key);
768 }
while (key == range);
769 return((
double) key/range);
790 MagickPrivate MagickBooleanType RandomComponentGenesis(
void)
793 random_semaphore=AcquireSemaphoreInfo();
815 MagickPrivate
void RandomComponentTerminus(
void)
818 ActivateSemaphoreInfo(&random_semaphore);
819 RelinquishSemaphoreInfo(&random_semaphore);
850 static inline void IncrementRandomNonce(
StringInfo *nonce)
858 datum=GetStringInfoDatum(nonce);
859 for (i=(ssize_t) (GetStringInfoLength(nonce)-1); i != 0; i--)
865 ThrowFatalException(RandomFatalError,
"SequenceWrapError");
868 MagickExport
void SetRandomKey(
RandomInfo *random_info,
const size_t length,
886 LockSemaphoreInfo(random_info->semaphore);
887 signature_info=random_info->signature_info;
888 datum=GetStringInfoDatum(random_info->reservoir);
890 for (p=key; (i != 0) && (random_info->i != 0); i--)
892 *p++=datum[random_info->i];
894 if (random_info->i == GetSignatureDigestsize(signature_info))
897 while (i >= GetSignatureDigestsize(signature_info))
899 InitializeSignature(signature_info);
900 UpdateSignature(signature_info,random_info->nonce);
901 FinalizeSignature(signature_info);
902 IncrementRandomNonce(random_info->nonce);
903 (void) memcpy(p,GetStringInfoDatum(GetSignatureDigest(
904 signature_info)),GetSignatureDigestsize(signature_info));
905 p+=GetSignatureDigestsize(signature_info);
906 i-=GetSignatureDigestsize(signature_info);
910 InitializeSignature(signature_info);
911 UpdateSignature(signature_info,random_info->nonce);
912 FinalizeSignature(signature_info);
913 IncrementRandomNonce(random_info->nonce);
914 SetStringInfo(random_info->reservoir,GetSignatureDigest(signature_info));
916 datum=GetStringInfoDatum(random_info->reservoir);
920 UnlockSemaphoreInfo(random_info->semaphore);
945 MagickExport
void SetRandomSecretKey(
const unsigned long key)
974 MagickExport
void SetRandomTrueRandom(
const MagickBooleanType true_random)
976 gather_true_random=true_random;