2 * Written in 2012 by Gregor Pintar <grpintar@gmail.com>
4 * To the extent possible under law, the author(s) have dedicated
5 * all copyright and related and neighboring rights to this software
6 * to the public domain worldwide.
8 * This software is distributed without any warranty.
10 * You should have received a copy of the CC0 Public Domain Dedication.
11 * If not, see <http://creativecommons.org/publicdomain/zero/1.0/>.
16 #if defined(KRIPTO_UNIX)
18 #ifndef KRIPTO_DEV_RANDOM
19 #define KRIPTO_DEV_RANDOM "/dev/urandom"
25 #elif defined(KRIPTO_WINDOWS)
27 #if !defined(KRIPTO_RTLGENRANDOM) && !defined(KRIPTO_CRYPTGENRANDOM)
28 #define KRIPTO_RTLGENRANDOM
33 #if defined(KRIPTO_RTLGENRANDOM)
40 #elif defined(KRIPTO_CRYPTGENRANDOM)
46 #ifndef KRIPTO_RESEED_OUTPUT
47 #define KRIPTO_RESEED_OUTPUT 5242880 /* 5MB */
50 #ifndef KRIPTO_RESEED_TIME
51 #define KRIPTO_RESEED_TIME 300 /* 5 min */
59 #include <sys/resource.h>
62 #include <kripto/memwipe.h>
63 #include <kripto/stream.h>
64 #include <kripto/scrypt.h>
65 #include <kripto/stream/chacha.h>
66 #include <kripto/mac.h>
67 #include <kripto/mac.h>
68 #include <kripto/mac/hmac.h>
69 #include <kripto/hash.h>
70 #include <kripto/hash/blake2s.h>
74 kripto_stream
*stream
;
86 #include <kripto/random.h>
88 #if !defined(KRIPTO_WINDOWS) && !defined(KRIPTO_UNIX)
90 static int seed(kripto_random
*s
, uint8_t *out
, unsigned int len
)
94 #if defined(KRIPTO_UNIX)
102 uint8_t unassigned
[4];
105 s
->mac
= kripto_mac_hmac(kripto_hash_blake2s
);
106 if(!s
->mac
) return -1;
108 #if defined(KRIPTO_UNIX)
109 entropy
.pid
= getpid();
110 (void)clock_gettime(CLOCK_REALTIME
, &entropy
.time
);
111 (void)getrusage(RUSAGE_SELF
, &entropy
.usage
);
113 entropy
.time
= time(NULL
);
114 entropy
.clock
= clock();
121 &entropy
, sizeof(entropy
),
126 memcpy(entropy
.unassigned
, &s
, 4);
128 #if defined(KRIPTO_UNIX)
129 (void)clock_gettime(CLOCK_REALTIME
, &entropy
.time
);
130 (void)getrusage(RUSAGE_SELF
, &entropy
.usage
);
132 entropy
.time
= time(NULL
);
133 entropy
.clock
= clock();
140 &entropy
, sizeof(entropy
),
145 kripto_memwipe(&entropy
, sizeof(entropy
));
148 s
->time
= time(NULL
);
153 static kripto_random
*create(void)
158 s
= malloc(sizeof(kripto_random
));
161 if(seed(s
, buf
, 32)) goto err
;
163 s
->stream
= kripto_stream_create
165 kripto_stream_chacha
, 0,
169 if(!s
->stream
) goto err
;
180 kripto_random
*kripto_random_create(void)
182 #if defined(KRIPTO_DEV_RANDOM)
184 const char *dev_random
;
187 dev_random
= getenv("KRIPTO_RANDOM");
189 #ifdef KRIPTO_DEV_RANDOM
190 dev_random
= KRIPTO_DEV_RANDOM
;
195 return (kripto_random
*)fopen(dev_random
, "rb");
197 /*fp = fopen(dev_random, "rb");
198 if(fp) return (kripto_random *)fp;
199 else return create();*/
201 #elif defined(KRIPTO_RTLGENRANDOM)
205 s
= malloc(sizeof(kripto_random
));
208 s
->lib
= LoadLibrary("advapi32.dll");
215 s
->rtlgenrandom
= GetProcAddress(s
->lib
, "SystemFunction036");
225 #elif defined(KRIPTO_CRYPTGENRANDOM)
226 #if sizeof(kripto_random *) < sizeof(HCRYPTPROV)
227 #error sizeof(kripto_random *) < sizeof(HCRYPTPROV)
232 if(!CryptAcquireContext
238 CRYPT_VERIFYCONTEXT
| CRYPT_SILENT
241 return (kripto_random
*)prov
;
250 size_t kripto_random_gen(kripto_random
*s
, void *out
, size_t len
)
254 #if defined(KRIPTO_DEV_RANDOM)
256 return fread(out
, sizeof(char), len
, (FILE *)s
);
258 #elif defined(KRIPTO_RTLGENRANDOM)
260 assert(s
->rtlgenrandom
);
261 if(s
->rtlgenrandom(out
, len
) == TRUE
) return len
;
264 #elif defined(KRIPTO_CRYPTGENRANDOM)
266 if(CryptGenRandom((HCRYPTPROV
)s
, len
, out
)) return len
;
278 s
->output
> KRIPTO_RESEED_OUTPUT
||
279 time(NULL
) - s
->time
> KRIPTO_RESEED_TIME
282 kripto_stream_prng(s
->stream
, iv
, 8);
284 if(seed(s
, buf
, 32)) goto err
;
286 s
->stream
= kripto_stream_recreate
292 if(!s
->stream
) goto err
;
295 kripto_stream_prng(s
->stream
, out
, len
);
300 kripto_memwipe(s
, sizeof(kripto_random
));
307 void kripto_random_destroy(kripto_random
*s
)
311 #if defined(KRIPTO_DEV_RANDOM)
315 #elif defined(KRIPTO_RTLGENRANDOM)
320 #elif defined(KRIPTO_CRYPTGENRANDOM)
322 CryptReleaseContext((HCRYPTPROV
)s
, 0);
326 kripto_stream_destroy(s
->stream
);
329 kripto_memwipe(s
, sizeof(kripto_random
));
335 #if !defined(__STDC_VERSION__) || __STDC_VERSION__ < 199901L || \
336 (defined(__cplusplus) && __cplusplus < 201103L)
338 #define LOG2(X) (log(X) / log(2))
340 #define LOG2(X) log2(X)
343 static unsigned int bitcount(const uint8_t x
)
348 for(mask
= 0x80; mask
; mask
>>= 1)
354 static unsigned int bitflips(const uint8_t prev
, const uint8_t x
)
362 for(mask
= 0x80; mask
; mask
>>= 1)
369 else if(p
&& !(x
& mask
))
379 int kripto_random_test(kripto_random
*s
)
381 uint8_t sample
[4096];
382 unsigned int count
[256];
387 double avg_null
= 0.0;
388 unsigned int bits
= 0;
389 unsigned int bit_flips
= 0;
392 unsigned int dist
[256];
393 unsigned int dist_prev
[256];
394 unsigned int dist_zero
= 0;
396 /* serial correlation */
405 if(kripto_random_gen(s
, sample
, 4096) != 4096) return 0;
407 memset(count
, 0, sizeof(unsigned int) * 256);
408 memset(dist
, 0, sizeof(unsigned int) * 256);
409 memset(dist_prev
, 0, sizeof(unsigned int) * 256);
411 for(i
= 0; i
< 4096; i
++)
415 bits
+= bitcount(sample
[i
]);
417 bit_flips
+= bitflips(prev
& 1, sample
[i
]);
420 if(prev
== sample
[i
]) dist_zero
++;
421 dist
[sample
[i
]] += 4096 - dist_prev
[sample
[i
]];
422 dist_prev
[sample
[i
]] = 4096;
424 /* serial correlation */
425 corr1
+= prev
* sample
[i
];
427 corr3
+= sample
[i
] * sample
[i
];
432 for(i
= 0; i
< 256; i
++)
439 t
= (double)count
[i
] / 4096.0;
440 if(t
) ent
-= t
* LOG2(t
);
442 /* arithmetic mean */
445 /* average null distance */
446 if(count
[i
]) avg_null
+= dist
[i
] / (double)count
[i
];
451 /* serial correlation */
452 corr2
= corr2
* corr2
;
453 corr
= (double)(4096 * corr1
- corr2
)
454 / (double)(4096 * corr3
- corr2
);
455 if(corr
< 0.0) corr
= -corr
; /* absolute */
458 if(ent
< 7.9) return 0;
459 if(avg
< 125 || avg
> 130.5) return 0;
461 if(t
< 0.49 || t
> 0.51) return 0;
462 if(chi
< 192 || chi
> 320) return 0;
463 t
= bit_flips
/ 32768.0;
464 if(t
< 0.49 || t
> 0.51) return 0;
465 if(avg_null
< 192 || avg_null
> 320) return 0;
466 if(dist_zero
/ 4096.0 > 0.1) return 0;
467 if(corr
> 0.1) return 0;