-
Notifications
You must be signed in to change notification settings - Fork 2
/
Copy pathEntropy.c
144 lines (108 loc) · 3.29 KB
/
Entropy.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
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
#include "Entropy.h"
#include "Encodings.h"
#include "Hash.h"
#include <sys/utsname.h>
#ifdef HAVE_GETENTROPY
static int GetEntropyFromGetEntropy(char *RandomBytes, int ReqLen)
{
int len=0, chunk, result;
while (len < ReqLen)
{
chunk=ReqLen-len;
if (chunk > 256) chunk=256;
//get entropy does not return length, instead it returns 0 on success
//and success means it provided the requested number of bytes
result=getentropy(RandomBytes+len, chunk);
if (result != 0) break;
len+=chunk;
}
return(len);
}
#endif
static int GetEntropyFromFile(const char *Path, char *RandomBytes, int ReqLen)
{
int len=0, result;
int fd;
fd=open(Path,O_RDONLY);
if (fd > -1)
{
while(len < ReqLen)
{
result=read(fd,RandomBytes+len,ReqLen-len);
if (result < 0) break;
len+=result;
}
close(fd);
}
return(len);
}
//desperately try and generate some random bytes if all better methods fail
static int GetEntropyEmergencyFallback(char **RandomBytes, int ReqLen)
{
clock_t ClocksStart, ClocksEnd;
char *Tempstr=NULL;
struct utsname uts;
int len=0, i;
ClocksStart=clock();
//how many clock cycles used here will depend on overall
//machine activity/performance/number of running processes
for (i=0; i < 100; i++) sleep(0);
uname(&uts);
ClocksEnd=clock();
srand(time(NULL) + ClocksEnd);
Tempstr=FormatStr(Tempstr,"%lu:%lu:%lu:%lu:%lu:%llu\n",getpid(),getuid(),rand(),ClocksStart,ClocksEnd,GetTime(TIME_MILLISECS));
//This stuff should be unique to a machine
Tempstr=CatStr(Tempstr, uts.sysname);
Tempstr=CatStr(Tempstr, uts.nodename);
Tempstr=CatStr(Tempstr, uts.machine);
Tempstr=CatStr(Tempstr, uts.release);
Tempstr=CatStr(Tempstr, uts.version);
len=HashBytes(RandomBytes, "sha512", Tempstr, StrLen(Tempstr), 0);
if (len > ReqLen) len=ReqLen;
Destroy(Tempstr);
return(len);
}
int GenerateRandomBytes(char **RetBuff, int ReqLen, int Encoding)
{
int len=0;
char *RandomBytes=NULL;
RandomBytes=SetStrLen(RandomBytes,ReqLen);
#ifdef HAVE_GETENTROPY
len=GetEntropyFromGetEntropy(RandomBytes, ReqLen);
#endif
if (len==0) len=GetEntropyFromFile("/dev/urandom", RandomBytes, ReqLen);
if (len==0) len=GetEntropyEmergencyFallback(&RandomBytes, ReqLen);
if (Encoding==0)
{
//don't use CopyStrLen, as 'RandomBytes' can include '\0'
*RetBuff=SetStrLen(*RetBuff, len);
memcpy(*RetBuff, RandomBytes, len);
}
else *RetBuff=EncodeBytes(*RetBuff, RandomBytes, len, Encoding);
Destroy(RandomBytes);
return(len);
}
char *GetRandomData(char *RetBuff, int ReqLen, char *AllowedChars)
{
char *Tempstr=NULL, *RetStr=NULL;
int i, len;
uint8_t val, max_val;
max_val=StrLen(AllowedChars);
RetStr=CopyStr(RetBuff,"");
len=GenerateRandomBytes(&Tempstr, ReqLen, 0);
for (i=0; i < len ; i++)
{
val=Tempstr[i];
RetStr=AddCharToStr(RetStr,AllowedChars[val % max_val]);
}
DestroyString(Tempstr);
return(RetStr);
}
char *GetRandomHexStr(char *RetBuff, int len)
{
return(GetRandomData(RetBuff,len,HEX_CHARS));
}
char *GetRandomAlphabetStr(char *RetBuff, int len)
{
return(GetRandomData(RetBuff,len,ALPHA_CHARS));
}