54
54
#include "magick/semaphore.h"
55
55
#include "magick/random_.h"
56
56
#include "magick/resource_.h"
57
#include "magick/signature.h"
57
#include "magick/signature-private.h"
58
58
#include "magick/string_.h"
59
59
#include "magick/utility.h"
63
#define PseudoRandomHash SHA256Hash
64
#define RandomEntropyLevel 9
65
#define RandomFilename "reservoir.xdm"
66
#define RandomFiletype "random"
67
#define RandomProtocolMajorVersion 1
68
#define RandomProtocolMinorVersion 0
62
71
Typedef declarations.
64
typedef struct _RandomInfo
100
External declarations.
102
#if defined(__APPLE__)
103
#include <crt_externs.h>
104
#define environ (*_NSGetEnviron())
74
111
Global declarations.
77
random_info = { ~0U, ~0U, ~0U, ~0U };
79
113
static SemaphoreInfo
80
114
*random_semaphore = (SemaphoreInfo *) NULL;
83
*reservoir = (SignatureInfo *) NULL;
85
116
static unsigned long
86
*roulette = (unsigned long *) NULL;
117
random_seed[4] = { ~0UL, 0x50a7f451UL, 0x5365417eUL, 0xc3a4171aUL };
119
static MagickBooleanType
120
gather_true_random = MagickFalse;
89
123
Forward declarations.
92
InitializeRandomReservoir(void);
126
*GenerateEntropicChaos(RandomInfo *);
129
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
133
% A c q u i r e R a n d o m I n f o %
137
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
139
% AcquireRandomInfo() allocates the RandomInfo structure.
141
% The format of the AcquireRandomInfo method is:
143
% RandomInfo *AcquireRandomInfo(void)
146
MagickExport RandomInfo *AcquireRandomInfo(void)
154
random_info=(RandomInfo *) AcquireMagickMemory(sizeof(*random_info));
155
if (random_info == (RandomInfo *) NULL)
156
ThrowFatalException(ResourceLimitFatalError,"MemoryAllocationFailed");
157
(void) ResetMagickMemory(random_info,0,sizeof(*random_info));
158
random_info->signature_info=AcquireSignatureInfo();
159
random_info->nonce=AcquireStringInfo(GetSignatureDigestsize(
160
random_info->signature_info));
161
ResetStringInfo(random_info->nonce);
162
random_info->reservoir=AcquireStringInfo(GetSignatureDigestsize(
163
random_info->signature_info));
164
ResetStringInfo(random_info->reservoir);
165
random_info->semaphore=AllocateSemaphoreInfo();
166
random_info->protocol_major=RandomProtocolMajorVersion;
167
random_info->protocol_minor=RandomProtocolMinorVersion;
168
random_info->timestamp=(long) time(0);
169
random_info->signature=MagickSignature;
171
Seed random reservoir with entropic data.
173
entropy=GenerateEntropicChaos(random_info);
174
if (entropy == (StringInfo *) NULL)
175
ThrowFatalException(ResourceLimitFatalError,"MemoryAllocationFailed");
176
if (GetStringInfoLength(entropy) > GetStringInfoLength(random_info->nonce))
181
nonce=SplitStringInfo(entropy,GetStringInfoLength(random_info->nonce)/2);
182
if (nonce != (StringInfo *) NULL)
185
Use some of the entropy to set a random nonce.
187
SetStringInfo(random_info->nonce,nonce);
188
nonce=DestroyStringInfo(nonce);
191
UpdateSignature(random_info->signature_info,entropy);
192
FinalizeSignature(random_info->signature_info);
193
SetStringInfo(random_info->reservoir,GetSignatureDigest(
194
random_info->signature_info));
195
entropy=DestroyStringInfo(entropy);
200
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
204
+ D e s t r o y R a n d o m I n f o %
208
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
210
% DestroyRandomInfo() deallocates memory associated with the random
213
% The format of the DestroyRandomInfo method is:
215
% RandomInfo *DestroyRandomInfo(RandomInfo *random_info)
217
% A description of each parameter follows:
219
% o random_info: the random info.
222
MagickExport RandomInfo *DestroyRandomInfo(RandomInfo *random_info)
224
(void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
225
assert(random_info != (RandomInfo *) NULL);
226
assert(random_info->signature == MagickSignature);
227
(void) LockSemaphoreInfo(random_info->semaphore);
228
if (random_info->reservoir != (StringInfo *) NULL)
229
random_info->reservoir=DestroyStringInfo(random_info->reservoir);
230
if (random_info->nonce != (StringInfo *) NULL)
231
random_info->nonce=DestroyStringInfo(random_info->nonce);
232
if (random_info->signature_info != (SignatureInfo *) NULL)
233
random_info->signature_info=DestroySignatureInfo(
234
random_info->signature_info);
235
random_info->signature=(~MagickSignature);
236
(void) UnlockSemaphoreInfo(random_info->semaphore);
237
DestroySemaphoreInfo(&random_info->semaphore);
238
random_info=(RandomInfo *) RelinquishMagickMemory(random_info);
95
243
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
113
261
MagickExport void DestroyRandomReservoir(void)
115
263
AcquireSemaphoreInfo(&random_semaphore);
116
if (reservoir != (SignatureInfo *) NULL)
118
(void) ResetMagickMemory(reservoir,0,sizeof(*reservoir));
119
reservoir=(SignatureInfo *) RelinquishMagickMemory(reservoir);
121
if (roulette != (unsigned long *) NULL)
123
(void) ResetMagickMemory(roulette,0,sizeof(*roulette));
124
roulette=(unsigned long *) RelinquishMagickMemory(roulette);
126
(void) ResetMagickMemory(&random_info,0xff,sizeof(random_info));
127
RelinquishSemaphoreInfo(random_semaphore);
128
random_semaphore=DestroySemaphoreInfo(random_semaphore);
132
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
136
% D i s t i l l R a n d o m E v e n t %
140
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
142
% DistillRandomEvent() distills randomness from an event and stores it int
143
% the reservoir. This method should be called before GetRandomKey() and it
144
% should be called a number of times using different random events (e.g.
145
% thread completion time, fine grained time-of-day clock in a tight loop,
146
% keystroke timing, etc.) to build up sufficient randomness in the reservoir.
148
% The format of the DistillRandomEvent method is:
150
% DistillRandomEvent(const unsigned char *event,const size_t length)
152
% A description of each parameter follows:
154
% o event: A random event.
156
% o length: The length of the event.
159
MagickExport void DistillRandomEvent(const unsigned char *event,
166
Distill a random event.
168
(void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
169
assert(event != (const unsigned char *) NULL);
170
if ((reservoir == (SignatureInfo *) NULL) ||
171
(roulette == (unsigned long *) NULL))
173
AcquireSemaphoreInfo(&random_semaphore);
174
if (reservoir == (SignatureInfo *) NULL)
175
reservoir=(SignatureInfo *) AcquireMagickMemory(sizeof(*reservoir));
176
if (roulette == (unsigned long *) NULL)
177
roulette=(unsigned long *) AcquireMagickMemory(sizeof(*roulette));
178
RelinquishSemaphoreInfo(random_semaphore);
179
if ((reservoir == (SignatureInfo *) NULL) ||
180
(roulette == (unsigned long *) NULL))
181
ThrowFatalException(ResourceLimitFatalError,"MemoryAllocationFailed");
182
(void) ResetMagickMemory(reservoir,0,sizeof(*reservoir));
183
(void) ResetMagickMemory(roulette,0,sizeof(*roulette));
184
(void) ResetMagickMemory(&random_info,0xff,sizeof(random_info));
186
AcquireSemaphoreInfo(&random_semaphore);
187
GetSignatureInfo(&digest_info);
188
UpdateSignature(&digest_info,(const unsigned char *) reservoir->digest,
189
sizeof(reservoir->digest));
190
UpdateSignature(&digest_info,event,length);
191
FinalizeSignature(&digest_info);
192
(void) CopyMagickMemory(reservoir->digest,digest_info.digest,
193
sizeof(reservoir->digest));
194
RelinquishSemaphoreInfo(random_semaphore);
198
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
202
% G e t R a n d o m K e y %
206
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
208
% GetRandomKey() gets a random key from the reservoir.
210
% The format of the GetRandomKey method is:
212
% GetRandomKey(unsigned char *key,const size_t length)
214
% A description of each parameter follows:
218
% o length: The key length.
221
MagickExport void GetRandomKey(unsigned char *key,const size_t length)
229
assert(key != (unsigned char *) NULL);
230
if ((roulette == (unsigned long *) NULL) ||
231
(reservoir == (SignatureInfo *) NULL))
232
InitializeRandomReservoir();
233
AcquireSemaphoreInfo(&random_semaphore);
234
for (n=(long) length; n > 0; n-=sizeof(reservoir->digest))
236
GetSignatureInfo(&digest_info);
237
UpdateSignature(&digest_info,(const unsigned char *) reservoir->digest,
238
sizeof(reservoir->digest));
239
UpdateSignature(&digest_info,(const unsigned char *) roulette,
241
FinalizeSignature(&digest_info);
243
(void) CopyMagickMemory(key,digest_info.digest,(size_t) (n < (long)
244
sizeof(reservoir->digest) ? n : (long) sizeof(reservoir->digest)));
245
key+=sizeof(reservoir->digest);
247
RelinquishSemaphoreInfo(random_semaphore);
251
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
255
% G e t R a n d o m V a l u e %
259
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
261
% GetRandomValue() return a non-negative double-precision floating-point
262
% value uniformly distributed over the interval [0.0, 1.0) with a 2 to the
265
% The format of the GetRandomValue method is:
267
% double GetRandomValue(void)
270
MagickExport double GetRandomValue(void)
276
if ((roulette == (unsigned long *) NULL) ||
277
(reservoir == (SignatureInfo *) NULL))
278
InitializeRandomReservoir();
279
while ((random_info.w == ~0U) || (random_info.x == (~0U)) ||
280
(random_info.y == (~0U)) || (random_info.z == (~0U)))
282
GetRandomKey((unsigned char *) &random_info.w,sizeof(random_info.w));
283
GetRandomKey((unsigned char *) &random_info.x,sizeof(random_info.x));
284
GetRandomKey((unsigned char *) &random_info.y,sizeof(random_info.y));
285
GetRandomKey((unsigned char *) &random_info.z,sizeof(random_info.z));
290
t=(random_info.x ^ (random_info.x << 11));
291
random_info.x=random_info.y;
292
random_info.y=random_info.z;
293
random_info.z=random_info.w;
294
random_info.w=(random_info.w ^ (random_info.w >> 19)) ^ (t ^ (t >> 8));
296
while (random_info.w == range);
297
return((double) random_info.w/range);
301
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
305
+ I n i t i a l i z e R a n d o m R e s e r v i o r %
309
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
311
% InitializeRandomReservoir() initializes the random reservoir with entropy.
313
% The format of the InitializeRandomReservoir method is:
315
% InitializeRandomReservoir(void)
318
static void InitializeRandomReservoir(void)
321
filename[MaxTextExtent];
264
(void) UnlockSemaphoreInfo(random_semaphore);
265
DestroySemaphoreInfo(&random_semaphore);
269
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
273
+ G e n e r a t e E n t r o p i c C h a o s %
277
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
279
% GenerateEntropicChaos() generate entropic chaos used to initialize the
282
% The format of the GenerateEntropicChaos method is:
284
% StringInfo *GenerateEntropicChaos(RandomInfo *random_info)
286
% A description of each parameter follows:
288
% o random_info: the random info.
292
static ssize_t ReadRandom(int file,unsigned char *source,size_t length)
294
register unsigned char
302
for (q=source; length != 0; length-=count)
304
count=(ssize_t) read(file,q,length);
318
static StringInfo *GenerateEntropicChaos(RandomInfo *random_info)
320
#define MaxEntropyExtent 64
334
random[MaxTextExtent];
337
334
Initialize random reservoir.
336
entropy=AcquireStringInfo(0);
337
(void) LockSemaphoreInfo(random_info->semaphore);
338
chaos=AcquireStringInfo(sizeof(unsigned char *));
339
SetStringInfoDatum(chaos,(unsigned char *) &entropy);
340
ConcatenateStringInfo(entropy,chaos);
341
SetStringInfoDatum(chaos,(unsigned char *) entropy);
342
ConcatenateStringInfo(entropy,chaos);
344
SetStringInfoLength(chaos,sizeof(pid));
345
SetStringInfoDatum(chaos,(unsigned char *) &pid);
346
ConcatenateStringInfo(entropy,chaos);
339
347
seconds=time((time_t *) 0);
341
349
#if defined(MAGICKCORE_HAVE_GETTIMEOFDAY)
373
388
(void) times(&timer);
374
389
nanoseconds=timer.tms_utime+timer.tms_stime;
392
SetStringInfoLength(chaos,sizeof(nanoseconds));
393
SetStringInfoDatum(chaos,(unsigned char *) &nanoseconds);
394
ConcatenateStringInfo(entropy,chaos);
395
#if defined(MAGICKCORE_HAVE_MKSTEMP)
403
filename=ConstantString("magickXXXXXX");
404
file=mkstemp(filename);
407
(void) remove(filename);
408
SetStringInfoLength(chaos,strlen(filename));
409
SetStringInfoDatum(chaos,(unsigned char *) filename);
410
ConcatenateStringInfo(entropy,chaos);
411
filename=DestroyString(filename);
377
414
#if defined(__WINDOWS__)
378
nanoseconds=(time_t) (NTElapsedTime()+NTUserTime());
426
Not crytographically strong but better than nothing.
428
seconds=NTElapsedTime()+NTUserTime();
429
SetStringInfoLength(chaos,sizeof(seconds));
430
SetStringInfoDatum(chaos,(unsigned char *) &seconds);
431
ConcatenateStringInfo(entropy,chaos);
432
if (QueryPerformanceCounter(&nanoseconds) != 0)
434
SetStringInfoLength(chaos,sizeof(nanoseconds));
435
SetStringInfoDatum(chaos,(unsigned char *) &nanoseconds);
436
ConcatenateStringInfo(entropy,chaos);
439
Our best hope for true entropy.
441
SetStringInfoLength(chaos,MaxEntropyExtent);
442
status=NTGatherRandomData(MaxEntropyExtent,GetStringInfoDatum(chaos));
443
ConcatenateStringInfo(entropy,chaos);
383
DistillRandomEvent((const unsigned char *) &nanoseconds,sizeof(nanoseconds));
385
DistillRandomEvent((const unsigned char *) &pid,sizeof(pid));
386
DistillRandomEvent((const unsigned char *) &roulette,sizeof(roulette));
387
(void) AcquireUniqueFilename(filename);
388
DistillRandomEvent((const unsigned char *) filename,strlen(filename));
389
(void) RelinquishUniqueFileResource(filename);
390
file=open("/dev/urandom",O_RDONLY | O_BINARY);
396
count=read(file,random,MaxTextExtent);
398
DistillRandomEvent(random,(size_t) count);
403
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
407
% S e e d R a n d o m E v e n t %
411
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
413
% SeedRandomReservoir() sets its argument as the seed for a new sequence of
414
% pseudo-random numbers to be returned by GetRandomValue().
416
% The format of the SeedRandomReservoir method is:
418
% SeedRandomReservoir(const unsigned long seed)
420
% A description of each parameter follows:
425
MagickExport void SeedRandomReservoir(const unsigned long seed)
460
Not crytographically strong but better than nothing.
462
if (environ != (char **) NULL)
468
Squeeze some entropy from the sometimes unpredicatble environment.
470
for (i=0; environ[i] != (char *) NULL; i++)
472
SetStringInfoLength(chaos,strlen(environ[i]));
473
SetStringInfoDatum(chaos,(unsigned char *) environ[i]);
474
ConcatenateStringInfo(entropy,chaos);
477
filename=AcquireString("/dev/urandom");
478
device=StringToStringInfo(filename);
479
device=DestroyStringInfo(device);
480
file=open(filename,O_RDONLY | O_BINARY);
481
filename=DestroyString(filename);
484
SetStringInfoLength(chaos,MaxEntropyExtent);
485
count=ReadRandom(file,GetStringInfoDatum(chaos),MaxEntropyExtent);
487
SetStringInfoLength(chaos,(size_t) count);
488
ConcatenateStringInfo(entropy,chaos);
490
if (gather_true_random != MagickFalse)
493
Our best hope for true entropy.
495
filename=AcquireString("/dev/random");
496
device=StringToStringInfo(filename);
497
device=DestroyStringInfo(device);
498
file=open(filename,O_RDONLY | O_BINARY);
499
filename=DestroyString(filename);
502
filename=AcquireString("/dev/srandom");
503
device=StringToStringInfo(filename);
504
device=DestroyStringInfo(device);
505
file=open(filename,O_RDONLY | O_BINARY);
509
SetStringInfoLength(chaos,MaxEntropyExtent);
510
count=ReadRandom(file,GetStringInfoDatum(chaos),MaxEntropyExtent);
512
SetStringInfoLength(chaos,(size_t) count);
513
ConcatenateStringInfo(entropy,chaos);
518
chaos=DestroyStringInfo(chaos);
519
(void) UnlockSemaphoreInfo(random_info->semaphore);
524
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
528
% G e t P s e u d o R a n d o m V a l u e %
532
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
534
% GetPseudoRandomValue() return a non-negative double-precision floating-point
535
% value uniformly distributed over the interval [0.0, 1.0) with a 2 to the
538
% The format of the GetPseudoRandomValue method is:
540
% double GetPseudoRandomValue(void)
543
MagickExport double GetPseudoRandomValue(void)
552
AcquireSemaphoreInfo(&random_semaphore);
553
if (random_seed[0] == ~0UL)
554
SeedPseudoRandomGenerator(~0UL);
558
alpha=(unsigned long) (random_seed[1] ^ (random_seed[1] << 11));
559
random_seed[1]=random_seed[2];
560
random_seed[2]=random_seed[3];
561
random_seed[3]=random_seed[0];
562
random_seed[0]=(random_seed[0] ^ (random_seed[0] >> 19)) ^ (alpha ^
564
} while (random_seed[0] == range);
565
random=(double) random_seed[0]/range;
566
(void) UnlockSemaphoreInfo(random_semaphore);
571
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
575
% G e t R a n d o m K e y %
579
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
581
% GetRandomKey() gets a random key from the reservoir.
583
% The format of the GetRandomKey method is:
585
% StringInfo *GetRandomKey(RandomInfo *random_info,const size_t length)
587
% A description of each parameter follows:
589
% o random_info: the random info.
591
% o length: the key length.
594
MagickExport StringInfo *GetRandomKey(RandomInfo *random_info,
600
assert(random_info != (RandomInfo *) NULL);
601
key=AcquireStringInfo(length);
602
SetRandomKey(random_info,length,GetStringInfoDatum(key));
607
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
611
% G e t R a n d o m V a l u e %
615
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
617
% GetRandomValue() return a non-negative double-precision floating-point
618
% value uniformly distributed over the interval [0.0, 1.0) with a 2 to the
619
% 128th-1 period (not cryptographically strong).
621
% The format of the GetRandomValue method is:
623
% double GetRandomValue(void)
626
MagickExport double GetRandomValue(RandomInfo *random_info)
635
SetRandomKey(random_info,sizeof(key),(unsigned char *) &key);
636
} while (key == range);
637
return((double) key/range);
641
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
645
% S e e d P s e u d o R a n d o m G e n e r a t o r %
649
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
651
% SeedPseudoRandomGenerator() initializes the pseudo-random number generator
652
% with a random seed.
654
% The format of the SeedPseudoRandomGenerator method is:
656
% void SeedPseudoRandomGenerator(const unsigned long seed)
658
% A description of each parameter follows:
664
static inline size_t MagickMin(const size_t x,const size_t y)
671
MagickExport void SeedPseudoRandomGenerator(const unsigned long seed)
427
682
(void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
428
DestroyRandomReservoir();
429
DistillRandomEvent((const unsigned char *) &seed,sizeof(seed));
693
Initialize pseudo random number generator with random seed.
695
random_info=AcquireRandomInfo();
696
key=GetRandomKey(random_info,sizeof(random_seed));
697
(void) CopyMagickMemory(random_seed,GetStringInfoDatum(key),
698
GetStringInfoLength(key));
699
key=DestroyStringInfo(key);
700
random_info=DestroyRandomInfo(random_info);
704
Initialize pseudo random number generator with a user-supplied seed.
706
signature_info=AcquireSignatureInfo();
707
key=AcquireStringInfo(sizeof(seed));
708
SetStringInfoDatum(key,(unsigned char *) &seed);
709
UpdateSignature(signature_info,key);
710
key=DestroyStringInfo(key);
711
FinalizeSignature(signature_info);
712
digest=GetSignatureDigest(signature_info);
713
(void) CopyMagickMemory(random_seed,GetStringInfoDatum(digest),
714
MagickMin(GetSignatureDigestsize(signature_info),sizeof(random_seed)));
715
signature_info=DestroySignatureInfo(signature_info);
719
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
723
% S e t R a n d o m K e y %
727
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
729
% SetRandomKey() sets a random key from the reservoir.
731
% The format of the SetRandomKey method is:
733
% void SetRandomKey(RandomInfo *random_info,const size_t length,
734
% unsigned char *key)
736
% A description of each parameter follows:
738
% o random_info: the random info.
740
% o length: the key length.
746
static inline void IncrementRandomNonce(StringInfo *nonce)
754
datum=GetStringInfoDatum(nonce);
755
for (i=(long) (GetStringInfoLength(nonce)-1); i != 0; i--)
761
ThrowFatalException(RandomFatalError,"SequenceWrapError");
764
MagickExport void SetRandomKey(RandomInfo *random_info,const size_t length,
770
register unsigned char
779
assert(random_info != (RandomInfo *) NULL);
782
(void) LockSemaphoreInfo(random_info->semaphore);
783
signature_info=random_info->signature_info;
784
datum=GetStringInfoDatum(random_info->reservoir);
786
for (p=key; (i != 0) && (random_info->i != 0); i--)
788
*p++=datum[random_info->i];
790
if (random_info->i == GetSignatureDigestsize(signature_info))
793
while (i >= GetSignatureDigestsize(signature_info))
795
InitializeSignature(signature_info);
796
UpdateSignature(signature_info,random_info->nonce);
797
FinalizeSignature(signature_info);
798
IncrementRandomNonce(random_info->nonce);
799
(void) CopyMagickMemory(p,GetStringInfoDatum(GetSignatureDigest(
800
signature_info)),GetSignatureDigestsize(signature_info));
801
p+=GetSignatureDigestsize(signature_info);
802
i-=GetSignatureDigestsize(signature_info);
806
InitializeSignature(signature_info);
807
UpdateSignature(signature_info,random_info->nonce);
808
FinalizeSignature(signature_info);
809
IncrementRandomNonce(random_info->nonce);
810
SetStringInfo(random_info->reservoir,GetSignatureDigest(signature_info));
812
datum=GetStringInfoDatum(random_info->reservoir);
816
(void) UnlockSemaphoreInfo(random_info->semaphore);
820
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
824
% S e t R a n d o m T r u e R a n d o m %
828
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
830
% SetRandomTrueRandom() declares your intentions to use true random numbers.
831
% True random numbers are encouraged but may not always be practical because
832
% your application may block while entropy is gathered from your environment.
834
% The format of the SetRandomTrueRandom method is:
836
% void SetRandomTrueRandom(const MagickBooleanType true_random)
838
% A description of each parameter follows:
840
% o true_random: declare your intentions to use true-random number.
843
MagickExport void SetRandomTrueRandom(const MagickBooleanType true_random)
845
gather_true_random=true_random;