summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorheinrich5991 <heinrich5991@gmail.com>2015-06-21 17:47:37 +0200
committerheinrich5991 <heinrich5991@gmail.com>2018-10-12 22:09:04 +0200
commit4389728d64318639e493b9d5c9dc52a9ab52d9c4 (patch)
treed7f9d79d6882d655d4889403e52a48455a67699e
parent6866069ce68b0afcfd224b4064a7619a4462fca7 (diff)
Add platform-independent secure random number generator
(cherry picked from commit 903878f4a2fe63cd7df2fa998129f517faf9ee2a)
-rw-r--r--bam.lua1
-rw-r--r--src/base/system.c64
-rw-r--r--src/base/system.h21
-rw-r--r--src/engine/client/client.cpp6
-rw-r--r--src/engine/server/server.cpp6
5 files changed, 98 insertions, 0 deletions
diff --git a/bam.lua b/bam.lua
index da1eb8aca..8d95eb104 100644
--- a/bam.lua
+++ b/bam.lua
@@ -188,6 +188,7 @@ function build(settings)
settings.link.libs:Add("ws2_32")
settings.link.libs:Add("ole32")
settings.link.libs:Add("shell32")
+ settings.link.libs:Add("advapi32")
end
-- compile zlib if needed
diff --git a/src/base/system.c b/src/base/system.c
index ca6400756..c5765e68a 100644
--- a/src/base/system.c
+++ b/src/base/system.c
@@ -40,6 +40,7 @@
#include <fcntl.h>
#include <direct.h>
#include <errno.h>
+ #include <wincrypt.h>
#else
#error NOT IMPLEMENTED
#endif
@@ -2029,6 +2030,69 @@ unsigned str_quickhash(const char *str)
return hash;
}
+struct SECURE_RANDOM_DATA
+{
+ int initialized;
+#if defined(CONF_FAMILY_WINDOWS)
+ HCRYPTPROV provider;
+#else
+ IOHANDLE urandom;
+#endif
+};
+
+static struct SECURE_RANDOM_DATA secure_random_data = { 0 };
+
+int secure_random_init()
+{
+ if(secure_random_data.initialized)
+ {
+ return 0;
+ }
+#if defined(CONF_FAMILY_WINDOWS)
+ if(CryptAcquireContext(&secure_random_data.provider, NULL, NULL, PROV_RSA_FULL, 0))
+ {
+ secure_random_data.initialized = 1;
+ return 0;
+ }
+ else
+ {
+ return 1;
+ }
+#else
+ secure_random_data.urandom = io_open("/dev/urandom", IOFLAG_READ);
+ if(secure_random_data.urandom)
+ {
+ secure_random_data.initialized = 1;
+ return 0;
+ }
+ else
+ {
+ return 1;
+ }
+#endif
+}
+
+void secure_random_fill(void *bytes, unsigned length)
+{
+ if(!secure_random_data.initialized)
+ {
+ dbg_msg("secure", "called secure_random_fill before secure_random_init");
+ dbg_break();
+ }
+#if defined(CONF_FAMILY_WINDOWS)
+ if(!CryptGenRandom(secure_random_data.provider, length, bytes))
+ {
+ dbg_msg("secure", "CryptGenRandom failed, last_error=%d", GetLastError());
+ dbg_break();
+ }
+#else
+ if(length != io_read(secure_random_data.urandom, bytes, length))
+ {
+ dbg_msg("secure", "io_read returned with a short read");
+ dbg_break();
+ }
+#endif
+}
#if defined(__cplusplus)
}
diff --git a/src/base/system.h b/src/base/system.h
index ec208096b..c4fb1a4c5 100644
--- a/src/base/system.h
+++ b/src/base/system.h
@@ -1294,6 +1294,27 @@ int str_utf8_encode(char *ptr, int chr);
*/
int str_utf8_check(const char *str);
+/*
+ Function: secure_random_init
+ Initializes the secure random module.
+ You *MUST* check the return value of this function.
+
+ Returns:
+ 0 - Initialization succeeded.
+ 1 - Initialization failed.
+*/
+int secure_random_init();
+
+/*
+ Function: secure_random_fill
+ Fills the buffer with the specified amount of random bytes.
+
+ Parameters:
+ bytes - Pointer to the start of the buffer.
+ length - Length of the buffer.
+*/
+void secure_random_fill(void *bytes, unsigned length);
+
#ifdef __cplusplus
}
#endif
diff --git a/src/engine/client/client.cpp b/src/engine/client/client.cpp
index d8cd41557..d64c39c39 100644
--- a/src/engine/client/client.cpp
+++ b/src/engine/client/client.cpp
@@ -2303,6 +2303,12 @@ int main(int argc, const char **argv) // ignore_convention
}
#endif
+ if(secure_random_init() != 0)
+ {
+ dbg_msg("secure", "could not initialize secure RNG");
+ return -1;
+ }
+
CClient *pClient = CreateClient();
IKernel *pKernel = IKernel::Create();
pKernel->RegisterInterface(pClient);
diff --git a/src/engine/server/server.cpp b/src/engine/server/server.cpp
index 6c459257f..14778e8f5 100644
--- a/src/engine/server/server.cpp
+++ b/src/engine/server/server.cpp
@@ -1664,6 +1664,12 @@ int main(int argc, const char **argv) // ignore_convention
}
#endif
+ if(secure_random_init() != 0)
+ {
+ dbg_msg("secure", "could not initialize secure RNG");
+ return -1;
+ }
+
CServer *pServer = CreateServer();
IKernel *pKernel = IKernel::Create();