Jelajahi Sumber

[Crypto] Implement CryptoCore::RandomGenerator.

As a cryptographically secure random generator.

Internally it uses mbedTLS CTR-DRBG implementation which gets re-seeded
with entropy from OS::get_entropy when needed.

CryptoCore now additionally depends on `ctr_drbg.c` and `entropy.c`
thirdparty mbedtls files.
Fabio Alessandrelli 3 tahun lalu
induk
melakukan
ee7b67e135

+ 2 - 0
core/crypto/SCsub

@@ -31,6 +31,8 @@ if not has_module:
         "aes.c",
         "base64.c",
         "constant_time.c",
+        "ctr_drbg.c",
+        "entropy.c",
         "md5.c",
         "sha1.c",
         "sha256.c",

+ 43 - 0
core/crypto/crypto_core.cpp

@@ -30,12 +30,55 @@
 
 #include "crypto_core.h"
 
+#include "core/os/os.h"
+
 #include <mbedtls/aes.h>
 #include <mbedtls/base64.h>
+#include <mbedtls/ctr_drbg.h>
+#include <mbedtls/entropy.h>
 #include <mbedtls/md5.h>
 #include <mbedtls/sha1.h>
 #include <mbedtls/sha256.h>
 
+// RandomGenerator
+CryptoCore::RandomGenerator::RandomGenerator() {
+	entropy = memalloc(sizeof(mbedtls_entropy_context));
+	mbedtls_entropy_init((mbedtls_entropy_context *)entropy);
+	mbedtls_entropy_add_source((mbedtls_entropy_context *)entropy, &CryptoCore::RandomGenerator::_entropy_poll, nullptr, 256, MBEDTLS_ENTROPY_SOURCE_STRONG);
+	ctx = memalloc(sizeof(mbedtls_ctr_drbg_context));
+	mbedtls_ctr_drbg_init((mbedtls_ctr_drbg_context *)ctx);
+}
+
+CryptoCore::RandomGenerator::~RandomGenerator() {
+	mbedtls_ctr_drbg_free((mbedtls_ctr_drbg_context *)ctx);
+	memfree(ctx);
+	mbedtls_entropy_free((mbedtls_entropy_context *)entropy);
+	memfree(entropy);
+}
+
+int CryptoCore::RandomGenerator::_entropy_poll(void *p_data, unsigned char *r_buffer, size_t p_len, size_t *r_len) {
+	*r_len = 0;
+	Error err = OS::get_singleton()->get_entropy(r_buffer, p_len);
+	ERR_FAIL_COND_V(err, MBEDTLS_ERR_ENTROPY_SOURCE_FAILED);
+	*r_len = p_len;
+	return 0;
+}
+
+Error CryptoCore::RandomGenerator::init() {
+	int ret = mbedtls_ctr_drbg_seed((mbedtls_ctr_drbg_context *)ctx, mbedtls_entropy_func, (mbedtls_entropy_context *)entropy, nullptr, 0);
+	if (ret) {
+		ERR_FAIL_COND_V_MSG(ret, FAILED, " failed\n  ! mbedtls_ctr_drbg_seed returned an error" + itos(ret));
+	}
+	return OK;
+}
+
+Error CryptoCore::RandomGenerator::get_random_bytes(uint8_t *r_buffer, size_t p_bytes) {
+	ERR_FAIL_COND_V(!ctx, ERR_UNCONFIGURED);
+	int ret = mbedtls_ctr_drbg_random((mbedtls_ctr_drbg_context *)ctx, r_buffer, p_bytes);
+	ERR_FAIL_COND_V_MSG(ret, FAILED, " failed\n  ! mbedtls_ctr_drbg_seed returned an error" + itos(ret));
+	return OK;
+}
+
 // MD5
 CryptoCore::MD5Context::MD5Context() {
 	ctx = memalloc(sizeof(mbedtls_md5_context));

+ 19 - 4
core/crypto/crypto_core.h

@@ -35,9 +35,24 @@
 
 class CryptoCore {
 public:
+	class RandomGenerator {
+	private:
+		void *entropy = nullptr;
+		void *ctx = nullptr;
+
+		static int _entropy_poll(void *p_data, unsigned char *r_buffer, size_t p_len, size_t *r_len);
+
+	public:
+		RandomGenerator();
+		~RandomGenerator();
+
+		Error init();
+		Error get_random_bytes(uint8_t *r_buffer, size_t p_bytes);
+	};
+
 	class MD5Context {
 	private:
-		void *ctx = nullptr; // To include, or not to include...
+		void *ctx = nullptr;
 
 	public:
 		MD5Context();
@@ -50,7 +65,7 @@ public:
 
 	class SHA1Context {
 	private:
-		void *ctx = nullptr; // To include, or not to include...
+		void *ctx = nullptr;
 
 	public:
 		SHA1Context();
@@ -63,7 +78,7 @@ public:
 
 	class SHA256Context {
 	private:
-		void *ctx = nullptr; // To include, or not to include...
+		void *ctx = nullptr;
 
 	public:
 		SHA256Context();
@@ -76,7 +91,7 @@ public:
 
 	class AESContext {
 	private:
-		void *ctx = nullptr; // To include, or not to include...
+		void *ctx = nullptr;
 
 	public:
 		AESContext();

+ 5 - 0
thirdparty/mbedtls/include/godot_core_mbedtls_config.h

@@ -7,7 +7,12 @@
 
 #define MBEDTLS_AES_C
 #define MBEDTLS_BASE64_C
+#define MBEDTLS_CTR_DRBG_C
+#define MBEDTLS_ENTROPY_C
 #define MBEDTLS_MD5_C
 #define MBEDTLS_SHA1_C
 #define MBEDTLS_SHA256_C
 #define MBEDTLS_PLATFORM_ZEROIZE_ALT
+#define MBEDTLS_NO_DEFAULT_ENTROPY_SOURCES
+
+#include <limits.h>