|
MagickCore
6.7.5
|
00001 /* 00002 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 00003 % % 00004 % % 00005 % RRRR AAA N N DDDD OOO M M % 00006 % R R A A NN N D D O O MM MM % 00007 % RRRR AAAAA N N N D D O O M M M % 00008 % R R A A N NN D D O O M M % 00009 % R R A A N N DDDD OOO M M % 00010 % % 00011 % % 00012 % MagickCore Methods to Generate Random Numbers % 00013 % % 00014 % Software Design % 00015 % John Cristy % 00016 % December 2001 % 00017 % % 00018 % % 00019 % Copyright 1999-2012 ImageMagick Studio LLC, a non-profit organization % 00020 % dedicated to making software imaging solutions freely available. % 00021 % % 00022 % You may not use this file except in compliance with the License. You may % 00023 % obtain a copy of the License at % 00024 % % 00025 % http://www.imagemagick.org/script/license.php % 00026 % % 00027 % Unless required by applicable law or agreed to in writing, software % 00028 % distributed under the License is distributed on an "AS IS" BASIS, % 00029 % WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. % 00030 % See the License for the specific language governing permissions and % 00031 % limitations under the License. % 00032 % % 00033 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 00034 % 00035 % The generation of random numbers is too important to be left to chance. 00036 % -- Tom Christiansen <tchrist@mox.perl.com> 00037 % 00038 % 00039 */ 00040 00041 /* 00042 Include declarations. 00043 */ 00044 #if defined(__VMS) 00045 #include <time.h> 00046 #endif 00047 #if defined(__MINGW32__) 00048 #include <sys/time.h> 00049 #endif 00050 #include "MagickCore/studio.h" 00051 #include "MagickCore/exception.h" 00052 #include "MagickCore/exception-private.h" 00053 #include "MagickCore/memory_.h" 00054 #include "MagickCore/semaphore.h" 00055 #include "MagickCore/random_.h" 00056 #include "MagickCore/random-private.h" 00057 #include "MagickCore/resource_.h" 00058 #include "MagickCore/signature-private.h" 00059 #include "MagickCore/string_.h" 00060 #include "MagickCore/thread_.h" 00061 #include "MagickCore/thread-private.h" 00062 #include "MagickCore/utility.h" 00063 #include "MagickCore/utility-private.h" 00064 /* 00065 Define declarations. 00066 */ 00067 #define PseudoRandomHash SHA256Hash 00068 #define RandomEntropyLevel 9 00069 #define RandomFilename "reservoir.xdm" 00070 #define RandomFiletype "random" 00071 #define RandomProtocolMajorVersion 1 00072 #define RandomProtocolMinorVersion 0 00073 00074 /* 00075 Typedef declarations. 00076 */ 00077 struct _RandomInfo 00078 { 00079 SignatureInfo 00080 *signature_info; 00081 00082 StringInfo 00083 *nonce, 00084 *reservoir; 00085 00086 size_t 00087 i; 00088 00089 unsigned long 00090 seed[4]; 00091 00092 double 00093 normalize; 00094 00095 unsigned short 00096 protocol_major, 00097 protocol_minor; 00098 00099 SemaphoreInfo 00100 *semaphore; 00101 00102 ssize_t 00103 timestamp; 00104 00105 size_t 00106 signature; 00107 }; 00108 00109 /* 00110 External declarations. 00111 */ 00112 #if defined(__APPLE__) && !defined(TARGET_OS_IPHONE) 00113 #include <crt_externs.h> 00114 #define environ (*_NSGetEnviron()) 00115 #endif 00116 00117 extern char 00118 **environ; 00119 00120 /* 00121 Global declarations. 00122 */ 00123 static SemaphoreInfo 00124 *random_semaphore = (SemaphoreInfo *) NULL; 00125 00126 static unsigned long 00127 random_seed = ~0UL; 00128 00129 static MagickBooleanType 00130 gather_true_random = MagickFalse; 00131 00132 /* 00133 Forward declarations. 00134 */ 00135 static StringInfo 00136 *GenerateEntropicChaos(RandomInfo *); 00137 00138 /* 00139 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 00140 % % 00141 % % 00142 % % 00143 % A c q u i r e R a n d o m I n f o % 00144 % % 00145 % % 00146 % % 00147 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 00148 % 00149 % AcquireRandomInfo() allocates the RandomInfo structure. 00150 % 00151 % The format of the AcquireRandomInfo method is: 00152 % 00153 % RandomInfo *AcquireRandomInfo(void) 00154 % 00155 */ 00156 00157 static inline size_t MagickMin(const size_t x,const size_t y) 00158 { 00159 if (x < y) 00160 return(x); 00161 return(y); 00162 } 00163 00164 MagickExport RandomInfo *AcquireRandomInfo(void) 00165 { 00166 const StringInfo 00167 *digest; 00168 00169 RandomInfo 00170 *random_info; 00171 00172 StringInfo 00173 *entropy, 00174 *key, 00175 *nonce; 00176 00177 random_info=(RandomInfo *) AcquireMagickMemory(sizeof(*random_info)); 00178 if (random_info == (RandomInfo *) NULL) 00179 ThrowFatalException(ResourceLimitFatalError,"MemoryAllocationFailed"); 00180 (void) ResetMagickMemory(random_info,0,sizeof(*random_info)); 00181 random_info->signature_info=AcquireSignatureInfo(); 00182 random_info->nonce=AcquireStringInfo(2*GetSignatureDigestsize( 00183 random_info->signature_info)); 00184 ResetStringInfo(random_info->nonce); 00185 random_info->reservoir=AcquireStringInfo(GetSignatureDigestsize( 00186 random_info->signature_info)); 00187 ResetStringInfo(random_info->reservoir); 00188 random_info->normalize=1.0/(~0UL); 00189 random_info->semaphore=AllocateSemaphoreInfo(); 00190 random_info->protocol_major=RandomProtocolMajorVersion; 00191 random_info->protocol_minor=RandomProtocolMinorVersion; 00192 random_info->timestamp=(ssize_t) time(0); 00193 random_info->signature=MagickSignature; 00194 /* 00195 Seed random nonce. 00196 */ 00197 nonce=GenerateEntropicChaos(random_info); 00198 if (nonce == (StringInfo *) NULL) 00199 ThrowFatalException(ResourceLimitFatalError,"MemoryAllocationFailed"); 00200 InitializeSignature(random_info->signature_info); 00201 UpdateSignature(random_info->signature_info,nonce); 00202 FinalizeSignature(random_info->signature_info); 00203 SetStringInfoLength(nonce,(GetSignatureDigestsize( 00204 random_info->signature_info)+1)/2); 00205 SetStringInfo(nonce,GetSignatureDigest(random_info->signature_info)); 00206 SetStringInfo(random_info->nonce,nonce); 00207 nonce=DestroyStringInfo(nonce); 00208 /* 00209 Seed random reservoir with entropic data. 00210 */ 00211 entropy=GenerateEntropicChaos(random_info); 00212 if (entropy == (StringInfo *) NULL) 00213 ThrowFatalException(ResourceLimitFatalError,"MemoryAllocationFailed"); 00214 UpdateSignature(random_info->signature_info,entropy); 00215 FinalizeSignature(random_info->signature_info); 00216 SetStringInfo(random_info->reservoir,GetSignatureDigest( 00217 random_info->signature_info)); 00218 entropy=DestroyStringInfo(entropy); 00219 /* 00220 Seed pseudo random number generator. 00221 */ 00222 if (random_seed == ~0UL) 00223 { 00224 key=GetRandomKey(random_info,sizeof(random_seed)); 00225 (void) CopyMagickMemory(random_info->seed,GetStringInfoDatum(key), 00226 GetStringInfoLength(key)); 00227 key=DestroyStringInfo(key); 00228 } 00229 else 00230 { 00231 SignatureInfo 00232 *signature_info; 00233 00234 signature_info=AcquireSignatureInfo(); 00235 key=AcquireStringInfo(sizeof(random_seed)); 00236 SetStringInfoDatum(key,(unsigned char *) &random_seed); 00237 UpdateSignature(signature_info,key); 00238 key=DestroyStringInfo(key); 00239 FinalizeSignature(signature_info); 00240 digest=GetSignatureDigest(signature_info); 00241 (void) CopyMagickMemory(random_info->seed,GetStringInfoDatum(digest), 00242 MagickMin(GetSignatureDigestsize(signature_info), 00243 sizeof(*random_info->seed))); 00244 signature_info=DestroySignatureInfo(signature_info); 00245 } 00246 random_info->seed[1]=0x50a7f451UL; 00247 random_info->seed[2]=0x5365417eUL; 00248 random_info->seed[3]=0xc3a4171aUL; 00249 return(random_info); 00250 } 00251 00252 /* 00253 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 00254 % % 00255 % % 00256 % % 00257 + D e s t r o y R a n d o m I n f o % 00258 % % 00259 % % 00260 % % 00261 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 00262 % 00263 % DestroyRandomInfo() deallocates memory associated with the random 00264 % reservoir. 00265 % 00266 % The format of the DestroyRandomInfo method is: 00267 % 00268 % RandomInfo *DestroyRandomInfo(RandomInfo *random_info) 00269 % 00270 % A description of each parameter follows: 00271 % 00272 % o random_info: the random info. 00273 % 00274 */ 00275 MagickExport RandomInfo *DestroyRandomInfo(RandomInfo *random_info) 00276 { 00277 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"..."); 00278 assert(random_info != (RandomInfo *) NULL); 00279 assert(random_info->signature == MagickSignature); 00280 LockSemaphoreInfo(random_info->semaphore); 00281 if (random_info->reservoir != (StringInfo *) NULL) 00282 random_info->reservoir=DestroyStringInfo(random_info->reservoir); 00283 if (random_info->nonce != (StringInfo *) NULL) 00284 random_info->nonce=DestroyStringInfo(random_info->nonce); 00285 if (random_info->signature_info != (SignatureInfo *) NULL) 00286 random_info->signature_info=DestroySignatureInfo( 00287 random_info->signature_info); 00288 (void) ResetMagickMemory(random_info->seed,0,sizeof(*random_info->seed)); 00289 random_info->signature=(~MagickSignature); 00290 UnlockSemaphoreInfo(random_info->semaphore); 00291 DestroySemaphoreInfo(&random_info->semaphore); 00292 random_info=(RandomInfo *) RelinquishMagickMemory(random_info); 00293 return(random_info); 00294 } 00295 00296 /* 00297 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 00298 % % 00299 % % 00300 % % 00301 + G e n e r a t e E n t r o p i c C h a o s % 00302 % % 00303 % % 00304 % % 00305 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 00306 % 00307 % GenerateEntropicChaos() generate entropic chaos used to initialize the 00308 % random reservoir. 00309 % 00310 % The format of the GenerateEntropicChaos method is: 00311 % 00312 % StringInfo *GenerateEntropicChaos(RandomInfo *random_info) 00313 % 00314 % A description of each parameter follows: 00315 % 00316 % o random_info: the random info. 00317 % 00318 */ 00319 00320 #if !defined(MAGICKCORE_WINDOWS_SUPPORT) 00321 static ssize_t ReadRandom(int file,unsigned char *source,size_t length) 00322 { 00323 register unsigned char 00324 *q; 00325 00326 ssize_t 00327 offset, 00328 count; 00329 00330 offset=0; 00331 for (q=source; length != 0; length-=count) 00332 { 00333 count=(ssize_t) read(file,q,length); 00334 if (count <= 0) 00335 { 00336 count=0; 00337 if (errno == EINTR) 00338 continue; 00339 return(-1); 00340 } 00341 q+=count; 00342 offset+=count; 00343 } 00344 return(offset); 00345 } 00346 #endif 00347 00348 static StringInfo *GenerateEntropicChaos(RandomInfo *random_info) 00349 { 00350 #define MaxEntropyExtent 64 00351 00352 MagickThreadType 00353 tid; 00354 00355 StringInfo 00356 *chaos, 00357 *entropy; 00358 00359 size_t 00360 nanoseconds, 00361 seconds; 00362 00363 ssize_t 00364 pid; 00365 00366 /* 00367 Initialize random reservoir. 00368 */ 00369 entropy=AcquireStringInfo(0); 00370 LockSemaphoreInfo(random_info->semaphore); 00371 chaos=AcquireStringInfo(sizeof(unsigned char *)); 00372 SetStringInfoDatum(chaos,(unsigned char *) &entropy); 00373 ConcatenateStringInfo(entropy,chaos); 00374 SetStringInfoDatum(chaos,(unsigned char *) entropy); 00375 ConcatenateStringInfo(entropy,chaos); 00376 pid=(ssize_t) getpid(); 00377 SetStringInfoLength(chaos,sizeof(pid)); 00378 SetStringInfoDatum(chaos,(unsigned char *) &pid); 00379 ConcatenateStringInfo(entropy,chaos); 00380 tid=GetMagickThreadId(); 00381 SetStringInfoLength(chaos,sizeof(tid)); 00382 SetStringInfoDatum(chaos,(unsigned char *) &tid); 00383 ConcatenateStringInfo(entropy,chaos); 00384 #if defined(MAGICKCORE_HAVE_GETRUSAGE) && defined(RUSAGE_SELF) 00385 { 00386 struct rusage 00387 usage; 00388 00389 if (getrusage(RUSAGE_SELF,&usage) == 0) 00390 { 00391 SetStringInfoLength(chaos,sizeof(usage)); 00392 SetStringInfoDatum(chaos,(unsigned char *) &usage); 00393 } 00394 } 00395 #endif 00396 seconds=time((time_t *) 0); 00397 nanoseconds=0; 00398 #if defined(MAGICKCORE_HAVE_GETTIMEOFDAY) 00399 { 00400 struct timeval 00401 timer; 00402 00403 if (gettimeofday(&timer,(struct timezone *) NULL) == 0) 00404 { 00405 seconds=timer.tv_sec; 00406 nanoseconds=1000UL*timer.tv_usec; 00407 } 00408 } 00409 #endif 00410 #if defined(MAGICKCORE_HAVE_CLOCK_GETTIME) && defined(CLOCK_REALTIME_HR) 00411 { 00412 struct timespec 00413 timer; 00414 00415 if (clock_gettime(CLOCK_REALTIME_HR,&timer) == 0) 00416 { 00417 seconds=timer.tv_sec; 00418 nanoseconds=timer.tv_nsec; 00419 } 00420 } 00421 #endif 00422 SetStringInfoLength(chaos,sizeof(seconds)); 00423 SetStringInfoDatum(chaos,(unsigned char *) &seconds); 00424 ConcatenateStringInfo(entropy,chaos); 00425 SetStringInfoLength(chaos,sizeof(nanoseconds)); 00426 SetStringInfoDatum(chaos,(unsigned char *) &nanoseconds); 00427 ConcatenateStringInfo(entropy,chaos); 00428 nanoseconds=0; 00429 #if defined(MAGICKCORE_HAVE_CLOCK) 00430 nanoseconds=clock(); 00431 #endif 00432 #if defined(MAGICKCORE_HAVE_TIMES) 00433 { 00434 struct tms 00435 timer; 00436 00437 (void) times(&timer); 00438 nanoseconds=timer.tms_utime+timer.tms_stime; 00439 } 00440 #endif 00441 SetStringInfoLength(chaos,sizeof(nanoseconds)); 00442 SetStringInfoDatum(chaos,(unsigned char *) &nanoseconds); 00443 ConcatenateStringInfo(entropy,chaos); 00444 #if defined(MAGICKCORE_HAVE_MKSTEMP) 00445 { 00446 char 00447 *filename; 00448 00449 int 00450 file; 00451 00452 filename=ConstantString("magickXXXXXX"); 00453 file=mkstemp(filename); 00454 #if defined(__OS2__) 00455 setmode(file,O_BINARY); 00456 #endif 00457 if (file != -1) 00458 (void) close(file); 00459 (void) remove_utf8(filename); 00460 SetStringInfoLength(chaos,strlen(filename)); 00461 SetStringInfoDatum(chaos,(unsigned char *) filename); 00462 ConcatenateStringInfo(entropy,chaos); 00463 filename=DestroyString(filename); 00464 } 00465 #endif 00466 #if defined(MAGICKCORE_WINDOWS_SUPPORT) 00467 { 00468 double 00469 seconds; 00470 00471 LARGE_INTEGER 00472 nanoseconds; 00473 00474 MagickBooleanType 00475 status; 00476 00477 /* 00478 Not crytographically strong but better than nothing. 00479 */ 00480 seconds=NTElapsedTime()+NTUserTime(); 00481 SetStringInfoLength(chaos,sizeof(seconds)); 00482 SetStringInfoDatum(chaos,(unsigned char *) &seconds); 00483 ConcatenateStringInfo(entropy,chaos); 00484 if (QueryPerformanceCounter(&nanoseconds) != 0) 00485 { 00486 SetStringInfoLength(chaos,sizeof(nanoseconds)); 00487 SetStringInfoDatum(chaos,(unsigned char *) &nanoseconds); 00488 ConcatenateStringInfo(entropy,chaos); 00489 } 00490 /* 00491 Our best hope for true entropy. 00492 */ 00493 SetStringInfoLength(chaos,MaxEntropyExtent); 00494 status=NTGatherRandomData(MaxEntropyExtent,GetStringInfoDatum(chaos)); 00495 ConcatenateStringInfo(entropy,chaos); 00496 } 00497 #else 00498 { 00499 char 00500 *filename; 00501 00502 int 00503 file; 00504 00505 ssize_t 00506 count; 00507 00508 StringInfo 00509 *device; 00510 00511 /* 00512 Not crytographically strong but better than nothing. 00513 */ 00514 if (environ != (char **) NULL) 00515 { 00516 register ssize_t 00517 i; 00518 00519 /* 00520 Squeeze some entropy from the sometimes unpredicatble environment. 00521 */ 00522 for (i=0; environ[i] != (char *) NULL; i++) 00523 { 00524 SetStringInfoLength(chaos,strlen(environ[i])); 00525 SetStringInfoDatum(chaos,(unsigned char *) environ[i]); 00526 ConcatenateStringInfo(entropy,chaos); 00527 } 00528 } 00529 filename=AcquireString("/dev/urandom"); 00530 device=StringToStringInfo(filename); 00531 device=DestroyStringInfo(device); 00532 file=open_utf8(filename,O_RDONLY | O_BINARY,0); 00533 filename=DestroyString(filename); 00534 if (file != -1) 00535 { 00536 SetStringInfoLength(chaos,MaxEntropyExtent); 00537 count=ReadRandom(file,GetStringInfoDatum(chaos),MaxEntropyExtent); 00538 (void) close(file); 00539 SetStringInfoLength(chaos,(size_t) count); 00540 ConcatenateStringInfo(entropy,chaos); 00541 } 00542 if (gather_true_random != MagickFalse) 00543 { 00544 /* 00545 Our best hope for true entropy. 00546 */ 00547 filename=AcquireString("/dev/random"); 00548 device=StringToStringInfo(filename); 00549 device=DestroyStringInfo(device); 00550 file=open_utf8(filename,O_RDONLY | O_BINARY,0); 00551 filename=DestroyString(filename); 00552 if (file == -1) 00553 { 00554 filename=AcquireString("/dev/srandom"); 00555 device=StringToStringInfo(filename); 00556 device=DestroyStringInfo(device); 00557 file=open_utf8(filename,O_RDONLY | O_BINARY,0); 00558 } 00559 if (file != -1) 00560 { 00561 SetStringInfoLength(chaos,MaxEntropyExtent); 00562 count=ReadRandom(file,GetStringInfoDatum(chaos),MaxEntropyExtent); 00563 (void) close(file); 00564 SetStringInfoLength(chaos,(size_t) count); 00565 ConcatenateStringInfo(entropy,chaos); 00566 } 00567 } 00568 } 00569 #endif 00570 chaos=DestroyStringInfo(chaos); 00571 UnlockSemaphoreInfo(random_info->semaphore); 00572 return(entropy); 00573 } 00574 00575 /* 00576 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 00577 % % 00578 % % 00579 % % 00580 % G e t P s e u d o R a n d o m V a l u e % 00581 % % 00582 % % 00583 % % 00584 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 00585 % 00586 % GetPseudoRandomValue() return a non-negative double-precision floating-point 00587 % value uniformly distributed over the interval [0.0, 1.0) with a 2 to the 00588 % 128th-1 period. 00589 % 00590 % The format of the GetPseudoRandomValue method is: 00591 % 00592 % double GetPseudoRandomValue(RandomInfo *randon_info) 00593 % 00594 % A description of each parameter follows: 00595 % 00596 % o random_info: the random info. 00597 % 00598 */ 00599 MagickExport double GetPseudoRandomValue(RandomInfo *random_info) 00600 { 00601 register unsigned long 00602 *seed; 00603 00604 unsigned long 00605 alpha; 00606 00607 seed=random_info->seed; 00608 do 00609 { 00610 alpha=(unsigned long) (seed[1] ^ (seed[1] << 11)); 00611 seed[1]=seed[2]; 00612 seed[2]=seed[3]; 00613 seed[3]=seed[0]; 00614 seed[0]=(seed[0] ^ (seed[0] >> 19)) ^ (alpha ^ (alpha >> 8)); 00615 } while (seed[0] == ~0UL); 00616 return(random_info->normalize*seed[0]); 00617 } 00618 00619 /* 00620 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 00621 % % 00622 % % 00623 % % 00624 % G e t R a n d o m K e y % 00625 % % 00626 % % 00627 % % 00628 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 00629 % 00630 % GetRandomKey() gets a random key from the reservoir. 00631 % 00632 % The format of the GetRandomKey method is: 00633 % 00634 % StringInfo *GetRandomKey(RandomInfo *random_info,const size_t length) 00635 % 00636 % A description of each parameter follows: 00637 % 00638 % o random_info: the random info. 00639 % 00640 % o length: the key length. 00641 % 00642 */ 00643 MagickExport StringInfo *GetRandomKey(RandomInfo *random_info, 00644 const size_t length) 00645 { 00646 StringInfo 00647 *key; 00648 00649 assert(random_info != (RandomInfo *) NULL); 00650 key=AcquireStringInfo(length); 00651 SetRandomKey(random_info,length,GetStringInfoDatum(key)); 00652 return(key); 00653 } 00654 00655 /* 00656 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 00657 % % 00658 % % 00659 % % 00660 % G e t R a n d o m V a l u e % 00661 % % 00662 % % 00663 % % 00664 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 00665 % 00666 % GetRandomValue() return a non-negative double-precision floating-point 00667 % value uniformly distributed over the interval [0.0, 1.0) with a 2 to the 00668 % 128th-1 period (not cryptographically strong). 00669 % 00670 % The format of the GetRandomValue method is: 00671 % 00672 % double GetRandomValue(void) 00673 % 00674 */ 00675 MagickExport double GetRandomValue(RandomInfo *random_info) 00676 { 00677 unsigned long 00678 key, 00679 range; 00680 00681 range=(~0UL); 00682 do 00683 { 00684 SetRandomKey(random_info,sizeof(key),(unsigned char *) &key); 00685 } while (key == range); 00686 return((double) key/range); 00687 } 00688 00689 /* 00690 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 00691 % % 00692 % % 00693 % % 00694 + R a n d o m C o m p o n e n t G e n e s i s % 00695 % % 00696 % % 00697 % % 00698 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 00699 % 00700 % RandomComponentGenesis() instantiates the random component. 00701 % 00702 % The format of the RandomComponentGenesis method is: 00703 % 00704 % MagickBooleanType RandomComponentGenesis(void) 00705 % 00706 */ 00707 MagickPrivate MagickBooleanType RandomComponentGenesis(void) 00708 { 00709 AcquireSemaphoreInfo(&random_semaphore); 00710 return(MagickTrue); 00711 } 00712 00713 /* 00714 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 00715 % % 00716 % % 00717 % % 00718 + R a n d o m C o m p o n e n t T e r m i n u s % 00719 % % 00720 % % 00721 % % 00722 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 00723 % 00724 % RandomComponentTerminus() destroys the random component. 00725 % 00726 % The format of the RandomComponentTerminus method is: 00727 % 00728 % RandomComponentTerminus(void) 00729 % 00730 */ 00731 MagickPrivate void RandomComponentTerminus(void) 00732 { 00733 if (random_semaphore == (SemaphoreInfo *) NULL) 00734 AcquireSemaphoreInfo(&random_semaphore); 00735 DestroySemaphoreInfo(&random_semaphore); 00736 } 00737 00738 /* 00739 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 00740 % % 00741 % % 00742 % % 00743 % 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 % 00744 % % 00745 % % 00746 % % 00747 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 00748 % 00749 % SeedPseudoRandomGenerator() initializes the pseudo-random number generator 00750 % with a random seed. 00751 % 00752 % The format of the SeedPseudoRandomGenerator method is: 00753 % 00754 % void SeedPseudoRandomGenerator(const unsigned long seed) 00755 % 00756 % A description of each parameter follows: 00757 % 00758 % o seed: the seed. 00759 % 00760 */ 00761 MagickExport void SeedPseudoRandomGenerator(const unsigned long seed) 00762 { 00763 random_seed=seed; 00764 } 00765 00766 /* 00767 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 00768 % % 00769 % % 00770 % % 00771 % S e t R a n d o m K e y % 00772 % % 00773 % % 00774 % % 00775 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 00776 % 00777 % SetRandomKey() sets a random key from the reservoir. 00778 % 00779 % The format of the SetRandomKey method is: 00780 % 00781 % void SetRandomKey(RandomInfo *random_info,const size_t length, 00782 % unsigned char *key) 00783 % 00784 % A description of each parameter follows: 00785 % 00786 % o random_info: the random info. 00787 % 00788 % o length: the key length. 00789 % 00790 % o key: the key. 00791 % 00792 */ 00793 00794 static inline void IncrementRandomNonce(StringInfo *nonce) 00795 { 00796 register ssize_t 00797 i; 00798 00799 unsigned char 00800 *datum; 00801 00802 datum=GetStringInfoDatum(nonce); 00803 for (i=(ssize_t) (GetStringInfoLength(nonce)-1); i != 0; i--) 00804 { 00805 datum[i]++; 00806 if (datum[i] != 0) 00807 return; 00808 } 00809 ThrowFatalException(RandomFatalError,"SequenceWrapError"); 00810 } 00811 00812 MagickExport void SetRandomKey(RandomInfo *random_info,const size_t length, 00813 unsigned char *key) 00814 { 00815 register size_t 00816 i; 00817 00818 register unsigned char 00819 *p; 00820 00821 SignatureInfo 00822 *signature_info; 00823 00824 unsigned char 00825 *datum; 00826 00827 assert(random_info != (RandomInfo *) NULL); 00828 if (length == 0) 00829 return; 00830 LockSemaphoreInfo(random_info->semaphore); 00831 signature_info=random_info->signature_info; 00832 datum=GetStringInfoDatum(random_info->reservoir); 00833 i=length; 00834 for (p=key; (i != 0) && (random_info->i != 0); i--) 00835 { 00836 *p++=datum[random_info->i]; 00837 random_info->i++; 00838 if (random_info->i == GetSignatureDigestsize(signature_info)) 00839 random_info->i=0; 00840 } 00841 while (i >= GetSignatureDigestsize(signature_info)) 00842 { 00843 InitializeSignature(signature_info); 00844 UpdateSignature(signature_info,random_info->nonce); 00845 FinalizeSignature(signature_info); 00846 IncrementRandomNonce(random_info->nonce); 00847 (void) CopyMagickMemory(p,GetStringInfoDatum(GetSignatureDigest( 00848 signature_info)),GetSignatureDigestsize(signature_info)); 00849 p+=GetSignatureDigestsize(signature_info); 00850 i-=GetSignatureDigestsize(signature_info); 00851 } 00852 if (i != 0) 00853 { 00854 InitializeSignature(signature_info); 00855 UpdateSignature(signature_info,random_info->nonce); 00856 FinalizeSignature(signature_info); 00857 IncrementRandomNonce(random_info->nonce); 00858 SetStringInfo(random_info->reservoir,GetSignatureDigest(signature_info)); 00859 random_info->i=i; 00860 datum=GetStringInfoDatum(random_info->reservoir); 00861 while (i-- != 0) 00862 p[i]=datum[i]; 00863 } 00864 UnlockSemaphoreInfo(random_info->semaphore); 00865 } 00866 00867 /* 00868 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 00869 % % 00870 % % 00871 % % 00872 % S e t R a n d o m T r u e R a n d o m % 00873 % % 00874 % % 00875 % % 00876 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 00877 % 00878 % SetRandomTrueRandom() declares your intentions to use true random numbers. 00879 % True random numbers are encouraged but may not always be practical because 00880 % your application may block while entropy is gathered from your environment. 00881 % 00882 % The format of the SetRandomTrueRandom method is: 00883 % 00884 % void SetRandomTrueRandom(const MagickBooleanType true_random) 00885 % 00886 % A description of each parameter follows: 00887 % 00888 % o true_random: declare your intentions to use true-random number. 00889 % 00890 */ 00891 MagickExport void SetRandomTrueRandom(const MagickBooleanType true_random) 00892 { 00893 gather_true_random=true_random; 00894 }