Skip to content

Commit

Permalink
Fallback entropy using timers
Browse files Browse the repository at this point in the history
  • Loading branch information
danaj committed Sep 6, 2017
1 parent 15a4953 commit 8090f47
Show file tree
Hide file tree
Showing 3 changed files with 39 additions and 28 deletions.
2 changes: 0 additions & 2 deletions TODO
Original file line number Diff line number Diff line change
Expand Up @@ -132,5 +132,3 @@
- compare wheel_t with primes separated and possibly cached.

- Ensure 'secure' is secure.

- csrand contexts so fallback get entroy bytes can work properly.
16 changes: 4 additions & 12 deletions XS.xs
Original file line number Diff line number Diff line change
Expand Up @@ -92,11 +92,6 @@
# define FIX_MULTICALL_REFCOUNT
#endif

#if (PERL_REVISION <= 5 && PERL_VERSION < 8)
# include <time.h>
# define Perl_seed(pTHX) ((U32)time(NULL))
#endif

#ifndef CvISXSUB
# define CvISXSUB(cv) CvXSUB(cv)
#endif
Expand Down Expand Up @@ -397,13 +392,10 @@ void csrand(IN SV* seed = 0)

UV srand(IN UV seedval = 0)
CODE:
if (_XS_get_secure())
croak("secure option set, manual seeding disabled");
if (items == 0) {
unsigned char buf[8];
get_entropy_bytes(sizeof(UV), buf);
memcpy( &seedval, buf, sizeof(UV));
}
if (_XS_get_secure())
croak("secure option set, manual seeding disabled");
if (items == 0)
get_entropy_bytes(sizeof(UV), (unsigned char*) &seedval);
csprng_srand(seedval);
RETVAL = seedval;
OUTPUT:
Expand Down
49 changes: 35 additions & 14 deletions entropy.c
Original file line number Diff line number Diff line change
@@ -1,6 +1,38 @@
#include <stdio.h>
#include "entropy.h"

/* A fallback timer entropy method that will probably never be used. */
#if defined(_WIN32_WCE)
static UV timer_entropy(UV bytes, unsigned char* buf) { return 0; }
#else
#include <time.h>
static uint32_t mix32(uint32_t r0) { /* Similar to PCG 32 */
uint32_t word = ((r0 >> ((r0 >> 28u) + 4u)) ^ r0) * 277803737u;
return (word >> 22u) ^ word;
}
static uint32_t timer_mix8(uint32_t acc) {
clock_t t1;
uint32_t bit, a;
for (bit = a = 0; bit < 8; bit++) {
t1 = clock(); while (t1 == clock()) a ^= 1;
acc = (acc << 1) | a;
}
return mix32(acc);
}
static UV timer_entropy(UV bytes, unsigned char* buf) {
UV byte;
uint32_t acc = 0;

for (byte = 0; byte < 4; byte++)
acc = timer_mix8(acc);
for (byte = 0; byte < bytes; byte++) {
acc = timer_mix8( timer_mix8( acc ) );
buf[byte] = (acc >> 24) & 0xFF;
}
return bytes;
}
#endif

UV get_entropy_bytes(UV bytes, unsigned char* buf)
{
UV len = 0;
Expand Down Expand Up @@ -47,20 +79,9 @@ UV get_entropy_bytes(UV bytes, unsigned char* buf)

#endif

if (len == bytes) return len;
/* Do a fallback method if something didn't work right. */
if (len != bytes)
len = timer_entropy(bytes, buf);

/* Something didn't work. Do a fallback method. */

/* TODO: Something better here.
* 1. Get a decent seed, maybe some Perl_seed values
* 2. Get a private CSPRNG context, seed with above
* 3. Full buf from csprng
* 4. destroy csprng context
*/
while (len < bytes) {
uint32_t i, s = Perl_seed(); /* TODO Perl 5.6 */
for (i = 0; i < 4 && len < bytes; i++)
buf[len++] = (s >> (8*i)) & 0xFF;
}
return len;
}

0 comments on commit 8090f47

Please sign in to comment.