Coverage Report

Created: 2026-06-30 07:12

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