Procházet zdrojové kódy

[OS/Crypto] Add get_entropy to OS.

Implemented via `BCryptGenRandom` on Windows.
Implemented via `getentropy` syscall when available.
Implemented via `/dev/urandom` device as a fallback.

The `/dev/urandom` fallback can be disabled via the `NO_URANDOM` build
flag.

Note: The HTML5 version relies on emscripten file system urandom
device which itself uses the Crypto API when available or the plain
old not crypto-safe `Math.random()` otherwise.

Restore get_entropy.
Fabio Alessandrelli před 3 roky
rodič
revize
6b5634b96a

+ 2 - 0
core/os/os.h

@@ -132,6 +132,8 @@ public:
 
 	virtual String get_stdin_string(bool p_block = true) = 0;
 
+	virtual Error get_entropy(uint8_t *r_buffer, int p_bytes) = 0; // Should return cryptographically-safe random bytes.
+
 	virtual PackedStringArray get_connected_midi_inputs();
 	virtual void open_midi_inputs();
 	virtual void close_midi_inputs();

+ 40 - 0
drivers/unix/os_unix.cpp

@@ -65,6 +65,21 @@
 #include <time.h>
 #include <unistd.h>
 
+#if defined(OSX_ENABLED) || (defined(__ANDROID_API__) && __ANDROID_API__ >= 28)
+// Random location for getentropy. Fitting.
+#include <sys/random.h>
+#define UNIX_GET_ENTROPY
+#elif defined(__FreeBSD__) || defined(__OpenBSD__) || (defined(__GLIBC_MINOR__) && (__GLIBC__ == 2 && __GLIBC_MINOR__ >= 26))
+// In <unistd.h>.
+// One day... (defined(_XOPEN_SOURCE) && _XOPEN_SOURCE >= 700)
+// https://publications.opengroup.org/standards/unix/c211
+#define UNIX_GET_ENTROPY
+#endif
+
+#if !defined(UNIX_GET_ENTROPY) && !defined(NO_URANDOM)
+#include <fcntl.h>
+#endif
+
 /// Clock Setup function (used by get_ticks_usec)
 static uint64_t _clock_start = 0;
 #if defined(__APPLE__)
@@ -150,6 +165,31 @@ String OS_Unix::get_stdin_string(bool p_block) {
 	return "";
 }
 
+Error OS_Unix::get_entropy(uint8_t *r_buffer, int p_bytes) {
+#if defined(UNIX_GET_ENTROPY)
+	int left = p_bytes;
+	int ofs = 0;
+	do {
+		int chunk = MIN(left, 256);
+		ERR_FAIL_COND_V(getentropy(r_buffer + ofs, chunk), FAILED);
+		left -= chunk;
+		ofs += chunk;
+	} while (left > 0);
+#elif !defined(NO_URANDOM)
+	int r = open("/dev/urandom", O_RDONLY);
+	ERR_FAIL_COND_V(r < 0, FAILED);
+	int left = p_bytes;
+	do {
+		ssize_t ret = read(r, r_buffer, p_bytes);
+		ERR_FAIL_COND_V(ret <= 0, FAILED);
+		left -= ret;
+	} while (left > 0);
+#else
+	return ERR_UNAVAILABLE;
+#endif
+	return OK;
+}
+
 String OS_Unix::get_name() const {
 	return "Unix";
 }

+ 1 - 10
drivers/unix/os_unix.h

@@ -43,7 +43,6 @@ protected:
 
 	virtual void initialize_core();
 	virtual int unix_initialize_audio(int p_audio_driver);
-	//virtual Error initialize(int p_video_driver,int p_audio_driver);
 
 	virtual void finalize_core() override;
 
@@ -54,15 +53,7 @@ public:
 
 	virtual String get_stdin_string(bool p_block) override;
 
-	//virtual void set_mouse_show(bool p_show);
-	//virtual void set_mouse_grab(bool p_grab);
-	//virtual bool is_mouse_grab_enabled() const = 0;
-	//virtual void get_mouse_position(int &x, int &y) const;
-	//virtual void set_window_title(const String& p_title);
-
-	//virtual void set_video_mode(const VideoMode& p_video_mode);
-	//virtual VideoMode get_video_mode() const;
-	//virtual void get_fullscreen_mode_list(List<VideoMode> *p_list) const;
+	virtual Error get_entropy(uint8_t *r_buffer, int p_bytes) override; // Should return cryptographycally-safe random bytes.
 
 	virtual Error open_dynamic_library(const String p_path, void *&p_library_handle, bool p_also_set_library_path = false) override;
 	virtual Error close_dynamic_library(void *p_library_handle) override;

+ 7 - 0
platform/windows/os_windows.cpp

@@ -46,6 +46,7 @@
 #include "windows_terminal_logger.h"
 
 #include <avrt.h>
+#include <bcrypt.h>
 #include <direct.h>
 #include <knownfolders.h>
 #include <process.h>
@@ -192,6 +193,12 @@ void OS_Windows::finalize_core() {
 	NetSocketPosix::cleanup();
 }
 
+Error OS_Windows::get_entropy(uint8_t *r_buffer, int p_bytes) {
+	NTSTATUS status = BCryptGenRandom(nullptr, r_buffer, p_bytes, BCRYPT_USE_SYSTEM_PREFERRED_RNG);
+	ERR_FAIL_COND_V(status, FAILED);
+	return OK;
+}
+
 Error OS_Windows::open_dynamic_library(const String p_path, void *&p_library_handle, bool p_also_set_library_path) {
 	String path = p_path.replace("/", "\\");
 

+ 2 - 0
platform/windows/os_windows.h

@@ -106,6 +106,8 @@ protected:
 public:
 	virtual void alert(const String &p_alert, const String &p_title = "ALERT!") override;
 
+	virtual Error get_entropy(uint8_t *r_buffer, int p_bytes) override;
+
 	virtual Error open_dynamic_library(const String p_path, void *&p_library_handle, bool p_also_set_library_path = false) override;
 	virtual Error close_dynamic_library(void *p_library_handle) override;
 	virtual Error get_dynamic_library_symbol_handle(void *p_library_handle, const String p_name, void *&p_symbol_handle, bool p_optional = false) override;