Skip to content

Commit 8090f47

Browse files
committed
Fallback entropy using timers
1 parent 15a4953 commit 8090f47

File tree

3 files changed

+39
-28
lines changed

3 files changed

+39
-28
lines changed

TODO

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -132,5 +132,3 @@
132132
- compare wheel_t with primes separated and possibly cached.
133133

134134
- Ensure 'secure' is secure.
135-
136-
- csrand contexts so fallback get entroy bytes can work properly.

XS.xs

Lines changed: 4 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -92,11 +92,6 @@
9292
# define FIX_MULTICALL_REFCOUNT
9393
#endif
9494

95-
#if (PERL_REVISION <= 5 && PERL_VERSION < 8)
96-
# include <time.h>
97-
# define Perl_seed(pTHX) ((U32)time(NULL))
98-
#endif
99-
10095
#ifndef CvISXSUB
10196
# define CvISXSUB(cv) CvXSUB(cv)
10297
#endif
@@ -397,13 +392,10 @@ void csrand(IN SV* seed = 0)
397392

398393
UV srand(IN UV seedval = 0)
399394
CODE:
400-
if (_XS_get_secure())
401-
croak("secure option set, manual seeding disabled");
402-
if (items == 0) {
403-
unsigned char buf[8];
404-
get_entropy_bytes(sizeof(UV), buf);
405-
memcpy( &seedval, buf, sizeof(UV));
406-
}
395+
if (_XS_get_secure())
396+
croak("secure option set, manual seeding disabled");
397+
if (items == 0)
398+
get_entropy_bytes(sizeof(UV), (unsigned char*) &seedval);
407399
csprng_srand(seedval);
408400
RETVAL = seedval;
409401
OUTPUT:

entropy.c

Lines changed: 35 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,38 @@
11
#include <stdio.h>
22
#include "entropy.h"
33

4+
/* A fallback timer entropy method that will probably never be used. */
5+
#if defined(_WIN32_WCE)
6+
static UV timer_entropy(UV bytes, unsigned char* buf) { return 0; }
7+
#else
8+
#include <time.h>
9+
static uint32_t mix32(uint32_t r0) { /* Similar to PCG 32 */
10+
uint32_t word = ((r0 >> ((r0 >> 28u) + 4u)) ^ r0) * 277803737u;
11+
return (word >> 22u) ^ word;
12+
}
13+
static uint32_t timer_mix8(uint32_t acc) {
14+
clock_t t1;
15+
uint32_t bit, a;
16+
for (bit = a = 0; bit < 8; bit++) {
17+
t1 = clock(); while (t1 == clock()) a ^= 1;
18+
acc = (acc << 1) | a;
19+
}
20+
return mix32(acc);
21+
}
22+
static UV timer_entropy(UV bytes, unsigned char* buf) {
23+
UV byte;
24+
uint32_t acc = 0;
25+
26+
for (byte = 0; byte < 4; byte++)
27+
acc = timer_mix8(acc);
28+
for (byte = 0; byte < bytes; byte++) {
29+
acc = timer_mix8( timer_mix8( acc ) );
30+
buf[byte] = (acc >> 24) & 0xFF;
31+
}
32+
return bytes;
33+
}
34+
#endif
35+
436
UV get_entropy_bytes(UV bytes, unsigned char* buf)
537
{
638
UV len = 0;
@@ -47,20 +79,9 @@ UV get_entropy_bytes(UV bytes, unsigned char* buf)
4779

4880
#endif
4981

50-
if (len == bytes) return len;
82+
/* Do a fallback method if something didn't work right. */
83+
if (len != bytes)
84+
len = timer_entropy(bytes, buf);
5185

52-
/* Something didn't work. Do a fallback method. */
53-
54-
/* TODO: Something better here.
55-
* 1. Get a decent seed, maybe some Perl_seed values
56-
* 2. Get a private CSPRNG context, seed with above
57-
* 3. Full buf from csprng
58-
* 4. destroy csprng context
59-
*/
60-
while (len < bytes) {
61-
uint32_t i, s = Perl_seed(); /* TODO Perl 5.6 */
62-
for (i = 0; i < 4 && len < bytes; i++)
63-
buf[len++] = (s >> (8*i)) & 0xFF;
64-
}
6586
return len;
6687
}

0 commit comments

Comments
 (0)