diff options
Diffstat (limited to 'win32/sh_random.c')
-rw-r--r-- | win32/sh_random.c | 59 |
1 files changed, 59 insertions, 0 deletions
diff --git a/win32/sh_random.c b/win32/sh_random.c new file mode 100644 index 000000000..10e942e80 --- /dev/null +++ b/win32/sh_random.c | |||
@@ -0,0 +1,59 @@ | |||
1 | #include "libbb.h" | ||
2 | #include <ntsecapi.h> | ||
3 | #include "../shell/random.h" | ||
4 | |||
5 | /* | ||
6 | * Obtain a few bytes of random-ish data to initialise the generator. | ||
7 | * This is unlikely to be very robust: don't rely on it for | ||
8 | * anything that needs to be secure. | ||
9 | */ | ||
10 | static void get_entropy(uint32_t state[2]) | ||
11 | { | ||
12 | #if defined(__MINGW64_VERSION_MAJOR) && \ | ||
13 | (__MINGW64_VERSION_MAJOR >= 7 || defined(__MINGW64__)) | ||
14 | if (!RtlGenRandom(state, sizeof(state[0])*2)) | ||
15 | #endif | ||
16 | GetSystemTimeAsFileTime((FILETIME *)state); | ||
17 | |||
18 | #if 0 | ||
19 | { | ||
20 | unsigned char *p = (unsigned char *)state; | ||
21 | int j; | ||
22 | |||
23 | for (j=0; j<8; ++j) { | ||
24 | fprintf(stderr, "%02x", *p++); | ||
25 | if ((j&3) == 3) { | ||
26 | fprintf(stderr, " "); | ||
27 | } | ||
28 | } | ||
29 | fprintf(stderr, "\n"); | ||
30 | } | ||
31 | #endif | ||
32 | } | ||
33 | |||
34 | ssize_t get_random_bytes(void *buf, ssize_t count) | ||
35 | { | ||
36 | static random_t rnd; | ||
37 | ssize_t save_count = count; | ||
38 | uint32_t value; | ||
39 | unsigned char *ptr = (unsigned char *)&value; | ||
40 | |||
41 | if (buf == NULL || count < 0) { | ||
42 | errno = EINVAL; | ||
43 | return -1; | ||
44 | } | ||
45 | |||
46 | if (UNINITED_RANDOM_T(&rnd)) { | ||
47 | uint32_t state[2] = {0, 0}; | ||
48 | |||
49 | get_entropy(state); | ||
50 | INIT_RANDOM_T(&rnd, state[0] ? state[0] : 1, state[1]); | ||
51 | } | ||
52 | |||
53 | for (;count > 0; buf+=4, count-=4) { | ||
54 | value = full_random(&rnd); | ||
55 | memcpy(buf, ptr, count >= 4 ? 4 : count); | ||
56 | } | ||
57 | |||
58 | return save_count; | ||
59 | } | ||