1 /* 2 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 3 % % 4 % % 5 % RRRR AAA N N DDDD OOO M M % 6 % R R A A NN N D D O O MM MM % 7 % RRRR AAAAA N N N D D O O M M M % 8 % R R A A N NN D D O O M M % 9 % R R A A N N DDDD OOO M M % 10 % % 11 % % 12 % MagickCore Methods to Generate Random Numbers % 13 % % 14 % Software Design % 15 % Cristy % 16 % December 2001 % 17 % % 18 % % 19 % Copyright 1999-2016 ImageMagick Studio LLC, a non-profit organization % 20 % dedicated to making software imaging solutions freely available. % 21 % % 22 % You may not use this file except in compliance with the License. You may % 23 % obtain a copy of the License at % 24 % % 25 % http://www.imagemagick.org/script/license.php % 26 % % 27 % Unless required by applicable law or agreed to in writing, software % 28 % distributed under the License is distributed on an "AS IS" BASIS, % 29 % WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. % 30 % See the License for the specific language governing permissions and % 31 % limitations under the License. % 32 % % 33 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 34 % 35 % The generation of random numbers is too important to be left to chance. 36 % -- Tom Christiansen <tchrist (at) mox.perl.com> 37 % 38 % 39 */ 40 41 /* 43 Include declarations. 44 */ 45 #if defined(__VMS) 46 #include <time.h> 47 #endif 48 #if defined(__MINGW32__) || defined(__MINGW64__) 49 #include <sys/time.h> 50 #endif 51 #include "MagickCore/studio.h" 52 #include "MagickCore/exception.h" 53 #include "MagickCore/exception-private.h" 54 #include "MagickCore/image-private.h" 55 #include "MagickCore/memory_.h" 56 #include "MagickCore/semaphore.h" 57 #include "MagickCore/random_.h" 58 #include "MagickCore/random-private.h" 59 #include "MagickCore/resource_.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 /* 67 Define declarations. 68 */ 69 #define PseudoRandomHash SHA256Hash 70 #define RandomEntropyLevel 9 71 #define RandomFilename "reservoir.xdm" 72 #define RandomFiletype "random" 73 #define RandomProtocolMajorVersion 1 74 #define RandomProtocolMinorVersion 0 75 76 /* 78 Typedef declarations. 79 */ 80 struct _RandomInfo 81 { 82 SignatureInfo 83 *signature_info; 84 85 StringInfo 86 *nonce, 87 *reservoir; 88 89 size_t 90 i; 91 92 unsigned long 93 seed[4]; 94 95 double 96 normalize; 97 98 unsigned long 99 secret_key; 100 101 unsigned short 102 protocol_major, 103 protocol_minor; 104 105 SemaphoreInfo 106 *semaphore; 107 108 ssize_t 109 timestamp; 110 111 size_t 112 signature; 113 }; 114 115 /* 117 External declarations. 118 */ 119 #if defined(__APPLE__) && !defined(TARGET_OS_IPHONE) 120 #include <crt_externs.h> 121 #define environ (*_NSGetEnviron()) 122 #endif 123 124 #if !defined(MAGICKCORE_WINDOWS_SUPPORT) 125 extern char 126 **environ; 127 #endif 128 129 /* 131 Global declarations. 132 */ 133 static SemaphoreInfo 134 *random_semaphore = (SemaphoreInfo *) NULL; 135 136 static unsigned long 137 secret_key = ~0UL; 138 139 static MagickBooleanType 140 gather_true_random = MagickFalse; 141 142 /* 144 Forward declarations. 145 */ 146 static StringInfo 147 *GenerateEntropicChaos(RandomInfo *); 148 149 /* 151 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 152 % % 153 % % 154 % % 155 % A c q u i r e R a n d o m I n f o % 156 % % 157 % % 158 % % 159 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 160 % 161 % AcquireRandomInfo() allocates the RandomInfo structure. 162 % 163 % The format of the AcquireRandomInfo method is: 164 % 165 % RandomInfo *AcquireRandomInfo(void) 166 % 167 */ 168 169 MagickExport RandomInfo *AcquireRandomInfo(void) 170 { 171 const StringInfo 172 *digest; 173 174 RandomInfo 175 *random_info; 176 177 StringInfo 178 *entropy, 179 *key, 180 *nonce; 181 182 random_info=(RandomInfo *) AcquireMagickMemory(sizeof(*random_info)); 183 if (random_info == (RandomInfo *) NULL) 184 ThrowFatalException(ResourceLimitFatalError,"MemoryAllocationFailed"); 185 (void) ResetMagickMemory(random_info,0,sizeof(*random_info)); 186 random_info->signature_info=AcquireSignatureInfo(); 187 random_info->nonce=AcquireStringInfo(2*GetSignatureDigestsize( 188 random_info->signature_info)); 189 ResetStringInfo(random_info->nonce); 190 random_info->reservoir=AcquireStringInfo(GetSignatureDigestsize( 191 random_info->signature_info)); 192 ResetStringInfo(random_info->reservoir); 193 random_info->normalize=1.0/(~0UL); 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=(ssize_t) time(0); 199 random_info->signature=MagickCoreSignature; 200 /* 201 Seed random nonce. 202 */ 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); 214 /* 215 Seed random reservoir with entropic data. 216 */ 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); 225 /* 226 Seed pseudo random number generator. 227 */ 228 if (random_info->secret_key == ~0UL) 229 { 230 key=GetRandomKey(random_info,sizeof(random_info->secret_key)); 231 (void) CopyMagickMemory(random_info->seed,GetStringInfoDatum(key), 232 GetStringInfoLength(key)); 233 key=DestroyStringInfo(key); 234 } 235 else 236 { 237 SignatureInfo 238 *signature_info; 239 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) CopyMagickMemory(random_info->seed,GetStringInfoDatum(digest), 248 MagickMin(GetSignatureDigestsize(signature_info), 249 sizeof(*random_info->seed))); 250 signature_info=DestroySignatureInfo(signature_info); 251 } 252 random_info->seed[1]=0x50a7f451UL; 253 random_info->seed[2]=0x5365417eUL; 254 random_info->seed[3]=0xc3a4171aUL; 255 return(random_info); 256 } 257 258 /* 260 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 261 % % 262 % % 263 % % 264 + D e s t r o y R a n d o m I n f o % 265 % % 266 % % 267 % % 268 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 269 % 270 % DestroyRandomInfo() deallocates memory associated with the random 271 % reservoir. 272 % 273 % The format of the DestroyRandomInfo method is: 274 % 275 % RandomInfo *DestroyRandomInfo(RandomInfo *random_info) 276 % 277 % A description of each parameter follows: 278 % 279 % o random_info: the random info. 280 % 281 */ 282 MagickExport RandomInfo *DestroyRandomInfo(RandomInfo *random_info) 283 { 284 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"..."); 285 assert(random_info != (RandomInfo *) NULL); 286 assert(random_info->signature == MagickCoreSignature); 287 LockSemaphoreInfo(random_info->semaphore); 288 if (random_info->reservoir != (StringInfo *) NULL) 289 random_info->reservoir=DestroyStringInfo(random_info->reservoir); 290 if (random_info->nonce != (StringInfo *) NULL) 291 random_info->nonce=DestroyStringInfo(random_info->nonce); 292 if (random_info->signature_info != (SignatureInfo *) NULL) 293 random_info->signature_info=DestroySignatureInfo( 294 random_info->signature_info); 295 (void) ResetMagickMemory(random_info->seed,0,sizeof(*random_info->seed)); 296 random_info->signature=(~MagickCoreSignature); 297 UnlockSemaphoreInfo(random_info->semaphore); 298 RelinquishSemaphoreInfo(&random_info->semaphore); 299 random_info=(RandomInfo *) RelinquishMagickMemory(random_info); 300 return(random_info); 301 } 302 303 /* 305 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 306 % % 307 % % 308 % % 309 + G e n e r a t e E n t r o p i c C h a o s % 310 % % 311 % % 312 % % 313 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 314 % 315 % GenerateEntropicChaos() generate entropic chaos used to initialize the 316 % random reservoir. 317 % 318 % The format of the GenerateEntropicChaos method is: 319 % 320 % StringInfo *GenerateEntropicChaos(RandomInfo *random_info) 321 % 322 % A description of each parameter follows: 323 % 324 % o random_info: the random info. 325 % 326 */ 327 328 #if !defined(MAGICKCORE_WINDOWS_SUPPORT) 329 static ssize_t ReadRandom(int file,unsigned char *source,size_t length) 330 { 331 register unsigned char 332 *q; 333 334 ssize_t 335 offset, 336 count; 337 338 offset=0; 339 for (q=source; length != 0; length-=count) 340 { 341 count=(ssize_t) read(file,q,length); 342 if (count <= 0) 343 { 344 count=0; 345 if (errno == EINTR) 346 continue; 347 return(-1); 348 } 349 q+=count; 350 offset+=count; 351 } 352 return(offset); 353 } 354 #endif 355 356 static StringInfo *GenerateEntropicChaos(RandomInfo *random_info) 357 { 358 #define MaxEntropyExtent 64 359 360 MagickThreadType 361 tid; 362 363 StringInfo 364 *chaos, 365 *entropy; 366 367 size_t 368 nanoseconds, 369 seconds; 370 371 ssize_t 372 pid; 373 374 /* 375 Initialize random reservoir. 376 */ 377 entropy=AcquireStringInfo(0); 378 LockSemaphoreInfo(random_info->semaphore); 379 chaos=AcquireStringInfo(sizeof(unsigned char *)); 380 SetStringInfoDatum(chaos,(unsigned char *) &entropy); 381 ConcatenateStringInfo(entropy,chaos); 382 SetStringInfoDatum(chaos,(unsigned char *) entropy); 383 ConcatenateStringInfo(entropy,chaos); 384 pid=(ssize_t) getpid(); 385 SetStringInfoLength(chaos,sizeof(pid)); 386 SetStringInfoDatum(chaos,(unsigned char *) &pid); 387 ConcatenateStringInfo(entropy,chaos); 388 tid=GetMagickThreadId(); 389 SetStringInfoLength(chaos,sizeof(tid)); 390 SetStringInfoDatum(chaos,(unsigned char *) &tid); 391 ConcatenateStringInfo(entropy,chaos); 392 #if defined(MAGICKCORE_HAVE_SYSCONF) && defined(_SC_PHYS_PAGES) 393 { 394 ssize_t 395 pages; 396 397 pages=(ssize_t) sysconf(_SC_PHYS_PAGES); 398 SetStringInfoLength(chaos,sizeof(pages)); 399 SetStringInfoDatum(chaos,(unsigned char *) &pages); 400 ConcatenateStringInfo(entropy,chaos); 401 } 402 #endif 403 #if defined(MAGICKCORE_HAVE_GETRUSAGE) && defined(RUSAGE_SELF) 404 { 405 struct rusage 406 usage; 407 408 if (getrusage(RUSAGE_SELF,&usage) == 0) 409 { 410 SetStringInfoLength(chaos,sizeof(usage)); 411 SetStringInfoDatum(chaos,(unsigned char *) &usage); 412 } 413 } 414 #endif 415 seconds=time((time_t *) 0); 416 nanoseconds=0; 417 #if defined(MAGICKCORE_HAVE_GETTIMEOFDAY) 418 { 419 struct timeval 420 timer; 421 422 if (gettimeofday(&timer,(struct timezone *) NULL) == 0) 423 { 424 seconds=timer.tv_sec; 425 nanoseconds=1000UL*timer.tv_usec; 426 } 427 } 428 #endif 429 #if defined(MAGICKCORE_HAVE_CLOCK_GETTIME) && defined(CLOCK_REALTIME_HR) 430 { 431 struct timespec 432 timer; 433 434 if (clock_gettime(CLOCK_REALTIME_HR,&timer) == 0) 435 { 436 seconds=timer.tv_sec; 437 nanoseconds=timer.tv_nsec; 438 } 439 } 440 #endif 441 SetStringInfoLength(chaos,sizeof(seconds)); 442 SetStringInfoDatum(chaos,(unsigned char *) &seconds); 443 ConcatenateStringInfo(entropy,chaos); 444 SetStringInfoLength(chaos,sizeof(nanoseconds)); 445 SetStringInfoDatum(chaos,(unsigned char *) &nanoseconds); 446 ConcatenateStringInfo(entropy,chaos); 447 nanoseconds=0; 448 #if defined(MAGICKCORE_HAVE_CLOCK) 449 nanoseconds=clock(); 450 #endif 451 #if defined(MAGICKCORE_HAVE_TIMES) 452 { 453 struct tms 454 timer; 455 456 (void) times(&timer); 457 nanoseconds=timer.tms_utime+timer.tms_stime; 458 } 459 #endif 460 SetStringInfoLength(chaos,sizeof(nanoseconds)); 461 SetStringInfoDatum(chaos,(unsigned char *) &nanoseconds); 462 ConcatenateStringInfo(entropy,chaos); 463 #if defined(MAGICKCORE_HAVE_MKSTEMP) 464 { 465 char 466 path[MagickPathExtent]; 467 468 int 469 file; 470 471 (void) GetPathTemplate(path); 472 file=mkstemp(path); 473 if (file != -1) 474 { 475 #if defined(MAGICKCORE_HAVE_FCHMOD) 476 (void) fchmod(file,0600); 477 #endif 478 #if defined(__OS2__) 479 setmode(file,O_BINARY); 480 #endif 481 (void) close(file); 482 } 483 (void) remove_utf8(path); 484 SetStringInfoLength(chaos,strlen(path)); 485 SetStringInfoDatum(chaos,(unsigned char *) path); 486 ConcatenateStringInfo(entropy,chaos); 487 } 488 #endif 489 #if defined(MAGICKCORE_WINDOWS_SUPPORT) 490 { 491 double 492 seconds; 493 494 LARGE_INTEGER 495 nanoseconds; 496 497 MagickBooleanType 498 status; 499 500 /* 501 Not crytographically strong but better than nothing. 502 */ 503 seconds=NTElapsedTime()+NTUserTime(); 504 SetStringInfoLength(chaos,sizeof(seconds)); 505 SetStringInfoDatum(chaos,(unsigned char *) &seconds); 506 ConcatenateStringInfo(entropy,chaos); 507 if (QueryPerformanceCounter(&nanoseconds) != 0) 508 { 509 SetStringInfoLength(chaos,sizeof(nanoseconds)); 510 SetStringInfoDatum(chaos,(unsigned char *) &nanoseconds); 511 ConcatenateStringInfo(entropy,chaos); 512 } 513 /* 514 Our best hope for true entropy. 515 */ 516 SetStringInfoLength(chaos,MaxEntropyExtent); 517 status=NTGatherRandomData(MaxEntropyExtent,GetStringInfoDatum(chaos)); 518 (void) status; 519 ConcatenateStringInfo(entropy,chaos); 520 } 521 #else 522 { 523 char 524 *filename; 525 526 int 527 file; 528 529 ssize_t 530 count; 531 532 StringInfo 533 *device; 534 535 /* 536 Not crytographically strong but better than nothing. 537 */ 538 if (environ != (char **) NULL) 539 { 540 register ssize_t 541 i; 542 543 /* 544 Squeeze some entropy from the sometimes unpredicatble environment. 545 */ 546 for (i=0; environ[i] != (char *) NULL; i++) 547 { 548 SetStringInfoLength(chaos,strlen(environ[i])); 549 SetStringInfoDatum(chaos,(unsigned char *) environ[i]); 550 ConcatenateStringInfo(entropy,chaos); 551 } 552 } 553 filename=AcquireString("/dev/urandom"); 554 device=StringToStringInfo(filename); 555 device=DestroyStringInfo(device); 556 file=open_utf8(filename,O_RDONLY | O_BINARY,0); 557 filename=DestroyString(filename); 558 if (file != -1) 559 { 560 SetStringInfoLength(chaos,MaxEntropyExtent); 561 count=ReadRandom(file,GetStringInfoDatum(chaos),MaxEntropyExtent); 562 (void) close(file); 563 SetStringInfoLength(chaos,(size_t) count); 564 ConcatenateStringInfo(entropy,chaos); 565 } 566 if (gather_true_random != MagickFalse) 567 { 568 /* 569 Our best hope for true entropy. 570 */ 571 filename=AcquireString("/dev/random"); 572 device=StringToStringInfo(filename); 573 device=DestroyStringInfo(device); 574 file=open_utf8(filename,O_RDONLY | O_BINARY,0); 575 filename=DestroyString(filename); 576 if (file == -1) 577 { 578 filename=AcquireString("/dev/srandom"); 579 device=StringToStringInfo(filename); 580 device=DestroyStringInfo(device); 581 file=open_utf8(filename,O_RDONLY | O_BINARY,0); 582 } 583 if (file != -1) 584 { 585 SetStringInfoLength(chaos,MaxEntropyExtent); 586 count=ReadRandom(file,GetStringInfoDatum(chaos),MaxEntropyExtent); 587 (void) close(file); 588 SetStringInfoLength(chaos,(size_t) count); 589 ConcatenateStringInfo(entropy,chaos); 590 } 591 } 592 } 593 #endif 594 chaos=DestroyStringInfo(chaos); 595 UnlockSemaphoreInfo(random_info->semaphore); 596 return(entropy); 597 } 598 599 /* 601 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 602 % % 603 % % 604 % % 605 % G e t P s e u d o R a n d o m V a l u e % 606 % % 607 % % 608 % % 609 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 610 % 611 % GetPseudoRandomValue() return a non-negative double-precision floating-point 612 % value uniformly distributed over the interval [0.0, 1.0) with a 2 to the 613 % 128th-1 period. 614 % 615 % The format of the GetPseudoRandomValue method is: 616 % 617 % double GetPseudoRandomValue(RandomInfo *randon_info) 618 % 619 % A description of each parameter follows: 620 % 621 % o random_info: the random info. 622 % 623 */ 624 MagickExport double GetPseudoRandomValue(RandomInfo *random_info) 625 { 626 register unsigned long 627 *seed; 628 629 unsigned long 630 alpha; 631 632 seed=random_info->seed; 633 do 634 { 635 alpha=(unsigned long) (seed[1] ^ (seed[1] << 11)); 636 seed[1]=seed[2]; 637 seed[2]=seed[3]; 638 seed[3]=seed[0]; 639 seed[0]=(seed[0] ^ (seed[0] >> 19)) ^ (alpha ^ (alpha >> 8)); 640 } while (seed[0] == ~0UL); 641 return(random_info->normalize*seed[0]); 642 } 643 644 /* 646 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 647 % % 648 % % 649 % % 650 + G e t R a n d o m I n f o N o r m a l i z e % 651 % % 652 % % 653 % % 654 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 655 % 656 % GetRandomInfoNormalize() returns the random normalize value. 657 % 658 % The format of the GetRandomInfoNormalize method is: 659 % 660 % double GetRandomInfoNormalize(const RandomInfo *random_info) 661 % 662 % A description of each parameter follows: 663 % 664 % o random_info: the random info. 665 % 666 */ 667 MagickPrivate double GetRandomInfoNormalize(const RandomInfo *random_info) 668 { 669 assert(random_info != (const RandomInfo *) NULL); 670 return(random_info->normalize); 671 } 672 673 /* 675 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 676 % % 677 % % 678 % % 679 + G e t R a n d o m I n f o S e e d % 680 % % 681 % % 682 % % 683 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 684 % 685 % GetRandomInfoSeed() returns the random seed. 686 % 687 % The format of the GetRandomInfoSeed method is: 688 % 689 % unsigned long *GetRandomInfoSeed(RandomInfo *random_info) 690 % 691 % A description of each parameter follows: 692 % 693 % o random_info: the random info. 694 % 695 */ 696 MagickPrivate unsigned long *GetRandomInfoSeed(RandomInfo *random_info) 697 { 698 assert(random_info != (RandomInfo *) NULL); 699 return(random_info->seed); 700 } 701 702 /* 704 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 705 % % 706 % % 707 % % 708 % G e t R a n d o m K e y % 709 % % 710 % % 711 % % 712 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 713 % 714 % GetRandomKey() gets a random key from the reservoir. 715 % 716 % The format of the GetRandomKey method is: 717 % 718 % StringInfo *GetRandomKey(RandomInfo *random_info,const size_t length) 719 % 720 % A description of each parameter follows: 721 % 722 % o random_info: the random info. 723 % 724 % o length: the key length. 725 % 726 */ 727 MagickExport StringInfo *GetRandomKey(RandomInfo *random_info, 728 const size_t length) 729 { 730 StringInfo 731 *key; 732 733 assert(random_info != (RandomInfo *) NULL); 734 key=AcquireStringInfo(length); 735 SetRandomKey(random_info,length,GetStringInfoDatum(key)); 736 return(key); 737 } 738 739 /* 741 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 742 % % 743 % % 744 % % 745 % G e t R a n d o m S e c r e t K e y % 746 % % 747 % % 748 % % 749 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 750 % 751 % GetRandomSecretKey() returns the random secet key. 752 % 753 % The format of the GetRandomSecretKey method is: 754 % 755 % unsigned long GetRandomSecretKey(const RandomInfo *random_info) 756 % 757 % A description of each parameter follows: 758 % 759 % o random_info: the random info. 760 */ 761 MagickExport unsigned long GetRandomSecretKey(const RandomInfo *random_info) 762 { 763 return(random_info->secret_key); 764 } 765 766 /* 768 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 769 % % 770 % % 771 % % 772 % G e t R a n d o m V a l u e % 773 % % 774 % % 775 % % 776 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 777 % 778 % GetRandomValue() return a non-negative double-precision floating-point 779 % value uniformly distributed over the interval [0.0, 1.0) with a 2 to the 780 % 128th-1 period (not cryptographically strong). 781 % 782 % The format of the GetRandomValue method is: 783 % 784 % double GetRandomValue(void) 785 % 786 */ 787 MagickExport double GetRandomValue(RandomInfo *random_info) 788 { 789 unsigned long 790 key, 791 range; 792 793 range=(~0UL); 794 do 795 { 796 SetRandomKey(random_info,sizeof(key),(unsigned char *) &key); 797 } while (key == range); 798 return((double) key/range); 799 } 800 801 /* 803 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 804 % % 805 % % 806 % % 807 + R a n d o m C o m p o n e n t G e n e s i s % 808 % % 809 % % 810 % % 811 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 812 % 813 % RandomComponentGenesis() instantiates the random component. 814 % 815 % The format of the RandomComponentGenesis method is: 816 % 817 % MagickBooleanType RandomComponentGenesis(void) 818 % 819 */ 820 MagickPrivate MagickBooleanType RandomComponentGenesis(void) 821 { 822 if (random_semaphore == (SemaphoreInfo *) NULL) 823 random_semaphore=AcquireSemaphoreInfo(); 824 return(MagickTrue); 825 } 826 827 /* 829 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 830 % % 831 % % 832 % % 833 + R a n d o m C o m p o n e n t T e r m i n u s % 834 % % 835 % % 836 % % 837 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 838 % 839 % RandomComponentTerminus() destroys the random component. 840 % 841 % The format of the RandomComponentTerminus method is: 842 % 843 % RandomComponentTerminus(void) 844 % 845 */ 846 MagickPrivate void RandomComponentTerminus(void) 847 { 848 if (random_semaphore == (SemaphoreInfo *) NULL) 849 ActivateSemaphoreInfo(&random_semaphore); 850 RelinquishSemaphoreInfo(&random_semaphore); 851 } 852 853 /* 855 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 856 % % 857 % % 858 % % 859 % S e t R a n d o m K e y % 860 % % 861 % % 862 % % 863 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 864 % 865 % SetRandomKey() sets a random key from the reservoir. 866 % 867 % The format of the SetRandomKey method is: 868 % 869 % void SetRandomKey(RandomInfo *random_info,const size_t length, 870 % unsigned char *key) 871 % 872 % A description of each parameter follows: 873 % 874 % o random_info: the random info. 875 % 876 % o length: the key length. 877 % 878 % o key: the key. 879 % 880 */ 881 882 static inline void IncrementRandomNonce(StringInfo *nonce) 883 { 884 register ssize_t 885 i; 886 887 unsigned char 888 *datum; 889 890 datum=GetStringInfoDatum(nonce); 891 for (i=(ssize_t) (GetStringInfoLength(nonce)-1); i != 0; i--) 892 { 893 datum[i]++; 894 if (datum[i] != 0) 895 return; 896 } 897 ThrowFatalException(RandomFatalError,"SequenceWrapError"); 898 } 899 900 MagickExport void SetRandomKey(RandomInfo *random_info,const size_t length, 901 unsigned char *key) 902 { 903 register size_t 904 i; 905 906 register unsigned char 907 *p; 908 909 SignatureInfo 910 *signature_info; 911 912 unsigned char 913 *datum; 914 915 assert(random_info != (RandomInfo *) NULL); 916 if (length == 0) 917 return; 918 LockSemaphoreInfo(random_info->semaphore); 919 signature_info=random_info->signature_info; 920 datum=GetStringInfoDatum(random_info->reservoir); 921 i=length; 922 for (p=key; (i != 0) && (random_info->i != 0); i--) 923 { 924 *p++=datum[random_info->i]; 925 random_info->i++; 926 if (random_info->i == GetSignatureDigestsize(signature_info)) 927 random_info->i=0; 928 } 929 while (i >= GetSignatureDigestsize(signature_info)) 930 { 931 InitializeSignature(signature_info); 932 UpdateSignature(signature_info,random_info->nonce); 933 FinalizeSignature(signature_info); 934 IncrementRandomNonce(random_info->nonce); 935 (void) CopyMagickMemory(p,GetStringInfoDatum(GetSignatureDigest( 936 signature_info)),GetSignatureDigestsize(signature_info)); 937 p+=GetSignatureDigestsize(signature_info); 938 i-=GetSignatureDigestsize(signature_info); 939 } 940 if (i != 0) 941 { 942 InitializeSignature(signature_info); 943 UpdateSignature(signature_info,random_info->nonce); 944 FinalizeSignature(signature_info); 945 IncrementRandomNonce(random_info->nonce); 946 SetStringInfo(random_info->reservoir,GetSignatureDigest(signature_info)); 947 random_info->i=i; 948 datum=GetStringInfoDatum(random_info->reservoir); 949 while (i-- != 0) 950 p[i]=datum[i]; 951 } 952 UnlockSemaphoreInfo(random_info->semaphore); 953 } 954 955 /* 957 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 958 % % 959 % % 960 % % 961 % S e t R a n d o m S e c r e t K e y % 962 % % 963 % % 964 % % 965 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 966 % 967 % SetRandomSecretKey() sets the pseudo-random number generator secret key. 968 % 969 % The format of the SetRandomSecretKey method is: 970 % 971 % void SetRandomSecretKey(const unsigned long key) 972 % 973 % A description of each parameter follows: 974 % 975 % o key: the secret seed. 976 % 977 */ 978 MagickExport void SetRandomSecretKey(const unsigned long key) 979 { 980 secret_key=key; 981 } 982 983 /* 985 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 986 % % 987 % % 988 % % 989 % S e t R a n d o m T r u e R a n d o m % 990 % % 991 % % 992 % % 993 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 994 % 995 % SetRandomTrueRandom() declares your intentions to use true random numbers. 996 % True random numbers are encouraged but may not always be practical because 997 % your application may block while entropy is gathered from your environment. 998 % 999 % The format of the SetRandomTrueRandom method is: 1000 % 1001 % void SetRandomTrueRandom(const MagickBooleanType true_random) 1002 % 1003 % A description of each parameter follows: 1004 % 1005 % o true_random: declare your intentions to use true-random number. 1006 % 1007 */ 1008 MagickExport void SetRandomTrueRandom(const MagickBooleanType true_random) 1009 { 1010 gather_true_random=true_random; 1011 } 1012