util: add secure pseudorandom number generator
This commit is contained in:
@@ -15,9 +15,11 @@
|
|||||||
|
|
||||||
#define MAX_FAST_RANDOM_VALUE 0x7fff
|
#define MAX_FAST_RANDOM_VALUE 0x7fff
|
||||||
#define MAX_RANDOM_VALUE 0x7fffffffu
|
#define MAX_RANDOM_VALUE 0x7fffffffu
|
||||||
|
#define MAX_SECURE_RANDOM_VALUE 0xffffffffu
|
||||||
|
|
||||||
static const int kFastRandomShift = 15;
|
static const int kFastRandomShift = 15;
|
||||||
static const int kRandomShift = 31;
|
static const int kRandomShift = 31;
|
||||||
|
static const int kSecureRandomShift = 32;
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
extern "C" {
|
extern "C" {
|
||||||
@@ -25,6 +27,7 @@ extern "C" {
|
|||||||
|
|
||||||
unsigned int fast_random_value(void);
|
unsigned int fast_random_value(void);
|
||||||
unsigned int random_value(void);
|
unsigned int random_value(void);
|
||||||
|
unsigned int secure_random_value(void);
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
@@ -63,6 +66,21 @@ get_random()
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
T
|
||||||
|
secure_get_random()
|
||||||
|
{
|
||||||
|
size_t shift = 0;
|
||||||
|
T random = 0;
|
||||||
|
while (shift < sizeof(T) * 8) {
|
||||||
|
random |= (T)secure_random_value() << shift;
|
||||||
|
shift += kSecureRandomShift;
|
||||||
|
}
|
||||||
|
|
||||||
|
return random;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
#endif // __cplusplus
|
#endif // __cplusplus
|
||||||
|
|
||||||
#endif // KERNEL_UTIL_RANDOM_H
|
#endif // KERNEL_UTIL_RANDOM_H
|
||||||
|
|||||||
@@ -14,6 +14,59 @@
|
|||||||
|
|
||||||
static uint32 sFastLast = 0;
|
static uint32 sFastLast = 0;
|
||||||
static uint32 sLast = 0;
|
static uint32 sLast = 0;
|
||||||
|
static uint32 sSecureLast = 0;
|
||||||
|
|
||||||
|
// MD4 helper definitions, based on RFC 1320
|
||||||
|
#define F(x, y, z) (((x) & (y)) | (~(x) & (z)))
|
||||||
|
#define G(x, y, z) (((x) & (y)) | ((x) & (z)) | ((y) & (z)))
|
||||||
|
#define H(x, y, z) ((x) ^ (y) ^ (z))
|
||||||
|
|
||||||
|
#define STEP(f, a, b, c, d, xk, s) \
|
||||||
|
(a += f((b), (c), (d)) + (xk), a = (a << (s)) | (a >> (32 - (s))))
|
||||||
|
|
||||||
|
|
||||||
|
// MD4 based hash function. Simplified in order to improve performance.
|
||||||
|
static uint32
|
||||||
|
hash(uint32* data)
|
||||||
|
{
|
||||||
|
const uint32 kMD4Round2 = 0x5a827999;
|
||||||
|
const uint32 kMD4Round3 = 0x6ed9eba1;
|
||||||
|
|
||||||
|
uint32 a = 0x67452301;
|
||||||
|
uint32 b = 0xefcdab89;
|
||||||
|
uint32 c = 0x98badcfe;
|
||||||
|
uint32 d = 0x10325476;
|
||||||
|
|
||||||
|
STEP(F, a, b, c, d, data[0], 3);
|
||||||
|
STEP(F, d, a, b, c, data[1], 7);
|
||||||
|
STEP(F, c, d, a, b, data[2], 11);
|
||||||
|
STEP(F, b, c, d, a, data[3], 19);
|
||||||
|
STEP(F, a, b, c, d, data[4], 3);
|
||||||
|
STEP(F, d, a, b, c, data[5], 7);
|
||||||
|
STEP(F, c, d, a, b, data[6], 11);
|
||||||
|
STEP(F, b, c, d, a, data[7], 19);
|
||||||
|
|
||||||
|
STEP(G, a, b, c, d, data[1] + kMD4Round2, 3);
|
||||||
|
STEP(G, d, a, b, c, data[5] + kMD4Round2, 5);
|
||||||
|
STEP(G, c, d, a, b, data[6] + kMD4Round2, 9);
|
||||||
|
STEP(G, b, c, d, a, data[2] + kMD4Round2, 13);
|
||||||
|
STEP(G, a, b, c, d, data[3] + kMD4Round2, 3);
|
||||||
|
STEP(G, d, a, b, c, data[7] + kMD4Round2, 5);
|
||||||
|
STEP(G, c, d, a, b, data[4] + kMD4Round2, 9);
|
||||||
|
STEP(G, b, c, d, a, data[0] + kMD4Round2, 13);
|
||||||
|
|
||||||
|
STEP(H, a, b, c, d, data[1] + kMD4Round3, 3);
|
||||||
|
STEP(H, d, a, b, c, data[6] + kMD4Round3, 9);
|
||||||
|
STEP(H, c, d, a, b, data[5] + kMD4Round3, 11);
|
||||||
|
STEP(H, b, c, d, a, data[2] + kMD4Round3, 15);
|
||||||
|
STEP(H, a, b, c, d, data[3] + kMD4Round3, 3);
|
||||||
|
STEP(H, d, a, b, c, data[4] + kMD4Round3, 9);
|
||||||
|
STEP(H, c, d, a, b, data[7] + kMD4Round3, 11);
|
||||||
|
STEP(H, b, c, d, a, data[0] + kMD4Round3, 15);
|
||||||
|
|
||||||
|
return b;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
// In the following functions there are race conditions when many threads
|
// In the following functions there are race conditions when many threads
|
||||||
// attempt to update static variable last. However, since such conflicts
|
// attempt to update static variable last. However, since such conflicts
|
||||||
@@ -52,3 +105,24 @@ random_value()
|
|||||||
return random % (MAX_RANDOM_VALUE + 1);
|
return random % (MAX_RANDOM_VALUE + 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
unsigned int
|
||||||
|
secure_random_value()
|
||||||
|
{
|
||||||
|
static vint32 count = 0;
|
||||||
|
|
||||||
|
uint32 data[8];
|
||||||
|
data[0] = atomic_add(&count, 1);
|
||||||
|
data[1] = system_time();
|
||||||
|
data[2] = find_thread(NULL);
|
||||||
|
data[3] = smp_get_current_cpu();
|
||||||
|
data[4] = smp_get_num_cpus();
|
||||||
|
data[5] = sFastLast;
|
||||||
|
data[6] = sLast;
|
||||||
|
data[7] = sSecureLast;
|
||||||
|
|
||||||
|
uint32 random = hash(data);
|
||||||
|
sSecureLast = random;
|
||||||
|
return random;
|
||||||
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user