Skip to content

Commit

Permalink
joypad: feed user inputs into the getentropy() pool
Browse files Browse the repository at this point in the history
This makes things more random under emulators where user input is
basically the only source of non determinism.
  • Loading branch information
rasky committed Dec 31, 2024
1 parent 58be781 commit 62e7dcc
Show file tree
Hide file tree
Showing 2 changed files with 45 additions and 14 deletions.
4 changes: 4 additions & 0 deletions src/joypad.c
Original file line number Diff line number Diff line change
Expand Up @@ -469,6 +469,10 @@ static void joypad_read_callback(uint64_t *out_dwords, void *ctx)
{
memcpy((void *)joypad_read_output, out_dwords, JOYBUS_BLOCK_SIZE);
joypad_read_pending = false;

// Use some bytes from the joypad inputs to feed the entropy pool
extern void __entropy_add(uint64_t);
__entropy_add(out_dwords[0]);
}

/**
Expand Down
55 changes: 41 additions & 14 deletions src/system.c
Original file line number Diff line number Diff line change
Expand Up @@ -1334,6 +1334,44 @@ int truncate( const char *path, off_t length )
return ret;
}

/**
* @brief Add some non-deterministic data to the entropy pool.
*
* This is an internal function that can be used by libdragon libraries to add
* some non-deterministic data to the entropy pool. One example of such data
* would be the joypad inputs at any given point.
*
* The entropy pool is then used t
*
* @param k Non-deterministic data (up to 64 bits)
*/
void __entropy_add(uint64_t k) {
// This is half of MurMurHash3-128.
k *= __entropy_K[0];
k = k<<31 | k>>33;
k *= __entropy_K[1];
disable_interrupts();
__entropy_state ^= k;
__entropy_state = __entropy_state<<27 | __entropy_state>>37;
__entropy_state = __entropy_state * 5 + 0x52dce729;
enable_interrupts();
}

// Extract data from the entropy pool. This is kept here for symmetry with
// __entropy_add, but it is not an API; the API to use to extract entropy is
// #getentropy.
static uint64_t __entropy_get(void) {
disable_interrupts();
uint64_t h = __entropy_state;
enable_interrupts();
h ^= h >> 33;
h *= __entropy_K[2];
h ^= h >> 33;
h *= __entropy_K[3];
h ^= h >> 33;
return h;
}

/**
* @brief Generate an array of unpredictable random numbers
*
Expand Down Expand Up @@ -1367,24 +1405,13 @@ int getentropy(uint8_t *buf, size_t buflen)

// Mix in some hardware state / counters that are likely to be random
// at the point of sampling, especially during hardware activity.
// This is half of MurMurHash3-128.
for (int i=0; i<sizeof(entropic_regs)/sizeof(entropic_regs[0]); i+=2) {
uint64_t k = ((uint64_t)*entropic_regs[i+0] << 32) | *entropic_regs[i+1];
k *= __entropy_K[0];
k = k<<31 | k>>33;
k *= __entropy_K[1];
__entropy_state ^= k;
__entropy_state = __entropy_state<<27 | __entropy_state>>37;
__entropy_state = __entropy_state * 5 + 0x52dce729;
__entropy_add(k);
}

// Extract the current hash value
uint64_t h = __entropy_state;
h ^= h >> 33;
h *= __entropy_K[2];
h ^= h >> 33;
h *= __entropy_K[3];
h ^= h >> 33;
// Extract the current entropy value
uint64_t h = __entropy_get();

// Generate output buffer
typedef uint64_t u_uint64_t __attribute__((aligned(1)));
Expand Down

0 comments on commit 62e7dcc

Please sign in to comment.