summaryrefslogtreecommitdiff
path: root/kit/secure_random.c
diff options
context:
space:
mode:
Diffstat (limited to 'kit/secure_random.c')
-rw-r--r--kit/secure_random.c45
1 files changed, 45 insertions, 0 deletions
diff --git a/kit/secure_random.c b/kit/secure_random.c
new file mode 100644
index 0000000..2565f6f
--- /dev/null
+++ b/kit/secure_random.c
@@ -0,0 +1,45 @@
+#include "secure_random.h"
+
+#include <assert.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+#if defined(_WIN32) && !defined(__CYGWIN__)
+# ifndef WIN32_LEAN_AND_MEAN
+# define WIN32_LEAN_AND_MEAN 1
+# endif
+# include <windows.h>
+# include <wincrypt.h>
+#else
+# include <unistd.h>
+#endif
+
+s32 kit_secure_random(i64 size, void *data) {
+ assert(size >= 0);
+ assert(data != NULL);
+
+ if (size <= 0 || data == NULL)
+ return KIT_ERROR_INVALID_ARGUMENT;
+
+#if defined(_WIN32) && !defined(__CYGWIN__)
+ HCRYPTPROV prov = 0;
+ if (!CryptAcquireContextW(&prov, NULL, NULL, PROV_RSA_FULL,
+ CRYPT_VERIFYCONTEXT | CRYPT_SILENT) ||
+ !CryptGenRandom(prov, (DWORD) size, (BYTE *) data) ||
+ !CryptReleaseContext(prov, 0))
+ return KIT_ERROR_RESOURCE_UNAVAILABLE;
+#else
+ FILE *f = fopen("/dev/urandom", "rb");
+
+ if (f == NULL)
+ return KIT_ERROR_RESOURCE_UNAVAILABLE;
+
+ i64 n = (i64) fread(data, 1, size, f);
+ fclose(f);
+
+ if (n != size)
+ return KIT_ERROR_RESOURCE_UNAVAILABLE;
+#endif
+
+ return KIT_OK;
+}