MagickCore 7.0.10
random.c
Go to the documentation of this file.
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% Wizard's Toolkit Random Numbers Methods %
13% %
14% Software Design %
15% Cristy %
16% March 2003 %
17% %
18% %
19% Copyright 1999-2015 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% https://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%
36%
37*/
38
39/*
40 Include declarations.
41*/
42#if defined(__MINGW32__) || defined(__MINGW64__)
43#include <sys/time.h>
44#endif
45#include "wizard/studio.h"
46#include "wizard/entropy.h"
47#include "wizard/exception.h"
49#include "wizard/file.h"
50#include "wizard/hash.h"
51#include "wizard/magick.h"
52#include "wizard/memory_.h"
53#include "wizard/random_.h"
54#include "wizard/thread_.h"
56#include "wizard/semaphore.h"
58#if defined(WIZARDSTOOLKIT_HAVE_GETENTROPY)
59#include <sys/random.h>
60#endif
61
62/*
63 Define declarations.
64*/
65#define PseudoRandomHash SHA2256Hash
66#define RandomEntropyLevel 9
67#define RandomFilename "reservoir.xdm"
68#define RandomFiletype "random"
69#define RandomProtocolMajorVersion 1
70#define RandomProtocolMinorVersion 1
71
72/*
73 Typedef declarations.
74*/
76{
79
83
84 size_t
86
88 seed[4];
89
90 double
92
93 unsigned long
95
96 unsigned short
99
102
103 time_t
105
106 size_t
108};
109
110/*
111 External declarations.
112*/
113#if defined(__APPLE__) && !defined(TARGET_OS_IPHONE)
114#include <crt_externs.h>
115#define environ (*_NSGetEnviron())
116#endif
117
118extern char
119 **environ;
120
121/*
122 Global declarations.
123*/
124static SemaphoreInfo
126
127static unsigned long
129
132
133/*
134 Forward declarations.
135*/
138
139static StringInfo
142
143/*
144%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
145% %
146% %
147% %
148% A c q u i r e R a n d o m I n f o %
149% %
150% %
151% %
152%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
153%
154% AcquireRandomInfo() allocates the RandomInfo structure.
155%
156% The format of the AcquireRandomInfo method is:
157%
158% RandomInfo *AcquireRandomInfo(const RandomType hash)
159%
160% A description of each parameter follows:
161%
162% o hash: the hash type.
163%
164*/
166{
168 *exception;
169
172
174 status;
175
177 *entropy,
178 *key,
179 *nonce;
180
182 if (random_info == (RandomInfo *) NULL)
184 (void) memset(random_info,0,sizeof(*random_info));
192 random_info->normalize=(double) (1.0/(WizardULLConstant(~0) >> 11));
193 random_info->seed[0]=WizardULLConstant(0x76e15d3efefdcbbf);
194 random_info->seed[1]=WizardULLConstant(0xc5004e441c522fb3);
195 random_info->seed[2]=WizardULLConstant(0x77710069854ee241);
196 random_info->seed[3]=WizardULLConstant(0x39109bb02acbe635);
201 random_info->timestamp=time(0);
203 /*
204 Seed random nonce.
205 */
206 exception=AcquireExceptionInfo();
207 nonce=GenerateEntropicChaos(random_info,exception);
208 if (nonce == (StringInfo *) NULL)
209 ThrowFatalException(RandomFatalError,"Failed to initialize random "
210 "reservoir `%s'");
215 nonce=DestroyStringInfo(nonce);
216 /*
217 Seed random reservoir with entropic data.
218 */
219 entropy=GenerateEntropicChaos(random_info,exception);
220 if (entropy == (StringInfo *) NULL)
221 ThrowFatalException(RandomFatalError,"Failed to initialize random "
222 "reservoir `%s'");
225 status=SaveEntropyToReservoir(random_info,exception);
226 entropy=DestroyStringInfo(entropy);
227 exception=DestroyExceptionInfo(exception);
228 if (status == WizardFalse)
229 {
231 return((RandomInfo *) NULL);
232 }
233 /*
234 Seed pseudo random number generator.
235 */
236 if (random_info->secret_key == ~0UL)
237 {
239 (void) memcpy(random_info->seed,GetStringInfoDatum(key),
240 sizeof(random_info->seed));
241 key=DestroyStringInfo(key);
242 }
243 else
244 {
245 const StringInfo
246 *digest;
247
249 *signature_info;
250
251 signature_info=AcquireHashInfo(PseudoRandomHash);
253 SetStringInfoDatum(key,(unsigned char *) &random_info->secret_key);
254 (void) UpdateHash(signature_info,key);
255 key=DestroyStringInfo(key);
256 (void) FinalizeHash(signature_info);
257 digest=GetHashDigest(signature_info);
259 WizardMin((size_t) GetHashDigestsize(signature_info),
260 sizeof(random_info->seed)));
261 signature_info=DestroyHashInfo(signature_info);
262 }
263 return(random_info);
264}
265
266/*
267%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
268% %
269% %
270% %
271+ D e s t r o y R a n d o m I n f o %
272% %
273% %
274% %
275%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
276%
277% DestroyRandomInfo() deallocates memory associated with the random
278% reservoir.
279%
280% The format of the DestroyRandomInfo method is:
281%
282% RandomInfo *DestroyRandomInfo(RandomInfo *random_info)
283%
284% A description of each parameter follows:
285%
286% o random_info: the random info.
287%
288*/
290{
295 if (random_info->reservoir != (StringInfo *) NULL)
297 if (random_info->nonce != (StringInfo *) NULL)
299 if (random_info->hmac_info != (HMACInfo *) NULL)
301 (void) memset(random_info->seed,0,sizeof(*random_info->seed));
302 random_info->signature=(~WizardSignature);
306 return(random_info);
307}
308
309/*
310%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
311% %
312% %
313% %
314+ G e n e r a t e E n t r o p i c C h a o s %
315% %
316% %
317% %
318%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
319%
320% GenerateEntropicChaos() generate entropic chaos used to initialize the
321% random reservoir.
322%
323% The format of the GenerateEntropicChaos method is:
324%
325% StringInfo *GenerateEntropicChaos(RandomInfo *random_info,
326% ExceptionInfo *exception)
327%
328% A description of each parameter follows:
329%
330% o random_info: the random info.
331%
332% o exception: Return any errors or warnings in this structure.
333%
334*/
335
336static ssize_t ReadRandom(int file,unsigned char *source,size_t length)
337{
338 unsigned char
339 *q;
340
341 ssize_t
342 offset,
343 count;
344
345 offset=0;
346 for (q=source; length != 0; length-=count)
347 {
348 count=(ssize_t) read(file,q,length);
349 if (count <= 0)
350 {
351 count=0;
352 if (errno == EINTR)
353 continue;
354 return(-1);
355 }
356 q+=count;
357 offset+=count;
358 }
359 return(offset);
360}
361
363 ExceptionInfo *exception)
364{
365#define MaxEntropyExtent 64 /* max permitted: 256 */
366
367 ssize_t
368 pid;
369
371 *chaos,
372 *entropy;
373
374 size_t
375 nanoseconds,
376 seconds;
377
379 tid;
380
381 /*
382 Initialize random reservoir.
383 */
384 entropy=GetEntropyFromReservoir(random_info,exception);
385 if (entropy == (StringInfo *) NULL)
386 entropy=AcquireStringInfo(0);
388#if defined(WIZARDSTOOLKIT_HAVE_GETENTROPY)
389 {
390 int
391 status;
392
394 status=getentropy(GetStringInfoDatum(entropy),MaxEntropyExtent);
395 if (status == 0)
396 {
398 return(entropy);
399 }
400 }
401#endif
402 chaos=AcquireStringInfo(sizeof(unsigned char *));
403 SetStringInfoDatum(chaos,(unsigned char *) &entropy);
404 ConcatenateStringInfo(entropy,chaos);
405 SetStringInfoDatum(chaos,(unsigned char *) entropy);
406 ConcatenateStringInfo(entropy,chaos);
407 pid=(ssize_t) getpid();
408 SetStringInfoLength(chaos,sizeof(pid));
409 SetStringInfoDatum(chaos,(unsigned char *) &pid);
410 ConcatenateStringInfo(entropy,chaos);
411 tid=GetWizardThreadId();
412 SetStringInfoLength(chaos,sizeof(tid));
413 SetStringInfoDatum(chaos,(unsigned char *) &tid);
414 ConcatenateStringInfo(entropy,chaos);
415#if defined(WIZARDSTOOLKIT_SYSCONF) && defined(_SC_PHYS_PAGES)
416 {
417 ssize_t
418 pages;
419
420 pages=(ssize_t) sysconf(_SC_PHYS_PAGES);
421 SetStringInfoLength(chaos,sizeof(pages));
422 SetStringInfoDatum(chaos,(unsigned char *) &pages);
423 ConcatenateStringInfo(entropy,chaos);
424 }
425#endif
426#if defined(WIZARDSTOOLKIT_HAVE_GETRUSAGE) && defined(RUSAGE_SELF)
427 {
428 struct rusage
429 usage;
430
431 if (getrusage(RUSAGE_SELF,&usage) == 0)
432 {
433 SetStringInfoLength(chaos,sizeof(usage));
434 SetStringInfoDatum(chaos,(unsigned char *) &usage);
435 }
436 }
437#endif
438 seconds=time((time_t *) 0);
439 nanoseconds=0;
440#if defined(WIZARDSTOOLKIT_HAVE_GETTIMEOFDAY)
441 {
442 struct timeval
443 timer;
444
445 if (gettimeofday(&timer,(struct timezone *) NULL) == 0)
446 {
447 seconds=(size_t) timer.tv_sec;
448 nanoseconds=(size_t) (1000UL*timer.tv_usec);
449 }
450 }
451#endif
452#if defined(WIZARDSTOOLKIT_HAVE_CLOCK_GETTIME) && defined(CLOCK_REALTIME_HR)
453 {
454 struct timespec
455 timer;
456
457 if (clock_gettime(CLOCK_REALTIME_HR,&timer) == 0)
458 {
459 seconds=timer.tv_sec;
460 nanoseconds=timer.tv_nsec;
461 }
462 }
463#endif
464 SetStringInfoLength(chaos,sizeof(seconds));
465 SetStringInfoDatum(chaos,(unsigned char *) &seconds);
466 ConcatenateStringInfo(entropy,chaos);
467 SetStringInfoLength(chaos,sizeof(nanoseconds));
468 SetStringInfoDatum(chaos,(unsigned char *) &nanoseconds);
469 ConcatenateStringInfo(entropy,chaos);
470 nanoseconds=0;
471#if defined(WIZARDSTOOLKIT_HAVE_CLOCK)
472 nanoseconds=clock();
473#endif
474#if defined(WIZARDSTOOLKIT_HAVE_TIMES)
475 {
476 struct tms
477 timer;
478
479 (void) times(&timer);
480 nanoseconds=timer.tms_utime+timer.tms_stime;
481 }
482#endif
483 SetStringInfoLength(chaos,sizeof(nanoseconds));
484 SetStringInfoDatum(chaos,(unsigned char *) &nanoseconds);
485 ConcatenateStringInfo(entropy,chaos);
486#if defined(WIZARDSTOOLKIT_WINDOWS_SUPPORT)
487 {
488 double
489 seconds;
490
491 LARGE_INTEGER
492 nanoseconds;
493
495 status;
496
497 /*
498 Not crytographically strong but better than nothing.
499 */
500 seconds=NTElapsedTime()+NTUserTime();
501 SetStringInfoLength(chaos,sizeof(seconds));
502 SetStringInfoDatum(chaos,(unsigned char *) &seconds);
503 ConcatenateStringInfo(entropy,chaos);
504 if (QueryPerformanceCounter(&nanoseconds) != 0)
505 {
506 SetStringInfoLength(chaos,sizeof(nanoseconds));
507 SetStringInfoDatum(chaos,(unsigned char *) &nanoseconds);
508 ConcatenateStringInfo(entropy,chaos);
509 }
510 /*
511 Our best hope for true entropy.
512 */
514 status=NTGatherRandomData(MaxEntropyExtent,GetStringInfoDatum(chaos));
515 if (status == WizardFalse)
517 "unable to gather random data: %s",strerror(errno));
518 ConcatenateStringInfo(entropy,chaos);
519 }
520#else
521 {
522 char
523 *filename;
524
525 int
526 file;
527
528 ssize_t
529 count;
530
532 *device;
533
534 /*
535 Not crytographically strong but better than nothing.
536 */
537 if (environ != (char **) NULL)
538 {
539 ssize_t
540 i;
541
542 /*
543 Squeeze some entropy from the sometimes unpredicatble environment.
544 */
545 for (i=0; environ[i] != (char *) NULL; i++)
546 {
547 SetStringInfoLength(chaos,strlen(environ[i]));
548 SetStringInfoDatum(chaos,(unsigned char *) environ[i]);
549 ConcatenateStringInfo(entropy,chaos);
550 }
551 }
552 filename=AcquireString("/dev/urandom");
553 device=StringToStringInfo(filename);
554 if (GetStringInfoCRC(device) != (WizardSizeType) 0xf9f0014228f2264fll)
555 ThrowFatalException(RandomFatalError,"random device error `%s'");
556 device=DestroyStringInfo(device);
557 file=open_utf8(filename,O_RDONLY | O_BINARY,0);
558 filename=DestroyString(filename);
559 if (file != -1)
560 {
563 if (close(file) == -1)
565 "unable to close file `%s': %s",filename,strerror(errno));
566 SetStringInfoLength(chaos,(size_t) count);
567 ConcatenateStringInfo(entropy,chaos);
568 }
570 {
571 /*
572 Our best hope for true entropy.
573 */
574 filename=AcquireString("/dev/random");
575 device=StringToStringInfo(filename);
576 if (GetStringInfoCRC(device) != (WizardSizeType) 0xc36e1cc17bf25fd4ll)
577 ThrowFatalException(RandomFatalError,"random device error `%s'");
578 device=DestroyStringInfo(device);
579 file=open_utf8(filename,O_RDONLY | O_BINARY,0);
580 filename=DestroyString(filename);
581 if (file == -1)
582 {
583 filename=AcquireString("/dev/srandom");
584 device=StringToStringInfo(filename);
585 if (GetStringInfoCRC(device) != (WizardSizeType)
586 0xf9f0014228f223efll)
587 ThrowFatalException(RandomFatalError,"random device error `%s'");
588 device=DestroyStringInfo(device);
589 file=open_utf8(filename,O_RDONLY | O_BINARY,0);
590 }
591 if (file != -1)
592 {
595 if (close(file) == -1)
596 (void) ThrowWizardException(exception,GetWizardModule(),
597 RandomError,"unable to close file `%s': %s",filename,
598 strerror(errno));
599 SetStringInfoLength(chaos,(size_t) count);
600 ConcatenateStringInfo(entropy,chaos);
601 }
602 }
603 }
604#endif
605 chaos=DestroyStringInfo(chaos);
606 {
607 const StringInfo
608 *chaos;
609
611 *entropy_info;
612
613 /*
614 Estimate entropy.
615 */
617 (void) IncreaseEntropy(entropy_info,entropy,exception);
618 chaos=GetEntropyChaos(entropy_info);
619 if (GetStringInfoLength(entropy) < (GetStringInfoLength(chaos)/2))
620 ThrowFatalException(RandomFatalError,"not enough entropy to continue "
621 "`%s'");
622 entropy_info=DestroyEntropyInfo(entropy_info);
623 }
625 return(entropy);
626}
627
628/*
629%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
630% %
631% %
632% %
633% G e t E n t r o p y F r o m R e s e r v i o r %
634% %
635% %
636% %
637%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
638%
639% GetEntropyFromReservoir() gets entropy from the random reservoir on disk.
640%
641% The format of the GetEntropyFromReservoir method is:
642%
643% StringInfo *GetEntropyFromReservoir(RandomInfo *random_info,
644% ExceptionInfo *exception)
645%
646% A description of each parameter follows:
647%
648% o random_info: the random reservoir info.
649%
650% o exception: Return any errors or warnings in this structure.
651%
652*/
654 ExceptionInfo *exception)
655{
657 *file_info;
658
660 status;
661
663 *entropy,
664 *filetype,
665 *magick,
666 *target;
667
668 size_t
669 length;
670
672 crc;
673
677 WizardAssert(CipherDomain,exception != (ExceptionInfo *) NULL);
679 file_info=AcquireFileInfo((const char *) NULL,RandomFilename,ReadFileMode,
680 exception);
681 if (file_info == (FileInfo *) NULL)
682 {
684 return((StringInfo *) NULL);
685 }
687 target=CloneStringInfo(magick);
688 status=ReadFileChunk(file_info,GetStringInfoDatum(target),
689 GetStringInfoLength(target));
690 if ((status == WizardFalse) || (CompareStringInfo(target,magick) != 0))
691 {
692 file_info=DestroyFileInfo(file_info,exception);
694 "corrupt random reservoir file `%s'",GetFilePath(file_info));
696 return((StringInfo *) NULL);
697 }
698 magick=DestroyStringInfo(magick);
699 target=DestroyStringInfo(target);
700 filetype=GetWizardMagick((unsigned char *) RandomFiletype,strlen(
702 target=CloneStringInfo(filetype);
703 status&=ReadFileChunk(file_info,GetStringInfoDatum(target),
704 GetStringInfoLength(target));
705 if ((status == WizardFalse) || (CompareStringInfo(target,filetype) != 0))
706 {
707 filetype=DestroyStringInfo(filetype);
708 target=DestroyStringInfo(target);
709 file_info=DestroyFileInfo(file_info,exception);
711 "corrupt random reservoir file `%s'",GetFilePath(file_info));
713 return((StringInfo *) NULL);
714 }
715 filetype=DestroyStringInfo(filetype);
716 target=DestroyStringInfo(target);
717 status&=ReadFile16Bits(file_info,&random_info->protocol_major);
718 status&=ReadFile16Bits(file_info,&random_info->protocol_minor);
720 {
722 timestamp;
723
724 status&=ReadFile64Bits(file_info,&timestamp);
725 random_info->timestamp=(time_t) timestamp;
726 }
727 status&=ReadFile32Bits(file_info,&length);
728 if (status == WizardFalse)
729 {
730 file_info=DestroyFileInfo(file_info,exception);
732 "corrupt random reservoir file `%s'",GetFilePath(file_info));
734 return((StringInfo *) NULL);
735 }
736 entropy=AcquireStringInfo(length);
737 status&=ReadFileChunk(file_info,GetStringInfoDatum(entropy),
738 GetStringInfoLength(entropy));
739 crc=0;
740 status&=ReadFile64Bits(file_info,&crc);
741 if ((status == WizardFalse) || (crc != GetStringInfoCRC(entropy)))
742 {
743 entropy=DestroyStringInfo(entropy);
745 "corrupt random reservoir file `%s'",GetFilePath(file_info));
746 file_info=DestroyFileInfo(file_info,exception);
748 return((StringInfo *) NULL);
749 }
750 file_info=DestroyFileInfo(file_info,exception);
752 return(entropy);
753}
754
755/*
756%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
757% %
758% %
759% %
760% G e t P s e u d o R a n d o m V a l u e %
761% %
762% %
763% %
764%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
765%
766% GetPseudoRandomValue() is a Xoshiro generator that returns a non-negative
767% double-precision floating-point value uniformly distributed over the
768% interval [0.0, 1.0) with a 2 to the 256th-1 period.
769%
770% The format of the GetPseudoRandomValue method is:
771%
772% double GetPseudoRandomValue(RandomInfo *randon_info)
773%
774% A description of each parameter follows:
775%
776% o random_info: the random info.
777%
778*/
780{
781#define RandomROTL(x,k) (((x) << (k)) | ((x) >> (64-(k))))
782
783 const WizardSizeType
784 alpha = (random_info->seed[1] << 17),
785 value = (random_info->seed[0]+random_info->seed[3]);
786
791 random_info->seed[2]^=alpha;
793 return((double) ((value >> 11)*random_info->normalize));
794}
795
796/*
797%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
798% %
799% %
800% %
801% G e t R a n d o m K e y %
802% %
803% %
804% %
805%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
806%
807% GetRandomKey() gets a random key from the reservoir.
808%
809% The format of the GetRandomKey method is:
810%
811% StringInfo *GetRandomKey(RandomInfo *random_info,const size_t length)
812%
813% A description of each parameter follows:
814%
815% o random_info: the random info.
816%
817% o length: the key length.
818%
819*/
821 const size_t length)
822{
824 *key;
825
827 key=AcquireStringInfo(length);
829 return(key);
830}
831
832/*
833%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
834% %
835% %
836% %
837% G e t R a n d o m S e c r e t K e y %
838% %
839% %
840% %
841%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
842%
843% GetRandomSecretKey() returns the random secet key.
844%
845% The format of the GetRandomSecretKey method is:
846%
847% unsigned long GetRandomSecretKey(const RandomInfo *random_info)
848%
849% A description of each parameter follows:
850%
851% o random_info: the random info.
852*/
854{
855 return(random_info->secret_key);
856}
857
858/*
859%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
860% %
861% %
862% %
863% G e t R a n d o m V a l u e %
864% %
865% %
866% %
867%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
868%
869% GetRandomValue() return a non-negative double-precision floating-point
870% value uniformly distributed over the interval [0.0, 1.0) with a 2 to the
871% 128th-1 period (not cryptographically strong).
872%
873% The format of the GetRandomValue method is:
874%
875% double GetRandomValue(void)
876%
877*/
879{
880 unsigned long
881 key,
882 range;
883
884 range=(~0UL);
885 do
886 {
887 SetRandomKey(random_info,sizeof(key),(unsigned char *) &key);
888 } while (key == range);
889 return((double) key/range);
890}
891
892/*
893%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
894% %
895% %
896% %
897+ R a n d o m C o m p o n e n t G e n e s i s %
898% %
899% %
900% %
901%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
902%
903% RandomComponentGenesis() instantiates the random component.
904%
905% The format of the RandomComponentGenesis method is:
906%
907% RandomComponentGenesis(void)
908%
909*/
911{
912 if (random_semaphore == (SemaphoreInfo *) NULL)
914 return(WizardTrue);
915}
916
917/*
918%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
919% %
920% %
921% %
922+ R a n d o m C o m p o n e n t T e r m i n u s %
923% %
924% %
925% %
926%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
927%
928% RandomComponentTerminus() destroys the random component.
929%
930% The format of the RandomComponentTerminus method is:
931%
932% RandomComponentTerminus(void)
933%
934*/
936{
937 if (random_semaphore == (SemaphoreInfo *) NULL)
940}
941
942/*
943%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
944% %
945% %
946% %
947% S a v e E n t r o p y T o R e s e r v o i r %
948% %
949% %
950% %
951%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
952%
953% SaveEntropyToReservoir() saves entropy to the reservior on disk.
954%
955% The format of the SaveEntropyToReservoir method is:
956%
957% WizardBooleanType SaveEntropyToReservoir(RandomInfo *random_info,
958% ExceptionInfo *exception)
959%
960% A description of each parameter follows:
961%
962% o random_info: the random info.
963%
964% o exception: Return any errors or warnings in this structure.
965%
966*/
968 ExceptionInfo *exception)
969{
971 *file_info;
972
974 status;
975
976 size_t
977 length;
978
980 *filetype,
981 *magick;
982
986 WizardAssert(CipherDomain,exception != (ExceptionInfo *) NULL);
988 file_info=AcquireFileInfo((const char *) NULL,RandomFilename,WriteFileMode,
989 exception);
990 if (file_info == (FileInfo *) NULL)
991 {
993 return(WizardFalse);
994 }
996 status=WriteFileChunk(file_info,GetStringInfoDatum(magick),
997 GetStringInfoLength(magick));
998 magick=DestroyStringInfo(magick);
999 filetype=GetWizardMagick((unsigned char *) RandomFiletype,strlen(
1001 status&=WriteFileChunk(file_info,GetStringInfoDatum(filetype),
1002 GetStringInfoLength(filetype));
1003 filetype=DestroyStringInfo(filetype);
1004 status&=WriteFile16Bits(file_info,random_info->protocol_major);
1005 status&=WriteFile16Bits(file_info,random_info->protocol_minor);
1008 status&=WriteFile32Bits(file_info,length);
1010 random_info->hmac_info)),length);
1013 if (status == WizardFalse)
1015 "unable to write random reservior `%s': %s",GetFilePath(file_info),
1016 strerror(errno));
1017 file_info=DestroyFileInfo(file_info,exception);
1019 return(WizardTrue);
1020}
1021
1022/*
1023%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1024% %
1025% %
1026% %
1027% S e t R a n d o m K e y %
1028% %
1029% %
1030% %
1031%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1032%
1033% SetRandomKey() sets a random key from the reservoir.
1034%
1035% The format of the SetRandomKey method is:
1036%
1037% void SetRandomKey(RandomInfo *random_info,const size_t length,
1038% unsigned char *key)
1039%
1040% A description of each parameter follows:
1041%
1042% o random_info: the random info.
1043%
1044% o length: the key length.
1045%
1046% o key: the key.
1047%
1048*/
1049
1050static inline void IncrementRandomNonce(StringInfo *nonce)
1051{
1052 ssize_t
1053 i;
1054
1055 unsigned char
1056 *datum;
1057
1058 datum=GetStringInfoDatum(nonce);
1059 for (i=(ssize_t) (GetStringInfoLength(nonce)-1); i != 0; i--)
1060 {
1061 datum[i]++;
1062 if (datum[i] != 0)
1063 return;
1064 }
1065 ThrowFatalException(RandomFatalError,"Sequence wrap error `%s'");
1066}
1067
1069 unsigned char *key)
1070{
1071 HMACInfo
1072 *hmac_info;
1073
1074 size_t
1075 i;
1076
1077 unsigned char
1078 *p;
1079
1080 unsigned char
1081 *datum;
1082
1084 if (length == 0)
1085 return;
1087 i=length;
1088 hmac_info=random_info->hmac_info;
1090 for (p=key; (i != 0) && (random_info->i != 0); i--)
1091 {
1092 *p++=datum[random_info->i];
1093 random_info->i++;
1094 if (random_info->i == GetHMACDigestsize(hmac_info))
1095 random_info->i=0;
1096 }
1097 while (i >= GetHMACDigestsize(hmac_info))
1098 {
1099 ResetHMAC(hmac_info);
1100 UpdateHMAC(hmac_info,random_info->nonce);
1101 FinalizeHMAC(hmac_info);
1104 GetHMACDigestsize(hmac_info));
1105 p+=GetHMACDigestsize(hmac_info);
1106 i-=GetHMACDigestsize(hmac_info);
1107 }
1108 if (i != 0)
1109 {
1110 ResetHMAC(hmac_info);
1111 UpdateHMAC(hmac_info,random_info->nonce);
1112 FinalizeHMAC(hmac_info);
1115 random_info->i=i;
1117 while (i-- != 0)
1118 p[i]=datum[i];
1119 }
1121}
1122
1123/*
1124%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1125% %
1126% %
1127% %
1128% S e t R a n d o m S e c r e t K e y %
1129% %
1130% %
1131% %
1132%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1133%
1134% SetRandomSecretKey() sets the pseudo-random number generator secret key.
1135%
1136% The format of the SetRandomSecretKey method is:
1137%
1138% void SetRandomSecretKey(const unsigned long key)
1139%
1140% A description of each parameter follows:
1141%
1142% o key: the secret key.
1143%
1144*/
1145WizardExport void SetRandomSecretKey(const unsigned long key)
1146{
1147 secret_key=key;
1148}
1149
1150/*
1151%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1152% %
1153% %
1154% %
1155% S e t R a n d o m T r u e R a n d o m %
1156% %
1157% %
1158% %
1159%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1160%
1161% SetRandomTrueRandom() declares your intentions to use true random numbers.
1162% True random numbers are encouraged but may not always be practical because
1163% your application may block while entropy is gathered from your environment.
1164%
1165% The format of the SetRandomTrueRandom method is:
1166%
1167% void SetRandomTrueRandom(const WizardBooleanType true_random)
1168%
1169% A description of each parameter follows:
1170%
1171% o true_random: declare your intentions to use true-random number.
1172%
1173*/
1175{
1176 gather_true_random=true_random;
1177}
WizardExport EntropyInfo * AcquireEntropyInfo(const EntropyType entropy, const size_t level)
Definition entropy.c:95
WizardExport EntropyInfo * DestroyEntropyInfo(EntropyInfo *entropy_info)
Definition entropy.c:154
WizardExport WizardBooleanType IncreaseEntropy(EntropyInfo *entropy_info, const StringInfo *message, ExceptionInfo *exception)
Definition entropy.c:283
WizardExport const StringInfo * GetEntropyChaos(const EntropyInfo *entropy_info)
Definition entropy.c:210
@ ZIPEntropy
Definition entropy.h:32
#define WizardAssert(domain, predicate)
#define ThrowWizardFatalError(domain, error)
#define ThrowFatalException(severity, tag)
WizardExport ExceptionInfo * AcquireExceptionInfo(void)
Definition exception.c:125
WizardExport ExceptionInfo * DestroyExceptionInfo(ExceptionInfo *exception)
Definition exception.c:399
WizardExport WizardBooleanType ThrowWizardException(ExceptionInfo *exception, const char *module, const char *function, const size_t line, const ExceptionType severity, const char *format,...)
Definition exception.c:1029
@ HashDomain
Definition exception.h:30
@ CipherDomain
Definition exception.h:34
@ RandomFatalError
Definition exception.h:104
@ RandomError
Definition exception.h:84
@ MemoryError
Definition exception.h:49
WizardExport WizardBooleanType ReadFile64Bits(FileInfo *file_info, WizardSizeType *value)
Definition file.c:754
WizardExport const char * GetFilePath(const FileInfo *file_info)
Definition file.c:505
static size_t GetWizardThreadId(void)
Definition file.c:116
WizardExport FileInfo * AcquireFileInfo(const char *path, const char *relative_path, const FileMode mode, ExceptionInfo *exception)
Definition file.c:257
WizardExport WizardBooleanType WriteFile32Bits(FileInfo *file_info, const size_t value)
Definition file.c:943
WizardExport WizardBooleanType WriteFile64Bits(FileInfo *file_info, const WizardSizeType value)
Definition file.c:984
WizardExport WizardBooleanType WriteFile16Bits(FileInfo *file_info, const unsigned short value)
Definition file.c:904
WizardExport WizardBooleanType ReadFileChunk(FileInfo *file_info, void *data, const size_t length)
Definition file.c:606
WizardExport WizardBooleanType WriteFileChunk(FileInfo *file_info, const void *data, const size_t length)
Definition file.c:851
WizardExport WizardBooleanType ReadFile32Bits(FileInfo *file_info, size_t *value)
Definition file.c:706
WizardExport FileInfo * DestroyFileInfo(FileInfo *file_info, ExceptionInfo *exception)
Definition file.c:431
WizardExport WizardBooleanType ReadFile16Bits(FileInfo *file_info, unsigned short *value)
Definition file.c:660
@ WriteFileMode
Definition file.h:30
@ ReadFileMode
Definition file.h:29
WizardExport HashInfo * AcquireHashInfo(const HashType hash)
Definition hash.c:99
WizardExport WizardBooleanType UpdateHash(HashInfo *hash_info, const StringInfo *message)
Definition hash.c:849
WizardExport HashInfo * DestroyHashInfo(HashInfo *hash_info)
Definition hash.c:231
WizardExport const StringInfo * GetHashDigest(const HashInfo *hash_info)
Definition hash.c:568
WizardExport size_t GetHashDigestsize(const HashInfo *hash_info)
Definition hash.c:598
WizardExport WizardBooleanType FinalizeHash(HashInfo *hash_info)
Definition hash.c:324
HashType
Definition hash.h:28
WizardExport void FinalizeHMAC(HMACInfo *hmac_info)
Definition hmac.c:214
WizardExport HMACInfo * AcquireHMACInfo(const HashType hash)
Definition hmac.c:91
WizardExport const StringInfo * GetHMACDigest(const HMACInfo *hmac_info)
Definition hmac.c:250
WizardExport void UpdateHMAC(HMACInfo *hmac_info, const StringInfo *message)
Definition hmac.c:399
WizardExport HMACInfo * DestroyHMACInfo(HMACInfo *hmac_info)
Definition hmac.c:174
WizardExport void InitializeHMAC(HMACInfo *hmac_info, const StringInfo *key)
Definition hmac.c:312
WizardExport size_t GetHMACDigestsize(const HMACInfo *hmac_info)
Definition hmac.c:280
WizardExport void ResetHMAC(HMACInfo *hmac_info)
Definition hmac.c:366
WizardBooleanType LogWizardEvent(const LogEventType type, const char *module, const char *function, const size_t line, const char *format,...)
Definition log.c:1390
@ TraceEvent
Definition log.h:39
#define GetWizardModule()
Definition log.h:30
WizardExport StringInfo * GetWizardMagick(const unsigned char *signature, const size_t length)
Definition magick.c:88
unsigned char WizardMagick[4]
Definition magick.c:56
WizardExport void * AcquireWizardMemory(const size_t size)
Definition memory.c:586
WizardExport void * CopyWizardMemory(void *destination, const void *source, const size_t size)
Definition memory.c:700
WizardExport void * RelinquishWizardMemory(void *memory)
Definition memory.c:1039
#define WizardExport
#define WizardSignature
WizardExport RandomInfo * AcquireRandomInfo(const HashType hash)
Definition random.c:165
WizardExport void SetRandomKey(RandomInfo *random_info, const size_t length, unsigned char *key)
Definition random.c:1068
WizardExport double GetPseudoRandomValue(RandomInfo *random_info)
Definition random.c:779
#define PseudoRandomHash
Definition random.c:65
static SemaphoreInfo * random_semaphore
Definition random.c:125
#define RandomProtocolMinorVersion
Definition random.c:70
#define RandomROTL(x, k)
static StringInfo * GenerateEntropicChaos(RandomInfo *, ExceptionInfo *)
Definition random.c:362
#define RandomProtocolMajorVersion
Definition random.c:69
WizardExport StringInfo * GetRandomKey(RandomInfo *random_info, const size_t length)
Definition random.c:820
#define RandomFiletype
Definition random.c:68
#define RandomEntropyLevel
Definition random.c:66
static StringInfo * GetEntropyFromReservoir(RandomInfo *, ExceptionInfo *)
Definition random.c:653
WizardExport RandomInfo * DestroyRandomInfo(RandomInfo *random_info)
Definition random.c:289
static void IncrementRandomNonce(StringInfo *nonce)
Definition random.c:1050
WizardExport double GetRandomValue(RandomInfo *random_info)
Definition random.c:878
WizardExport WizardBooleanType RandomComponentGenesis(void)
Definition random.c:910
char ** environ
WizardExport void RandomComponentTerminus(void)
Definition random.c:935
static unsigned long secret_key
Definition random.c:128
#define RandomFilename
Definition random.c:67
#define MaxEntropyExtent
static WizardBooleanType gather_true_random
Definition random.c:131
WizardExport void SetRandomSecretKey(const unsigned long key)
Definition random.c:1145
static ssize_t ReadRandom(int file, unsigned char *source, size_t length)
Definition random.c:336
WizardExport unsigned long GetRandomSecretKey(const RandomInfo *random_info)
Definition random.c:853
WizardExport void SetRandomTrueRandom(const WizardBooleanType true_random)
Definition random.c:1174
static WizardBooleanType SaveEntropyToReservoir(RandomInfo *, ExceptionInfo *)
Definition random.c:967
static RandomInfo * random_info
Definition resource.c:89
WizardExport void RelinquishSemaphoreInfo(SemaphoreInfo **semaphore_info)
Definition semaphore.c:338
WizardExport SemaphoreInfo * AcquireSemaphoreInfo(void)
Definition semaphore.c:156
WizardExport void LockSemaphoreInfo(SemaphoreInfo *semaphore_info)
Definition semaphore.c:282
WizardExport void UnlockSemaphoreInfo(SemaphoreInfo *semaphore_info)
Definition semaphore.c:437
WizardExport void ActivateSemaphoreInfo(SemaphoreInfo **semaphore_info)
Definition semaphore.c:247
WizardExport WizardSizeType GetStringInfoCRC(const StringInfo *string_info)
Definition string.c:1210
WizardExport void SetStringInfoLength(StringInfo *string_info, const size_t length)
Definition string.c:1865
WizardExport void SetStringInfo(StringInfo *string_info, const StringInfo *source)
Definition string.c:1792
WizardExport char * DestroyString(char *string)
Definition string.c:830
WizardExport size_t GetStringInfoLength(const StringInfo *string_info)
Definition string.c:1280
WizardExport StringInfo * AcquireStringInfo(const size_t length)
Definition string.c:179
WizardExport int CompareStringInfo(const StringInfo *target, const StringInfo *source)
Definition string.c:372
WizardExport StringInfo * CloneStringInfo(const StringInfo *string_info)
Definition string.c:332
WizardExport char * AcquireString(const char *source)
Definition string.c:133
WizardExport void SetStringInfoDatum(StringInfo *string_info, const unsigned char *source)
Definition string.c:1832
WizardExport void ConcatenateStringInfo(StringInfo *string_info, const StringInfo *source)
Definition string.c:704
WizardExport unsigned char * GetStringInfoDatum(const StringInfo *string_info)
Definition string.c:1251
WizardExport void ResetStringInfo(StringInfo *string_info)
Definition string.c:1761
WizardExport StringInfo * StringToStringInfo(const char *string)
Definition string.c:2199
WizardExport StringInfo * DestroyStringInfo(StringInfo *string_info)
Definition string.c:857
StringInfo * reservoir
Definition random.c:82
size_t signature
Definition random.c:107
HMACInfo * hmac_info
Definition random.c:78
double normalize
Definition random.c:91
unsigned short protocol_minor
Definition random.c:98
unsigned short protocol_major
Definition random.c:97
StringInfo * nonce
Definition random.c:81
unsigned long secret_key
Definition random.c:94
time_t timestamp
Definition random.c:104
SemaphoreInfo * semaphore
Definition random.c:101
WizardSizeType seed[4]
Definition random.c:88
size_t i
Definition random.c:85
#define O_BINARY
Definition studio.h:326
pid_t WizardThreadType
Definition thread_.h:30
static int open_utf8(const char *path, int flags, mode_t mode)
#define WizardMin(x, y)
#define WizardULLConstant(c)
Definition wizard-type.h:36
size_t WizardSizeType
Definition wizard-type.h:51
WizardBooleanType
Definition wizard-type.h:26
@ WizardTrue
Definition wizard-type.h:28
@ WizardFalse
Definition wizard-type.h:27
unsigned int WizardStatusType
Definition wizard-type.h:42