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/utility-private.h"
64 #if defined(MAGICKCORE_HAVE_GETENTROPY)
65 #include <sys/random.h>
70 #define PseudoRandomHash SHA256Hash
71 #define RandomEntropyLevel 9
72 #define RandomFilename "reservoir.xdm"
73 #define RandomFiletype "random"
74 #define RandomProtocolMajorVersion 1
75 #define RandomProtocolMinorVersion 0
118 #if defined(__APPLE__) && !defined(TARGET_OS_IPHONE)
119 #include <crt_externs.h>
120 #define environ (*_NSGetEnviron())
123 #if !defined(MAGICKCORE_WINDOWS_SUPPORT)
137 static MagickBooleanType
138 gather_true_random = MagickFalse;
164 MagickExport
RandomInfo *AcquireRandomInfo(
void)
177 random_info=(
RandomInfo *) AcquireCriticalMemory(
sizeof(*random_info));
178 (void) memset(random_info,0,
sizeof(*random_info));
179 random_info->signature_info=AcquireSignatureInfo();
180 random_info->nonce=AcquireStringInfo(2*GetSignatureDigestsize(
181 random_info->signature_info));
182 ResetStringInfo(random_info->nonce);
183 random_info->reservoir=AcquireStringInfo(GetSignatureDigestsize(
184 random_info->signature_info));
185 ResetStringInfo(random_info->reservoir);
186 random_info->normalize=(double) (1.0/(MagickULLConstant(~0) >> 11));
187 random_info->seed[0]=MagickULLConstant(0x76e15d3efefdcbbf);
188 random_info->seed[1]=MagickULLConstant(0xc5004e441c522fb3);
189 random_info->seed[2]=MagickULLConstant(0x77710069854ee241);
190 random_info->seed[3]=MagickULLConstant(0x39109bb02acbe635);
191 random_info->secret_key=secret_key;
192 random_info->protocol_major=RandomProtocolMajorVersion;
193 random_info->protocol_minor=RandomProtocolMinorVersion;
194 random_info->semaphore=AllocateSemaphoreInfo();
195 random_info->timestamp=(ssize_t) time(0);
196 random_info->signature=MagickCoreSignature;
200 nonce=GenerateEntropicChaos(random_info);
202 ThrowFatalException(ResourceLimitFatalError,
"MemoryAllocationFailed");
203 InitializeSignature(random_info->signature_info);
204 UpdateSignature(random_info->signature_info,nonce);
205 FinalizeSignature(random_info->signature_info);
206 SetStringInfoLength(nonce,(GetSignatureDigestsize(
207 random_info->signature_info)+1)/2);
208 SetStringInfo(nonce,GetSignatureDigest(random_info->signature_info));
209 SetStringInfo(random_info->nonce,nonce);
210 nonce=DestroyStringInfo(nonce);
214 entropy=GenerateEntropicChaos(random_info);
216 ThrowFatalException(ResourceLimitFatalError,
"MemoryAllocationFailed");
217 UpdateSignature(random_info->signature_info,entropy);
218 FinalizeSignature(random_info->signature_info);
219 SetStringInfo(random_info->reservoir,GetSignatureDigest(
220 random_info->signature_info));
221 entropy=DestroyStringInfo(entropy);
225 if (random_info->secret_key == ~0UL)
227 key=GetRandomKey(random_info,
sizeof(random_info->seed));
228 (void) memcpy(random_info->seed,GetStringInfoDatum(key),
229 sizeof(random_info->seed));
230 key=DestroyStringInfo(key);
237 signature_info=AcquireSignatureInfo();
238 key=AcquireStringInfo(
sizeof(random_info->secret_key));
239 SetStringInfoDatum(key,(
unsigned char *) &random_info->secret_key);
240 UpdateSignature(signature_info,key);
241 key=DestroyStringInfo(key);
242 FinalizeSignature(signature_info);
243 digest=GetSignatureDigest(signature_info);
244 (void) memcpy(random_info->seed,GetStringInfoDatum(digest),
245 MagickMin((
size_t) GetSignatureDigestsize(signature_info),
246 sizeof(random_info->seed)));
247 signature_info=DestroySignatureInfo(signature_info);
278 assert(random_info->signature == MagickCoreSignature);
279 if (IsEventLogging() != MagickFalse)
280 (void) LogMagickEvent(TraceEvent,GetMagickModule(),
"...");
281 LockSemaphoreInfo(random_info->semaphore);
282 if (random_info->reservoir != (
StringInfo *) NULL)
283 random_info->reservoir=DestroyStringInfo(random_info->reservoir);
284 if (random_info->nonce != (
StringInfo *) NULL)
285 random_info->nonce=DestroyStringInfo(random_info->nonce);
287 random_info->signature_info=DestroySignatureInfo(
288 random_info->signature_info);
289 (void) memset(random_info->seed,0,
sizeof(random_info->seed));
290 random_info->signature=(~MagickCoreSignature);
291 UnlockSemaphoreInfo(random_info->semaphore);
292 DestroySemaphoreInfo(&random_info->semaphore);
293 random_info=(
RandomInfo *) RelinquishMagickMemory(random_info);
321 #if !defined(MAGICKCORE_WINDOWS_SUPPORT)
322 static ssize_t ReadRandom(
int file,
unsigned char *source,
size_t length)
332 for (q=source; length != 0; length-=count)
334 count=(ssize_t) read(file,q,length);
351 #define MaxEntropyExtent 64
370 entropy=AcquireStringInfo(0);
371 LockSemaphoreInfo(random_info->semaphore);
372 #if defined(MAGICKCORE_HAVE_GETENTROPY)
377 SetStringInfoLength(entropy,MaxEntropyExtent);
378 status=getentropy(GetStringInfoDatum(entropy),MaxEntropyExtent);
381 UnlockSemaphoreInfo(random_info->semaphore);
386 chaos=AcquireStringInfo(
sizeof(
unsigned char *));
387 SetStringInfoDatum(chaos,(
unsigned char *) &entropy);
388 ConcatenateStringInfo(entropy,chaos);
389 SetStringInfoDatum(chaos,(
unsigned char *) entropy);
390 ConcatenateStringInfo(entropy,chaos);
391 pid=(ssize_t) getpid();
392 SetStringInfoLength(chaos,
sizeof(pid));
393 SetStringInfoDatum(chaos,(
unsigned char *) &pid);
394 ConcatenateStringInfo(entropy,chaos);
395 tid=GetMagickThreadId();
396 SetStringInfoLength(chaos,
sizeof(tid));
397 SetStringInfoDatum(chaos,(
unsigned char *) &tid);
398 ConcatenateStringInfo(entropy,chaos);
399 #if defined(MAGICKCORE_HAVE_SYSCONF) && defined(_SC_PHYS_PAGES)
404 pages=(ssize_t) sysconf(_SC_PHYS_PAGES);
405 SetStringInfoLength(chaos,
sizeof(pages));
406 SetStringInfoDatum(chaos,(
unsigned char *) &pages);
407 ConcatenateStringInfo(entropy,chaos);
410 #if defined(MAGICKCORE_HAVE_GETRUSAGE) && defined(RUSAGE_SELF)
415 if (getrusage(RUSAGE_SELF,&usage) == 0)
417 SetStringInfoLength(chaos,
sizeof(usage));
418 SetStringInfoDatum(chaos,(
unsigned char *) &usage);
422 seconds=time((time_t *) 0);
424 #if defined(MAGICKCORE_HAVE_GETTIMEOFDAY)
429 if (gettimeofday(&timer,(
struct timezone *) NULL) == 0)
431 seconds=(size_t) timer.tv_sec;
432 nanoseconds=(
size_t) (1000UL*timer.tv_usec);
436 #if defined(MAGICKCORE_HAVE_CLOCK_GETTIME) && defined(CLOCK_REALTIME_HR)
441 if (clock_gettime(CLOCK_REALTIME_HR,&timer) == 0)
443 seconds=timer.tv_sec;
444 nanoseconds=timer.tv_nsec;
448 SetStringInfoLength(chaos,
sizeof(seconds));
449 SetStringInfoDatum(chaos,(
unsigned char *) &seconds);
450 ConcatenateStringInfo(entropy,chaos);
451 SetStringInfoLength(chaos,
sizeof(nanoseconds));
452 SetStringInfoDatum(chaos,(
unsigned char *) &nanoseconds);
453 ConcatenateStringInfo(entropy,chaos);
455 #if defined(MAGICKCORE_HAVE_CLOCK)
458 #if defined(MAGICKCORE_HAVE_TIMES)
463 (void) times(&timer);
464 nanoseconds=timer.tms_utime+timer.tms_stime;
467 SetStringInfoLength(chaos,
sizeof(nanoseconds));
468 SetStringInfoDatum(chaos,(
unsigned char *) &nanoseconds);
469 ConcatenateStringInfo(entropy,chaos);
470 #if defined(MAGICKCORE_WINDOWS_SUPPORT)
481 seconds=NTElapsedTime()+NTUserTime();
482 SetStringInfoLength(chaos,
sizeof(seconds));
483 SetStringInfoDatum(chaos,(
unsigned char *) &seconds);
484 ConcatenateStringInfo(entropy,chaos);
485 if (QueryPerformanceCounter(&nanoseconds) != 0)
487 SetStringInfoLength(chaos,
sizeof(nanoseconds));
488 SetStringInfoDatum(chaos,(
unsigned char *) &nanoseconds);
489 ConcatenateStringInfo(entropy,chaos);
494 SetStringInfoLength(chaos,MaxEntropyExtent);
495 (void) NTGatherRandomData(MaxEntropyExtent,GetStringInfoDatum(chaos));
496 ConcatenateStringInfo(entropy,chaos);
515 if (environ != (
char **) NULL)
523 for (i=0; environ[i] != (
char *) NULL; i++)
525 SetStringInfoLength(chaos,strlen(environ[i]));
526 SetStringInfoDatum(chaos,(
unsigned char *) environ[i]);
527 ConcatenateStringInfo(entropy,chaos);
530 filename=AcquireString(
"/dev/urandom");
531 device=StringToStringInfo(filename);
532 device=DestroyStringInfo(device);
533 file=open_utf8(filename,O_RDONLY | O_BINARY,0);
534 filename=DestroyString(filename);
537 SetStringInfoLength(chaos,MaxEntropyExtent);
538 count=ReadRandom(file,GetStringInfoDatum(chaos),MaxEntropyExtent);
540 SetStringInfoLength(chaos,(
size_t) count);
541 ConcatenateStringInfo(entropy,chaos);
543 if (gather_true_random != MagickFalse)
548 filename=AcquireString(
"/dev/random");
549 device=StringToStringInfo(filename);
550 device=DestroyStringInfo(device);
551 file=open_utf8(filename,O_RDONLY | O_BINARY,0);
552 filename=DestroyString(filename);
555 filename=AcquireString(
"/dev/srandom");
556 device=StringToStringInfo(filename);
557 device=DestroyStringInfo(device);
558 file=open_utf8(filename,O_RDONLY | O_BINARY,0);
562 SetStringInfoLength(chaos,MaxEntropyExtent);
563 count=ReadRandom(file,GetStringInfoDatum(chaos),MaxEntropyExtent);
565 SetStringInfoLength(chaos,(
size_t) count);
566 ConcatenateStringInfo(entropy,chaos);
571 chaos=DestroyStringInfo(chaos);
572 UnlockSemaphoreInfo(random_info->semaphore);
600 MagickExport
double GetPseudoRandomValue(
603 #define RandomROTL(x,k) (((x) << (k)) | ((x) >> (64-(k))))
606 alpha = (random_info->seed[1] << 17),
607 value = (random_info->seed[0]+random_info->seed[3]);
609 random_info->seed[2]^=random_info->seed[0];
610 random_info->seed[3]^=random_info->seed[1];
611 random_info->seed[1]^=random_info->seed[2];
612 random_info->seed[0]^=random_info->seed[3];
613 random_info->seed[2]^=alpha;
614 random_info->seed[3]=RandomROTL(random_info->seed[3],45);
615 return((
double) ((value >> 11)*random_info->normalize));
640 MagickPrivate
double GetRandomInfoNormalize(
const RandomInfo *random_info)
642 assert(random_info != (
const RandomInfo *) NULL);
643 return(random_info->normalize);
668 MagickPrivate
unsigned long *GetRandomInfoSeed(
RandomInfo *random_info)
671 return((
unsigned long *) random_info->seed);
705 key=AcquireStringInfo(length);
706 SetRandomKey(random_info,length,GetStringInfoDatum(key));
731 MagickExport
unsigned long GetRandomSecretKey(
const RandomInfo *random_info)
733 return(random_info->secret_key);
756 MagickExport
double GetRandomValue(
RandomInfo *random_info)
765 SetRandomKey(random_info,
sizeof(key),(
unsigned char *) &key);
766 }
while (key == range);
767 return((
double) key/range);
788 MagickExport MagickBooleanType RandomComponentGenesis(
void)
791 random_semaphore=AllocateSemaphoreInfo();
813 MagickExport
void RandomComponentTerminus(
void)
816 ActivateSemaphoreInfo(&random_semaphore);
817 DestroySemaphoreInfo(&random_semaphore);
848 static inline void IncrementRandomNonce(
StringInfo *nonce)
856 datum=GetStringInfoDatum(nonce);
857 for (i=(ssize_t) (GetStringInfoLength(nonce)-1); i != 0; i--)
863 ThrowFatalException(RandomFatalError,
"SequenceWrapError");
866 MagickExport
void SetRandomKey(
RandomInfo *random_info,
const size_t length,
884 LockSemaphoreInfo(random_info->semaphore);
885 signature_info=random_info->signature_info;
886 datum=GetStringInfoDatum(random_info->reservoir);
888 for (p=key; (i != 0) && (random_info->i != 0); i--)
890 *p++=datum[random_info->i];
892 if (random_info->i == GetSignatureDigestsize(signature_info))
895 while (i >= GetSignatureDigestsize(signature_info))
897 InitializeSignature(signature_info);
898 UpdateSignature(signature_info,random_info->nonce);
899 FinalizeSignature(signature_info);
900 IncrementRandomNonce(random_info->nonce);
901 (void) memcpy(p,GetStringInfoDatum(GetSignatureDigest(
902 signature_info)),GetSignatureDigestsize(signature_info));
903 p+=GetSignatureDigestsize(signature_info);
904 i-=GetSignatureDigestsize(signature_info);
908 InitializeSignature(signature_info);
909 UpdateSignature(signature_info,random_info->nonce);
910 FinalizeSignature(signature_info);
911 IncrementRandomNonce(random_info->nonce);
912 SetStringInfo(random_info->reservoir,GetSignatureDigest(signature_info));
914 datum=GetStringInfoDatum(random_info->reservoir);
918 UnlockSemaphoreInfo(random_info->semaphore);
944 MagickExport
void SeedPseudoRandomGenerator(
const unsigned long seed)
946 SetRandomSecretKey(seed);
949 MagickExport
void SetRandomSecretKey(
const unsigned long key)
978 MagickExport
void SetRandomTrueRandom(
const MagickBooleanType true_random)
980 gather_true_random=true_random;