forked from toniebox-reverse-engineering/teddycloud
-
Notifications
You must be signed in to change notification settings - Fork 0
/
rand.c
104 lines (91 loc) · 2.09 KB
/
rand.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
#include <errno.h>
#ifdef WIN32
#else
#include <sys/random.h>
#include <fcntl.h>
#include <unistd.h>
#endif
#include "rng/yarrow.h"
#include "error.h"
#include "debug.h"
#include "rand.h"
YarrowContext yarrowContext;
bool rand_initialized = false;
void *rand_get_context()
{
if (!rand_initialized)
{
rand_init();
rand_initialized = true;
}
return &yarrowContext;
}
const PrngAlgo *rand_get_algo()
{
return YARROW_PRNG_ALGO;
}
int rand_get_bytes(void *buf, size_t buflen)
{
#ifndef WIN32
int urandom_fd = open("/dev/urandom", O_RDONLY);
if (urandom_fd == -1)
{
TRACE_ERROR("Failed to open /dev/urandom");
return -1;
}
ssize_t bytes_read = read(urandom_fd, buf, buflen);
if (bytes_read == -1)
{
TRACE_ERROR("Failed to read from /dev/urandom");
close(urandom_fd);
return -1;
}
close(urandom_fd);
return 0;
#else
return -1;
#endif
}
error_t rand_init()
{
uint8_t seed[32];
int ret = getrandom(seed, sizeof(seed), 0);
if (ret < 0)
{
if (errno == 38)
{
// Linux Kernel < 3.17
TRACE_WARNING("Syscall getrandom not available, fallback to /dev/urandom (%d)\r\n", errno);
int ret = rand_get_bytes(seed, sizeof(seed));
if (ret < 0)
{
TRACE_ERROR("Error: Failed to generate random data (%d)\r\n", errno);
return ERROR_FAILURE;
}
}
else
{
TRACE_ERROR("Error: Failed to generate random data (%d)\r\n", errno);
return ERROR_FAILURE;
}
}
error_t error = yarrowInit(&yarrowContext);
if (error)
{
TRACE_ERROR("Error: PRNG initialization failed (%d)\r\n", error);
return ERROR_FAILURE;
}
error = yarrowSeed(&yarrowContext, seed, sizeof(seed));
if (error)
{
TRACE_ERROR("Error: Failed to seed PRNG (%d)\r\n", error);
return error;
}
return NO_ERROR;
}
error_t rand_deinit()
{
// Release PRNG context
yarrowRelease(&yarrowContext);
return NO_ERROR;
}